ljzsdut
GitHubToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeToggle Dark/Light/Auto modeBack to homepage

05 X Ds Api理论基础

xDS API

概述

Envoy对xDS API的管理由后端服务器实现,包括LDS、CDS、RDS、EDS、SDS、HDS(Health Discovery Service)、RLS(Rate Limit Service)和MS(Metric Service)等;所有这些API都提供了最终的一致性,并且彼此间不存在相互影响;部分更高级别的操作(例如执行服务的A/B部署)需要进行排序以防止流量被丢弃,因此,基于一个管理服务器提供多类API时还需要使用聚合发现服务(ADS)API;ADS API允许所有其他API通过来自单个管理服务器的单个gRPC双向流进行编组,从而允许对操作进行确定性排序;

Envoy提供了基于Python和Golang的SDK,可以基于这些SDK开发各种DS服务器。也可以使用开源的DS管理服务器,例如istio(pilot)。

image-20211017184144427

动态配置

Envoy支持基于文件系统或通过查询一到多个管理服务器(Management Server) 来发现各种动态资源(配置信息),这些发现服务及其相应的API联合起来称为 xDS API;

xDS API为Envoy提供了资源的动态配置机制,它也被称为Data Plane API

Envoy v2 API以Protocol Buffers的proto3语言定义,该API支持:

  • 通过gRPC进行xDS API更新的流式传输,较之v1有效降低了更新延迟(双向流通道)
  • 新的REST-JSON API,支持以YAML/JSON格式承载配置信息(轮训)
  • 也支持基于文件系统的订阅,以REST-JSON或gRPC来传输更新

总之,Envoy通过订阅,指定要监视的文件系统路径、启动gRPC流或轮询REST- JSON URL来请求资源配置信息,后两种方法涉及使用DiscoveryRequest proto载荷发送请求,这三种方法中,资源均以DiscoveryResponse proto负载的形式进行响应。

Envoy资源的配置源(ConfigSource)

Envoy支持三种配置源。

配置源(ConfigSource)用于指定资源配置数据的来源,用于为Listener、Cluster、 Route、Endpoint、Secret和VirtualHost等资源提供配置信息;

目前,Envoy支持的资源配置源只能是path、api_config_source或ads其中之一;

api_config_source或ads的数据来自于xDS API Server,即Management Server;

image-20211023170303382

文件系统订阅

文件系统订阅为Envoy提供动态配置的最简单方法,是将其放置在ConfigSource中显式指定的文件路径中。Envoy将使用inotify(Mac OS X上的kqueue)来监视文件的更改,并在更新时解析文件中的DiscoveryResponse proto。二进制protobufs,JSON,YAML和proto文本是DiscoveryResponse支持的格式,这意味着,无论采用上述何种方案,文件内容自身需要编排为DiscoveryResponse proto响应报文的格式。

提示

除了统计计数器和日志以外,没有任何机制可用于文件系统订阅ACK/NACK更新

如果发生配置更新拒绝,xDS API的最后一个有效配置将继续使用(继续使用之前的配置)

gRPC订阅

Enovy支持为每个xDS API独立指定gRPC ApiConfigSource,它指向与管理服务器对应的某上游集群,这将为每个xDS资源类型启动一个独立的双向gRPC流,可能会发送给不同的管理服务器,每个流都有自己独立维护的资源版本 ,且不存在跨资源类型的共享版本机制 ;在不使用ADS的情况下,每个资源类型可能具有不同的版本,因为Envoy API允许指向不同的EDS/RDS资源配置并对应不同的ConfigSources。

API的交付方式采用最终一致性机制 ;

下图是基于ACK的配置逻辑:

image-20211023171127642

Discovery Proto

源码文件envoy/api/envoy/api/v2/discovery.proto共定义了5种报文格式

  • DiscoveryRequest:资源发现的请求报文
  • DiscoveryResponse:资源发现的响应报文
  • DeltaDiscoveryRequest:增量格式的请求报文,用于请求单个资源
  • DeltaDiscoveryResponse:增量格式的响应报文
  • Resource:跟踪的资源

DeltaDiscoveryRequest and DeltaDiscoveryResponse are used in a new gRPC endpoint for Delta xDS.

Discovery Request Proto

image-20211023175148270

Discovery Response Proto

image-20211023175208742

Type URLs

每个xDS API都与某特定的资源类型相关,xDS API和资源类型之间是1:1 的关系,其对应关系如下:

  • LDS: envoy.api.v2.Listener
  • RDS: envoy.api.v2.RouteConfiguration
  • VHDS: envoy.api.v2.Vhds
  • CDS: envoy.api.v2.Cluster
  • EDS: envoy.api.v2.ClusterLoadAssignment
  • SDS: envoy.api.v2.Auth.Secret
  • RTDS: envoy.service.discovery.v2.Runtime

URL类型采用type.googleapis.com/<resource type>形式,例如EDS对应于 type.googleapis.com/envoy.api.v2.ClusterLoadAssignment;如前所述,Discovery Proto中的请求和响应报文都需要提供资源类型的URL;

Discovery Request 和 Response报文示例(EDS)

Discovey Request初始报文

每个流都以Envoy的DiscoveryRequest开始,指定要订阅的资源列表、与订阅的资源对应的类型URL、节点标识符和空的version_info等信息,示例EDS

version_info:
node: { id: envoy }
resource_names:
- foo
- bar
type_url: type.googleapis.com/envoy.api.v2.ClusterLoadAssignment 
response_nonce:

Discovery Response报文

基于Discovery Response报文,管理服务器可能立即回复,或者当请求的资源可用时进行 回复

version_info: X
resources:
- foo ClusterLoadAssignment proto encoding
- bar ClusterLoadAssignment proto encoding
type_url: type.googleapis.com/envoy.api.v2.ClusterLoadAssignment
nonce: A

ACK/NACK and versioning

Versioning机制为Envoy和Management Server之间提供了共享当前应用配置的概念 ,以及通过 ACK/NACK来进行配置更新的机制;

  • 管理服务器应该只向Envoy客户端发送上次DiscoveryResponse后更新过的资源;
  • Envoy则会根据自身能否接受DiscoveryResponse的情况立即回复包含ACK/NACK的DiscoveryRequest 请求;
  • 另外,在同一个流中,Envoy可能会连续发送多个DiscoveryRequest,此时,新的 DiscoveryRequests 将取代此前同一资源类型DiscoveryRequest请求,这意味着管理服务器 只需要响应给定资源类型最新的 DiscoveryRequest 请求即可;

DiscoveryRequest中的resource_names仅用作资源提示信息;

  • 诸如Cluster和Listener一类的资源类型需要使用空的resource_names,因为Envoy需要获取管理服务器对应于节点标识的所有Cluster(CDS)和Listener(LDS)资源定义,这意味着本地已经配置但响应报文中不存的资源将会被删除;
  • 而对于RouteConfigurations(RDS)和ClusterLoadAssignments(EDS)一类的资源类型, Envoy可能明确地枚举相关的资源;但是,管理服务器并不需要为每个请求的资源进行响应,而且还可能提供额外未请求的资源,resource_names只不过是一个提示;

Discovery Request and Response的工作过程

  1. 每个Envoy流以DiscoveryRequest开始,包括了列表订阅的资源、订阅资源对应的类型URL、节点标识符和空的version_info;

  2. 管理服务器可立刻或等待资源就绪时发送 DiscoveryResponse作为响应;

  3. Envoy 在处理 DiscoveryResponse 响应后,将通过Stream发送一个新的请求(ACK),请求包含 应用成功的最后一个版本号和管理服务器提供的 nonce

  4. 若本次更新已成功应用,则version_info的值设置为相应的DiscoveryResponse报文中的版 本号,例如下图中的X;

image-20211023180014980

续前,若Envoy拒绝配置更新版本X,则响应以error_detail及前一个的版本 号;而前一个版本号为空的初始版本号,则error_detail会包含有关错误的 更为详细的信息:

image-20211023180128903

续前,即便拒绝了某响应报文,后续,API更新级可能会在新的版本Y上 成功完成

image-20211023180213766

注意事项:

  • 为避免资源更新时新旧版本之间的竞争状态,MS可通过在 DiscoveryResponse报文中使用nonce(nonce是一个一次性的加密字符串),从而让Envoy用来在后续的报文中保 证DiscoveryResponse对应每个DiscoveryRequest

  • Cluster和Listener需要经过预热才能提供服务,此过程在Envoy初始化期间 以及Cluster或侦听器更新时都会发生;

    • 仅当MS提供ClusterLoadAssignment响应时(EDS),Cluster预热才完成;
    • 仅当MS提供RouteConfiguration时(RDS ),Listener预热方可完成;
    • 若MS不提供EDS/RDS的响应,则Envoy在初始化阶段将不会进行自身初始化 ,并且在提供EDS/RDS响应之前,通过CDS/LDS发送的更新将不会生效;

最终一致性

Envoy xDS API的最终一致性机制会导致更新期间的流量丢弃;通常情况下,为了避免流量丢失,更新的顺序应该遵循make before break

模型,它要求:

  • 如果存在,必须始终先推送CDS更新;
  • EDS(如果存在)必须在相应集群的CDS更新后到达;
  • LDS更新必须在相应的CDS/EDS更新后到达;
  • 与新添加的Listener相关的RDS更新必须在CDS/EDS/LDS更新后到达;
  • 与新添加的RouteConfiguration相关的VHDS更新(如果存在)必须在RDS更新 之后到达;
  • 然后,可以删除陈旧的CDS集群和相关的EDS端点(不再被引用的端点)

需要注意的是,路由不会预热,管理平面必须在推送路由更新之前确保 路由引用的集群已就位

ADS

通过前述的交互顺序保证MS资源分发时的流量丢弃是一项很有挑战的工作,而 ADS允许单一MS通过单个gRPC流提供所有的API更新

  • 配合仔细规划的更新顺序,ADS可规避更新过程中流量丢失
  • 使用 ADS,在单个流上可通过类型 URL 来进行复用多个独立的 DiscoveryRequest/DiscoveryResponse 序列

image-20211023184412903

REST-JSON轮询订阅

  • 通过REST端点进行的同步(长)轮询也可用于xDS单例API

  • 上面的消息顺序是类似的,除了没有维护到管理服务器的持久流

  • 预计在任何时间点只有一个未完成的请求,因此响应nonce在REST-JSON中是可 选的

  • proto3的JSON规范转换用于编码DiscoveryRequest和DiscoveryResponse消息。

  • ADS不适用于REST-JSON轮询

  • 当轮询周期设置为较小的值时,为了进行长轮询,则还需要避免发送 DiscoveryResponse,除非发生了对底层资源的更改