searchusermenu
  • 发布文章
  • 消息中心
点赞
收藏
评论
分享
原创

Istio xDS协议简析

2023-05-19 07:31:49
154
0

Istio简介

Istio是一个开源的服务网格,可以控制微服务之间数据的共享方式。 Istio 可以在多种环境中运行:企业本地、云托管、Kubernetes容器,或虚拟机上运行的服务等,支持多集群及混合部署。通过可插拔的策略层和配置 API可以与Prometheus、kiali等工具集成。

下面就istio的架构和特性简单介绍,通过研究istio服务xDS通信协议探究下使用。

架构

Istio架构

Istio分为两部分,数据平面和控制平面,控制平面在istio部署完成之时就存在,负责数据平面的服务发现、配置分发、证书配置等,数据平面在用户创建pod时以sidecar的方式拉起(控制平面pilot agent也一同拉起),流量通过网关路由的转发在proxy之间流转。

控制平面

version 1.5以前:服务发现Pilot、配置Galley、证书生成Citadel、可扩展性Mixer。

version 1.5及以后:Pilot、Galley、Citadel合并为Istiod,Mixer模块由于性能原因取消,新增WebAssembly,在数据平面侧支持。

控制平面主要负责管理和配置数据平面。

数据平面

数据平面由C++开发的envoy组件组成,envoy通过sidecar的方式和业务容器一起提供服务,代理拦截该服务的所有入站和出站流量,实现流量管理等特性。

envoy配置包括四个方面:listeners、routes、clusters、endpoints,而数据平面和控制平面通信的协议为xDS。

特性

Istio主要有三大特性:流量管理、安全性和可观察性。正是为了实现这些特性设计了这样的架构,通过使用CRD(Custom Resource Define)定制路由规则、安全规则等,用户使用istio在配置自己的deployment、SVC同时,配置正确的CRD资源就能够正确使用istio,Istiod实现对CRD资源的管控。通过sidecar的方式,容器可以获取到istio配置,sidecar具体实现是使用的envoy,envoy想要和管理面通信则需要使用envoy定义的xDS协议。

xDS类型

xDS提供了标准的控制面规范,通过此规范传递信息到数据面,控制平面和数据平面Envoy所使用的通信协议,目前xDS版本主要是v3版本,为一组不同数据源的服务发现协议总称。该协议是由envoy组件定义规范,istiod实现响应envoy的请求。主要包括LDS、RDS、CDS、EDS、SDS、HDS、MS等多种类型,其中LDS、RDS、CDS、EDS为流量管理常用资源类型,ADS为聚合发现服务,一次请求能够获取LDS、RDS等所有信息。

CDS(Cluster Discovery Service)

cluster发现服务,envoy调用CDS API可以动态获取集群信息,根据DiscoveryResponse调整数据平面集群的增删改。

端点:POST /v3/discovery:clusters

Envoy侧配置CDS动态资源方式:

cds_config:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

EDS(Endpoint Discovery Service)

Endpoint为上游主机标识,可以和k8s的endpoint对照理解。Envoy调用EDS API动态获取集群成员信息,通过具体的服务发现配置策略修改。

端点:POST /envoy.service.endpoint.v3.EndpointDiscoveryService/StreamEndpoints

Envoy侧配置EDS动态资源方式:

eds_config:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

LDS(Listener Discovery Service)

listener发现服务,envoy调用LDS API可以动态获取listener信息,同样可以增删改。

端点:POST /envoy.service.listener.v3.ListenerDiscoveryService/StreamListeners

Envoy侧配置LDS动态资源方式:

lds_config:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

RDS(Route Discovery Service)

Route发现服务,用于envoy调用动态获取完整的路由配置,路由配置包括HTTP header的修改等。

端点:POST /envoy.service.route.v3.RouteDiscoveryService/StreamRoutes

Envoy侧配置RDS动态资源方式:

route_config_name: some_route_name

config_source:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

xDS一些特性

订阅方式

放置在指定configsource路径下可配置动态配置,envoy使用inotify监听文件更改,DiscoveryResponse支持Binary protobufs、JSON、YAML、text等

xDS变体

支持的传输协议变体包括:

  1. Basic xDS:每种资源类型使用独立的gRPC流;
  2. ncremental xDS:每种资源类型增量的使用独立的gRPC流;
  3. ADS:所有资源的聚合gRPC流;
  4. Incremental ADS:增量使用所有资源的聚合gRPC流。

对应的变体提供相应的xDS资源类型。

pilot响应过程

Pilot 实现

Pilot是控制平面和envoy主要通信的组件,包括Discover Service和Agent两部分,其中agent运行在容器pod sidecar内,但是也是属于控制平面的一部分,这两部分共同构成pilot。

Discover Service获取服务信息、流量规则等,envoy通过xDS获取到配置信息修改。

Agent负责envoy的配置管理、生命周期管理,同样也是通过xDS和agent交互。

Discover Service初始化

Discover Service初始化流程图

这是最新1.12.1版本Discover Service关于gRPC的初始化流程图。与旧版本不一样的点:

  1. 使用了envoy V3版本api;
  2. 通过调用discovery.RegisterAggregatedDiscoveryServiceServer新增了ADS相关的初始化工作。

 

func NewServer(args *PilotArgs, initFuncs ...func(*Server)) (*Server, error) {

…

s.XDSServer = xds.NewDiscoveryServer(e, args.Plugins, args.PodName, args.Namespace, args.RegistryOptions.KubeOptions.ClusterAliases)

…

s.initDiscoveryService(args)

…

}

NewServer方法首先配置DiscoveryServer实例,DiscoveryServer实例是Pilot对Envoy的xds API的gRPC实现,然后调用initDiscoveryService初始化initDiscoveryService,initDiscoveryService调用initGrpcServer执行gRPC的初始化工作。

func (s *Server) initGrpcServer(options *istiokeepalive.Options) {

       interceptors := []grpc.UnaryServerInterceptor{

              // setup server prometheus monitoring (as final interceptor in chain)

              prometheus.UnaryServerInterceptor,

       }

       grpcOptions := istiogrpc.ServerOptions(options, interceptors...)

       s.grpcServer = grpc.NewServer(grpcOptions...)

       s.XDSServer.Register(s.grpcServer)

       reflection.Register(s.grpcServer)

}

initGrpcServer则执行gRPC具体的初始化工作,包括初始化CDS、EDS等,同样包括ADS。执行完初始化的动作之后就执行启动的方法。

gRPC连接

由前文可知istio的xDS主要是通过调用gRPC的方式与envoy交互。Envoy发送DiscoveryRequest 请求,pilot获取请求返回DiscoveryResponse ,envoy读取信息并动态加载配置。

DiscoveryRequest 与DiscoveryResponse 

DiscoveryRequest是envoy节点请求istiod时版本化资源定义,结构如下:

type DiscoveryRequest struct {

       state         protoimpl.MessageState

       sizeCache     protoimpl.SizeCache

       unknownFields protoimpl.UnknownFields

// 请求消息中提供的 version_info 使用最近成功处理的响应接收的version_info

       VersionInfo string `protobuf:"bytes,1,opt,name=version_info,json=versionInfo,proto3" json:"version_info,omitempty"`

// 发起请求的节点信息,如位置信息等元数据

       Node *v3.Node `protobuf:"bytes,2,opt,name=node,proto3" json:"node,omitempty"`

// 请求的资源名称列表,为空表示订阅所有的资源

       ResourceNames []string `protobuf:"bytes,3,rep,name=resource_names,json=resourceNames,proto3" json:"resource_names,omitempty"`

// 指的是资源的类型,对应的是xDS的端点值

       TypeUrl string `protobuf:"bytes,4,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`

       ResponseNonce string `protobuf:"bytes,5,opt,name=response_nonce,json=responseNonce,proto3" json:"response_nonce,omitempty"`

       ErrorDetail *status.Status `protobuf:"bytes,6,opt,name=error_detail,json=errorDetail,proto3" json:"error_detail,omitempty"`

}

DiscoveryResponse则是对envoy发起的请求响应,结构如下:

type DiscoveryResponse struct {

       state         protoimpl.MessageState

       sizeCache     protoimpl.SizeCache

       unknownFields protoimpl.UnknownFields

//对应DiscoveryRequest的VersionInfo,相应的版本号

       VersionInfo string `protobuf:"bytes,1,opt,name=version_info,json=versionInfo,proto3" json:"version_info,omitempty"`

// pilot返回envoy具体的资源,已序列化

       Resources []*any.Any `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"`

       Canary bool `protobuf:"varint,3,opt,name=canary,proto3" json:"canary,omitempty"`

//对应DiscoveryRequest的TypeUrl

       TypeUrl string `protobuf:"bytes,4,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`

//定义了随后DiscoveryRequest中明确 ACK 特定 DiscoveryResponse 的方法

       Nonce string `protobuf:"bytes,5,opt,name=nonce,proto3" json:"nonce,omitempty"`

       ControlPlane *v3.ControlPlane `protobuf:"bytes,6,opt,name=control_plane,json=controlPlane,proto3" json:"control_plane,omitempty"`

}

通过约定的请求和响应结构定义了如何在控制平面和envoy之间使用xDS协议,是使用gRPC流或者轮询方式的进一步封装。

最终一致性

相对于事务类型数据库强一致性,istio是实现的最终一致性。最终一致性指的是istio最终的状态会能够达到预期,但是更新过程中并不能保证。这样设计可以提高性能,简化系统。但同时也会带来流量黑洞的问题,如果系统对可用性要求很高,则设计更新策略的时候需要遵循make before break原则。

make before break原则

istio的make before break模型简单的来说就是主要是对更新顺序的设定:CDS,EDS,LDS,RDS,VHDS,如果没有则顺延更新后面的配置,更新完成之后删除旧的CDS、EDS端点。

为了让用户能够比较简单的实现高可用的最终一致性,envoy提供了聚合发现服务(ADS API)的能力。这个API是单个gRPC流的多路复用,提供了一个严格的排序方式实现有序更新,提高可用性,他的更新序列如下:

ADS更新序列

用户可以根据自己的使用场景来选择配置的方式。

总结

目前Service Mesh最为活跃的Istio项目,是采取控制面 + xDS + envoy 的模式,控制面对接各种服务注册中心,然后再根据用户配置的转发规则,转换为xDS资源,通过gRPC流下发到Envoy中,完成容器的管理工作。

参考

Embracing eventual consistency in SoA networking

xDS REST and gRPC protocol

生态扩展-标准-xDS

Istio流量管理实现机制深度解析

0条评论
0 / 1000
田红艳
3文章数
1粉丝数
田红艳
3 文章 | 1 粉丝
田红艳
3文章数
1粉丝数
田红艳
3 文章 | 1 粉丝
原创

Istio xDS协议简析

2023-05-19 07:31:49
154
0

Istio简介

Istio是一个开源的服务网格,可以控制微服务之间数据的共享方式。 Istio 可以在多种环境中运行:企业本地、云托管、Kubernetes容器,或虚拟机上运行的服务等,支持多集群及混合部署。通过可插拔的策略层和配置 API可以与Prometheus、kiali等工具集成。

下面就istio的架构和特性简单介绍,通过研究istio服务xDS通信协议探究下使用。

架构

Istio架构

Istio分为两部分,数据平面和控制平面,控制平面在istio部署完成之时就存在,负责数据平面的服务发现、配置分发、证书配置等,数据平面在用户创建pod时以sidecar的方式拉起(控制平面pilot agent也一同拉起),流量通过网关路由的转发在proxy之间流转。

控制平面

version 1.5以前:服务发现Pilot、配置Galley、证书生成Citadel、可扩展性Mixer。

version 1.5及以后:Pilot、Galley、Citadel合并为Istiod,Mixer模块由于性能原因取消,新增WebAssembly,在数据平面侧支持。

控制平面主要负责管理和配置数据平面。

数据平面

数据平面由C++开发的envoy组件组成,envoy通过sidecar的方式和业务容器一起提供服务,代理拦截该服务的所有入站和出站流量,实现流量管理等特性。

envoy配置包括四个方面:listeners、routes、clusters、endpoints,而数据平面和控制平面通信的协议为xDS。

特性

Istio主要有三大特性:流量管理、安全性和可观察性。正是为了实现这些特性设计了这样的架构,通过使用CRD(Custom Resource Define)定制路由规则、安全规则等,用户使用istio在配置自己的deployment、SVC同时,配置正确的CRD资源就能够正确使用istio,Istiod实现对CRD资源的管控。通过sidecar的方式,容器可以获取到istio配置,sidecar具体实现是使用的envoy,envoy想要和管理面通信则需要使用envoy定义的xDS协议。

xDS类型

xDS提供了标准的控制面规范,通过此规范传递信息到数据面,控制平面和数据平面Envoy所使用的通信协议,目前xDS版本主要是v3版本,为一组不同数据源的服务发现协议总称。该协议是由envoy组件定义规范,istiod实现响应envoy的请求。主要包括LDS、RDS、CDS、EDS、SDS、HDS、MS等多种类型,其中LDS、RDS、CDS、EDS为流量管理常用资源类型,ADS为聚合发现服务,一次请求能够获取LDS、RDS等所有信息。

CDS(Cluster Discovery Service)

cluster发现服务,envoy调用CDS API可以动态获取集群信息,根据DiscoveryResponse调整数据平面集群的增删改。

端点:POST /v3/discovery:clusters

Envoy侧配置CDS动态资源方式:

cds_config:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

EDS(Endpoint Discovery Service)

Endpoint为上游主机标识,可以和k8s的endpoint对照理解。Envoy调用EDS API动态获取集群成员信息,通过具体的服务发现配置策略修改。

端点:POST /envoy.service.endpoint.v3.EndpointDiscoveryService/StreamEndpoints

Envoy侧配置EDS动态资源方式:

eds_config:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

LDS(Listener Discovery Service)

listener发现服务,envoy调用LDS API可以动态获取listener信息,同样可以增删改。

端点:POST /envoy.service.listener.v3.ListenerDiscoveryService/StreamListeners

Envoy侧配置LDS动态资源方式:

lds_config:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

RDS(Route Discovery Service)

Route发现服务,用于envoy调用动态获取完整的路由配置,路由配置包括HTTP header的修改等。

端点:POST /envoy.service.route.v3.RouteDiscoveryService/StreamRoutes

Envoy侧配置RDS动态资源方式:

route_config_name: some_route_name

config_source:

  resource_api_version: V3

  api_config_source:

    api_type: GRPC

    transport_api_version: V3

    grpc_services:

      envoy_grpc:

        cluster_name: some_xds_cluster

xDS一些特性

订阅方式

放置在指定configsource路径下可配置动态配置,envoy使用inotify监听文件更改,DiscoveryResponse支持Binary protobufs、JSON、YAML、text等

xDS变体

支持的传输协议变体包括:

  1. Basic xDS:每种资源类型使用独立的gRPC流;
  2. ncremental xDS:每种资源类型增量的使用独立的gRPC流;
  3. ADS:所有资源的聚合gRPC流;
  4. Incremental ADS:增量使用所有资源的聚合gRPC流。

对应的变体提供相应的xDS资源类型。

pilot响应过程

Pilot 实现

Pilot是控制平面和envoy主要通信的组件,包括Discover Service和Agent两部分,其中agent运行在容器pod sidecar内,但是也是属于控制平面的一部分,这两部分共同构成pilot。

Discover Service获取服务信息、流量规则等,envoy通过xDS获取到配置信息修改。

Agent负责envoy的配置管理、生命周期管理,同样也是通过xDS和agent交互。

Discover Service初始化

Discover Service初始化流程图

这是最新1.12.1版本Discover Service关于gRPC的初始化流程图。与旧版本不一样的点:

  1. 使用了envoy V3版本api;
  2. 通过调用discovery.RegisterAggregatedDiscoveryServiceServer新增了ADS相关的初始化工作。

 

func NewServer(args *PilotArgs, initFuncs ...func(*Server)) (*Server, error) {

…

s.XDSServer = xds.NewDiscoveryServer(e, args.Plugins, args.PodName, args.Namespace, args.RegistryOptions.KubeOptions.ClusterAliases)

…

s.initDiscoveryService(args)

…

}

NewServer方法首先配置DiscoveryServer实例,DiscoveryServer实例是Pilot对Envoy的xds API的gRPC实现,然后调用initDiscoveryService初始化initDiscoveryService,initDiscoveryService调用initGrpcServer执行gRPC的初始化工作。

func (s *Server) initGrpcServer(options *istiokeepalive.Options) {

       interceptors := []grpc.UnaryServerInterceptor{

              // setup server prometheus monitoring (as final interceptor in chain)

              prometheus.UnaryServerInterceptor,

       }

       grpcOptions := istiogrpc.ServerOptions(options, interceptors...)

       s.grpcServer = grpc.NewServer(grpcOptions...)

       s.XDSServer.Register(s.grpcServer)

       reflection.Register(s.grpcServer)

}

initGrpcServer则执行gRPC具体的初始化工作,包括初始化CDS、EDS等,同样包括ADS。执行完初始化的动作之后就执行启动的方法。

gRPC连接

由前文可知istio的xDS主要是通过调用gRPC的方式与envoy交互。Envoy发送DiscoveryRequest 请求,pilot获取请求返回DiscoveryResponse ,envoy读取信息并动态加载配置。

DiscoveryRequest 与DiscoveryResponse 

DiscoveryRequest是envoy节点请求istiod时版本化资源定义,结构如下:

type DiscoveryRequest struct {

       state         protoimpl.MessageState

       sizeCache     protoimpl.SizeCache

       unknownFields protoimpl.UnknownFields

// 请求消息中提供的 version_info 使用最近成功处理的响应接收的version_info

       VersionInfo string `protobuf:"bytes,1,opt,name=version_info,json=versionInfo,proto3" json:"version_info,omitempty"`

// 发起请求的节点信息,如位置信息等元数据

       Node *v3.Node `protobuf:"bytes,2,opt,name=node,proto3" json:"node,omitempty"`

// 请求的资源名称列表,为空表示订阅所有的资源

       ResourceNames []string `protobuf:"bytes,3,rep,name=resource_names,json=resourceNames,proto3" json:"resource_names,omitempty"`

// 指的是资源的类型,对应的是xDS的端点值

       TypeUrl string `protobuf:"bytes,4,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`

       ResponseNonce string `protobuf:"bytes,5,opt,name=response_nonce,json=responseNonce,proto3" json:"response_nonce,omitempty"`

       ErrorDetail *status.Status `protobuf:"bytes,6,opt,name=error_detail,json=errorDetail,proto3" json:"error_detail,omitempty"`

}

DiscoveryResponse则是对envoy发起的请求响应,结构如下:

type DiscoveryResponse struct {

       state         protoimpl.MessageState

       sizeCache     protoimpl.SizeCache

       unknownFields protoimpl.UnknownFields

//对应DiscoveryRequest的VersionInfo,相应的版本号

       VersionInfo string `protobuf:"bytes,1,opt,name=version_info,json=versionInfo,proto3" json:"version_info,omitempty"`

// pilot返回envoy具体的资源,已序列化

       Resources []*any.Any `protobuf:"bytes,2,rep,name=resources,proto3" json:"resources,omitempty"`

       Canary bool `protobuf:"varint,3,opt,name=canary,proto3" json:"canary,omitempty"`

//对应DiscoveryRequest的TypeUrl

       TypeUrl string `protobuf:"bytes,4,opt,name=type_url,json=typeUrl,proto3" json:"type_url,omitempty"`

//定义了随后DiscoveryRequest中明确 ACK 特定 DiscoveryResponse 的方法

       Nonce string `protobuf:"bytes,5,opt,name=nonce,proto3" json:"nonce,omitempty"`

       ControlPlane *v3.ControlPlane `protobuf:"bytes,6,opt,name=control_plane,json=controlPlane,proto3" json:"control_plane,omitempty"`

}

通过约定的请求和响应结构定义了如何在控制平面和envoy之间使用xDS协议,是使用gRPC流或者轮询方式的进一步封装。

最终一致性

相对于事务类型数据库强一致性,istio是实现的最终一致性。最终一致性指的是istio最终的状态会能够达到预期,但是更新过程中并不能保证。这样设计可以提高性能,简化系统。但同时也会带来流量黑洞的问题,如果系统对可用性要求很高,则设计更新策略的时候需要遵循make before break原则。

make before break原则

istio的make before break模型简单的来说就是主要是对更新顺序的设定:CDS,EDS,LDS,RDS,VHDS,如果没有则顺延更新后面的配置,更新完成之后删除旧的CDS、EDS端点。

为了让用户能够比较简单的实现高可用的最终一致性,envoy提供了聚合发现服务(ADS API)的能力。这个API是单个gRPC流的多路复用,提供了一个严格的排序方式实现有序更新,提高可用性,他的更新序列如下:

ADS更新序列

用户可以根据自己的使用场景来选择配置的方式。

总结

目前Service Mesh最为活跃的Istio项目,是采取控制面 + xDS + envoy 的模式,控制面对接各种服务注册中心,然后再根据用户配置的转发规则,转换为xDS资源,通过gRPC流下发到Envoy中,完成容器的管理工作。

参考

Embracing eventual consistency in SoA networking

xDS REST and gRPC protocol

生态扩展-标准-xDS

Istio流量管理实现机制深度解析

文章来自个人专栏
云原生
3 文章 | 1 订阅
0条评论
0 / 1000
请输入你的评论
1
1