从Envoy xDS演进到UDPA

备注:节选并翻译自设计文档 Evolving Envoy xDS to the UDPA

概述

根据UDPA-WG章程,我们设想了L4/L7数据平面配置的行业标准,类似于SDN中L2/L3/L4的OpenFlow所扮演的角色。 为此,我们将从Envoy的v2 XDS API开始,并在几个major版本上发展通用数据平面API(UDPA),该API分离出共同的关注点,并将Envoy的详细信息作为许多代理/ LB实现专长之一。 目的是保持供应商中立,同时认识到我们需要走渐进式发展之路。 净收益将为控制平面和代理/LB供应商带来更大的生态系统,并通过不必要的差异化APIS消除不必要的障碍。 本文档用作该过程的设计文档。

Data plan API

了解数据平面负载平衡器(data plane load balancer/DPLB)API的概况很有帮助。 这有助于确保供应商中立,并知道哪些API功能需要在UDPA中表示。

我们首先在下面列出承诺采用UDPA的DPLB的数据平面API。

随着我们逐步发展到xDS API的v3+,这些API有望实现UDPA覆盖,并且我们正在与这些项目中的团队成员积极合作,以确保考虑到这些项目的需求。

虽然有两个项目是UDPA的起点,但为了满足其他DPLB项目的需求,我们理想地希望在其他社区中拥有合作伙伴,例如HAProxy和NGINX,以确保我们正确反映了他们的项目要求。 在认识到每个项目可能都有现成的配置API并计划保留它们的同时,我们希望使UDPA能够表达全套DPLB API,为其他社区采用它提供一条途径。 以下是我们计划考虑的一些其他已知DPLB API。

Please add more examples here!

尽管我们在任何UDPA设计工作中都会考虑上述API集,但是一旦DPLB作为记录计划提交UDPA支持并且DPLB提供了技术帮助,我们将努力确保可以保证DPLB API得到支持, 例如 符合性测试和客户端API实施。

原则

  • UDPA是从表达性和行业采用的Envoy xDS API的增量演变而来。我们相信,经过验证的实施和现有的生态系统,很有可能获得最大的成功机会。

  • 将使用 proto3 中对API进行规范描述,并在 protoc-gen-validate-annotation 中添加其他的schema约束。其他API表示形式也是可能的,例如通过机械JSON映射。 API对象的文本表示形式将支持JSON,YAML和文本原型。

  • 该API将包含两个组件;数据模型和API传输。原则上将是独立的。数据模型将描述各种DPLB特定问题,例如如何将监听器或路由配置描述为proto3消息。 API transport 负责在客户端和管理服务器之间传输API对象。我们将独立定义数据模型和API transport,旨在避免不必要的交叉耦合。

  • UDPA将支持一系列一致性模型,从最终(eventual)到线性的(sequential)。要认识到UDPA和DPLB的不同应用需要不同的模型来保持一致性。例如,某些服务运营商可能会遇到一段时间的配置不一致,而新的更新会通过“make-before-break”更新来传播或在更高级别上处理一致性,而某些服务提供商可能会要求流量永远不会遭受任何意料之外的不一致。

  • 核心API将遵循pub-sub,遵循现有的API(例如LDS或EDS)的xDS模型。这些API将有gRPC bidi 流和 REST-JSON 的变体。此外,我们将提供仅用于gRPC流式传输的用于负载和健康状况报告的流式传输API,例如HDS和LRS。根据需要,我们将考虑可以从原始RPC定义机械派生的其他流RPC系统。

  • UDPA主要用于机器生成和使用。期望管理服务器负责将更高级别的配置概念映射到API响应。类似地,可以通过模板工具等来生成静态配置片段。用于生成UDPA配置的高级API和工具不在UDPA定义的范围内。

  • 我们将遵循xDS稳定API的建议,以确保在前进的过程中不会破坏Envoy xDS和UDPA的任何现有用户。 API系列的下一个主要版本,即 version3,将反映UDPA的第一版。

  • 我们将遵循云API最佳实践设计模式; https://cloud.google.com/apis/design/design_patterns

  • 资源在正确的配置状态下应该是可组合的。即集群X的存在不应影响集群Y,反之亦然。例外情况是错误条件,例如尝试绑定到同一端口的监听器。

除上述内容外,我们认为v2 xDS API的所有方面都将继续进行审查,下面我们征求有关可以与Envoy细节脱钩并朝着供应商中立的API进行更改的意见。

过程

  • 2019年第三季度将是一个咨询和设计阶段,在此期间我们将确定UDPA与现有API分开的总体结构。 我们将在 https://github.com/cncf/udpa-wg 的v1alpha命名空间中创建候选UDPA结构,同时在 https://github.com/envoyproxy/envoy/tree/master/ 上发展v3alpha xDS API。 UDPA树将成为Envoy API构建的依赖项。 udpa-wg@lists.cncf.io邮件列表和UDPA-WG会议将作为讨论更改的论坛。

  • UDPA的任何更改都需要从致力于UDPA支持的项目中注销。 此外,我们将征询其他UDPA-WG成员的意见并采取行动。

  • 在第三季度末,我们将完成 v1 UDPA和v3 Envoy API。 v2alpha UDPA和4alpha Envoy API将开放用于进一步的长期增量演进,而v2 UDPA和v4 Envoy API将在2020年第三季度末完成。我们希望到此为止至少支持3个DPLB项目,今天已确认2个。

设计

从Envoy xDS迁移到UDPA时,下面提供了一些关键的设计注意事项。

资料模型

通用化Envoy xDS要求更改其数据模型以将Envoy细节与常规配置分开。例如,在考虑RouteConfiguration对象时,Envoy支持许多不同的匹配条件,包括前缀和正则表达式匹配。在此要解决的合理问题将是:

  • 所有DPLB都支持正则表达式吗?
  • 需要支持哪些正则表达式语法?

从根本上说,数据模型中存在一些对实现性能有直接影响的假设,例如,线性RouteConfiguration的选择。可以想象,不同的DPLB(包括Envoy本身)可能希望支持替代的路由配置数据模型,同时仍广泛支持UDPA。 UDPA可能需要提供一种工具,以支持自定义路由配置替代方案,官方路由配置对象的专业化以及UDPA支持将实验性替代方案提升为官方支持状态。

UDPA数据模型中的关键对象将是(TODO:这只是Envoy的一些转储):

  • Listener
  • RouteConfiguration
  • Cluster
  • ClusterLoadAssignment
  • Secret …

API transport

根据我们在v2 Envoy xDS API transport方面的经验,以下几点是相关的。 这些在很大程度上与上述数据模型的细节解耦。

  • xDS有效地描述了 pub-sub 模型:

    • 大多数API有效遵循pub-sub模式,例如 CDS/LDS/RDS/EDS/SDS。在这些API中,管理服务器具有一组特定版本的给定类型的命名资源。 DPLB客户端有兴趣订阅命名资源或了解给定类型的所有命名资源。当在管理服务器上产生这些资源的较新版本时,DPLB会接收更新并将其接受或拒绝通知给管理服务器。

    • 与纯发布订阅不同,DPLB可以接受或拒绝从管理服务器传递的资源。 DPLB和管理服务器都需要对已应用于DPLB的给定资源的当前版本有准确的了解。

    • DPLB还是信息的产生者,例如在诸如LRS或HDS之类的API中。如今,仅在不遵循xDS中的标准发布-订阅模型的自定义bidi gRPC流上支持此功能。

    • 根据资源类型,xDS对于pub-sub具有不同的语义,这在推理上非常复杂。例如,集群使用通配符进行订阅,而ClusterLoadAssignments由DPLB明确订阅。热身行为根据资源类型(例如, LDS在RDS上变暖,而CDS在EDS上变暖,但是RDS和CDS之间没有连接。这里的另一个示例是可以通过CDS / LDS删除资源,但不能通过RDS / EDS删除资源。

    • xDS将ACK-NACK与发现请求结合在一起。起初,当协议很简单时这是有道理的,但是在添加了增量xDS和预热后,这变得非常复杂。

  • 数据模型和API端点是独立的:

    • 最初,我们将资源类型(即数据模型)和API端点紧密耦合,例如 CDS,很明显,能够将这些问题解耦并在不同的API端点(即ADS)上移动给定类型的资源非常有用。
  • DPLB对原子性,更新顺序和更新的版本具有复杂的要求:

    • 通常,一旦满足其他依赖关系,DPLB只会有效地使用命名资源。例如。在发送并接受依赖于X的监听器M之前,RouteConfiguration X不可使用。

    • 将命名资源更新到新版本时,确保一致性会非常复杂。最初,xDS API被设想为保持最终一致。考虑:

      • 用于版本0的foo.com的RouteConfiguration X指向版本0的集群M。如果X的版本1将foo.com指向集群N,则必须确保将集群N在X的版本1之前交付给DPLB,以避免将流量中断。

      • 具有ClusterLoadAssignment M的集群X。如果X的版本0和M的版本0都不假定没有TLS(没有TLS上下文和端口80),并且X的版本1和M的版本1都假定TLS(TLS上下文和端口443)。为了避免掉流量,需要进行仔细的排序和群集预热。今天xDS还没有解决其他复杂问题,例如如果X的版本1被拒绝,M的版本1也应该被拒绝吗?

    • 创建ADS,通过允许管理服务器显式地排序资源和版本更新的顺序,来简化更新一致性。

  • 大规模和支持的用例范围需要增量的API更新:

    • 最初,v2 xDS对于任何资源类型都是世界一流的。随着资源扩展到O(10k +),这变得不可持续。

    • 向v2 xDS添加了增量xDS,以在添加资源时支持有效的线路更新,并为 serverless 等应用支持延迟加载资源。例如。仅在首次访问foo.com时才获取foo.com的RouteConfiguration。

  • 资源类型的粒度非常重要:

    • 为了支持增量更新和大规模,我们在v2 xDS中引入了新的间接对象,例如 VHDS 和 SRDS 。这增加了API端点和资源类型的数量,以及最长更新路径上潜在的RPC的数量。

    • 如果您无法命名资源,则不能延迟或增量地更新它。

    • 在考虑联邦以及控制平面中不同实体如何管理资源时,粒度也会产生影响。

  • 资源更新很棘手:

    • 失败很复杂:

      • Envoy v2 xDS在更新粒度上具有ACK / NACK。 我们已经提出了许多要求来使这种资源更加精细。
      • 除了资源粒度失败之外,人们还普遍希望看到错误消息和可以通过机器理解的消息。

      • 与资源高度相关的是资源更新失败的影响以及更新操作的幂等性。

    • 成功更新的行为很复杂:

      • 一些资源依赖于其他资源,需要热身; DPLB可能直到其依赖资源到达并初始化了无限制的时间之后,才能知道资源更新的成功。
  • 粘性非常有用:

    • 事实证明,由控制平面服务的单个实例交付所有xDS更新的功能非常有用,尤其是在确保高度一致性时。
    • 能够将xDS API(例如EDS及其相关的反馈LRS)耦合到同一服务上,也简化了控制循环。
    • 今天,粘性在很大程度上是通过ADS和gRPC流亲和力实现的。

理想情况下,UDPA API传输借鉴了上述经验,提高了一致性和清晰度,同时在形式上没有太大的差异以允许现有的v2 xDS用户采用。

联邦

UDPA应该将对配置资源联邦的支持作为目标。用例是:

  • 多个控制平面(例如内部,公共云)管理单个平面网格。每个控制平面对一组服务都是权威的。

  • 多个网格,每个网格都有自己的权威控制平面。网格通过 ingress 网关桥接,另一个网格中的服务解析为网关 IP: port。

  • 控制平面故障转移以提高可用性。主控制平面存在于内部或公共云中,但是如果主控制平面不可用或发生分区,DPLB可能会故障转移到本地控制平面。要使控制平面同步,就需要完全联合,包括端点的注册。当主控制平面恢复或解决网络问题后,故障转移控制平面会将获取的状态同步到主控制平面。一旦主控制平面完全更新,它就会声明自己是健康的,并重新连接到它。

  • 服务故障转移。尽管通常由于故障转移或容量紧缩而可能在本地提供服务,但可能有必要使用由不同控制平面管理的端点。这意味着服务通常由主控制平面管理,但是在故障转移期间,其负载平衡和运行状况由辅助控制平面提供。

  • 选定控制平面进行联邦的功能。例如。允许仅通过某些控制平面来管理某些服务端点的负载平衡权重或运行状况。这允许将控制责任转移到托管云服务,并且在负载测试等应用程序中也很有用。

上述用例可能需要将DPLB连接到单个管理服务器或多个管理服务器。例如,DPLB可能仅需要通过其本地控制平面接收联邦配置,并且还可能需要从辅助控制平面接收配置替代。

下一代API注意事项

  • 术语,例如cluster, downstream, upstream, service等。今天我们对Envoy的术语感到满意吗?这只是potatah土豆,还是还有更多基本问题?

  • 在端点级别与集群级别之间可以表达什么?

  • 在路由与集群级别之间可以表达什么?

  • 我们是否有正确的抽象集,例如额外的间接对集群或后端有帮助,例如后端组,一流的加权群集等。

  • Envoy是特定于v2 xDS的哪个子集?

  • 如何为每个API中的任何DPLB提供不透明的可扩展性和可移植性?

  • 除了REST-JSON和gRPC之外,我们是否需要支持任何API使用?

  • xDS联邦:

  • 针对CDS的自定义内部区域LB策略

  • 增量xDS完整性和现场测试

  • xDS和Istio MCP融合

  • 我们可以在pub-sub中实现负载报告和运行状况检查API的更多对称性吗?

  • 如何在v1和v2上划分UDPA更改?我们可以在v1中加入哪些基本功能以使其在未来3个月内变得现实并且仍然有用?

  • 我们如何在管理服务器的复杂性之间取得平衡,例如 需要具备所有支持DPLB的知识以及针对所有这些的API生成,以及API的表达能力和支持跨项目的全套DLPB功能的能力。 例如。 以超时行为为例,每个DPLB可能都有一些稍微不同的描述超时的古怪方式。

  • 请在此处添加更多注意事项!

  • 使每个UDPA API(LDS,RDS,CDS等)都有自己的请求和响应 proto 可能会有所帮助,而不是让它们都使用 DiscoveryRequest 和 DiscoveryResponse。 当前方法的问题在于,阅读 proto 文件的人很难真正理解API,因为 proto 文件并没有清楚地说明每个API应该使用哪种类型的请求和响应消息。 每个API具有单独的请求和响应原型,将使该API对于新手来说更容易学习。

  • 我们希望如何处理Envoy等代理客户端和gRPC等非代理客户端之间的根本差异?例如,考虑一个服务网格部署,其中每个服务节点前面都有一个Envoy实例,该实例处理来自其他服务节点的入口连接和到其他服务节点的出口连接。在此部署中,Envoy可以将其所有配置同时应用于入口和出口连接(尽管它只能配置为在一个方向或另一个方向上使用某些功能)-例如,它可以在LDS中将速率限制用于入口或出口。出口连接以及RDS中的主机/路径重写和重试(对于入口或出口连接)。但是,在没有代理的gRPC情况下,在出口情况下LDS没有意义,在入口情况下RDS没有意义。那么,我们如何处理用户想要出口速率限制之类的情况?请注意,在某些情况下,用户的某些连接会通过代理,而有些连接不在同一部署中,因此,如果他们可以一次配置并让它们在两种情况下均能正常工作,那就太好了。让UDPA提供更基于意图的配置是否有意义,在该配置中,用户指定服务节点集和它们彼此通信所需的功能,但将其留给网格以找出系统的哪个部分有什么作用(因此Envoy和gRPC会看到相同的数据,但对它的反应却不同)?还是我们更希望对此进行更明确的说明,在这种情况下,我们需要仔细考虑UDPA服务器如何知道哪些数据发送给哪个客户端(例如,为此使用客户端功能)?我怀疑我们希望在这里使用后者,但是我们需要确定它的工作方式。

    • 相关问题:非代理客户端需要一种方法来查询CDS中的特定群集,而不是获取所有数据。
  • API当前代表许多功能作为过滤器配置(例如,LDS中的速率限制或RDS中的重试)。对于与Envoy相比没有相同类型的筛选器结构的客户,这种方法实际上不起作用。似乎配置功能比配置过滤器更有意义。在具有可配置过滤器顺序的可扩展性和以通用方式指定功能(适用于所有客户端,而不管其内部体系结构)的能力之间似乎需要权衡。我们如何满足这两种需求?

  • 支持提供增量而不是完整 locality/endpoint 列表的EDS变体可能会很有用。这样,在具有动态调度端点的k8之类的环境中,EDS不需要每次有一个端点移动时都重新发送整个更新。

  • [cheneyd @ vmware] xDS/UDPA服务器如何返回否定结果?到目前为止,如果服务器使用资源名称返回EDS发现请求,并且该名称不存在于服务器中,则服务器必须返回带有空资源集的EDS资源。对于其他资源类型(如LDS),没有有效的方法来构造空白资源类型。我认为需要一种通用的方式来表示404资源未找到。

  • [costinm @ google]除了CDS / LDS / RDS / EDS之类的功能外,我们还可以使用CNCF CloudEvents提供类似pub-sub的模型吗?用于LRS / HDS,监视等?我们需要ADS协议有效地实现双向发布订阅。

  • [rlenglet @ google] 结构化客户端发送的错误消息。至少包括引起NACK的资源的类型和名称,以便服务器可以删除它们,并可以与其他资源一起使用。对于服务器而言,始终能够确定配置了哪些资源以及哪个版本很重要。具有结构化的错误类型,服务器可以采取措施。

  • [rlenglet @ google]添加执行原子更新的功能(一次性配置修订版或捆绑包中的所有资源,或者一个都没有)。由于此文档与OpenFlow比较,因此它等同于OpenFlow 1.4的捆绑软件。应该允许捆绑包包含不同类型的资源。

  • [rlenglet @ google]为服务器添加了同步查询客户端中配置的资源的功能,以进行监视/故障排除。

用于下一个Envoy/UDPA主版本的计划清理