为Envoy v2构建捕鱼大亨网络版 Edge(Ingress)控制平面

作者:数据线产品架构师Daniel Bryant; Datawire大使,首席开发人员Flynn; Datawire首席执行官兼联合创始人Richard Li

捕鱼大亨网络版已经成为基于容器的微服务应用程序的实际运行时,但是仅此编排框架并不能提供运行分布式系统所需的所有基础架构。微服务通常通过第7层协议(例如HTTP,gRPC或WebSockets)进行通信,因此具有在这一层做出路由决策,操纵协议元数据并进行观察的能力至关重要。但是,传统的负载平衡器和边缘代理主要集中在L3 / 4流量上。这是 特使代理 发挥作用。

特使代理被设计为 通用数据平面 由Lyft Engineering团队从零开始,以当今以L7为中心的分布式世界,对L7协议的广泛支持,用于管理其配置,一流的可观察性和在小内存空间内实现高性能的实时API。但是,Envoy的广泛功能集和操作灵活性也使其配置变得非常复杂-从其丰富而冗长的外观中可以明显看出这一点。 控制平面 句法。

与开源 大使API网关,我们想解决创建新控制平面的挑战,该控制平面着重于以捕鱼大亨网络版运营商惯用的方式将Envoy部署为捕鱼大亨网络版集群中的前向边缘代理的用例。在本文中,我们将介绍Ambassador设计的两个主要迭代,以及如何将Ambassador与捕鱼大亨网络版集成在一起。

2019年之前的大使:Envoy v1 API,Jinja模板文件和热重启

大使本身作为捕鱼大亨网络版服务部署在容器中,并使用添加到捕鱼大亨网络版 Services的注释作为其捕鱼大亨网络版服务。 核心配置模型。这种方法 使应用程序开发人员可以管理路由 作为捕鱼大亨网络版服务定义的一部分。我们明确决定沿着这条路线走,因为 局限性 在当前 入口API规范,我们喜欢扩展捕鱼大亨网络版服务的简便性,而不是引入另一种自定义资源类型。可以在此处查看大使注释的示例:

kind: Service
apiVersion: v1
metadata:
  name: my-service
  annotations:
    getambassador.io/config: |
      ---
        apiVersion: ambassador/v0
        kind:  Mapping
        name:  my_service_mapping
        prefix: /my-service/
        service: my-service
spec:
  selector:
    app: MyApp
  ports:
  - protocol: TCP
    port: 80
    targetPort: 9376

将此简单的大使注释配置转换为有效的 特使v1 config并不是一件简单的任务。根据设计,大使的配置与Envoy的配置不基于相同的概念模型-我们故意要汇总并简化操作和配置。因此,将一组概念转换为另一组概念涉及大使内部的大量逻辑。

在Ambassador的第一个迭代中,我们创建了一个基于Python的服务,该服务监视捕鱼大亨网络版 API对Service对象的更改。当检测到新的或更新的Ambassador注释时,这些注释将从Ambassador语法转换为体现我们核心配置模型和概念的中间表示(IR)。接下来,大使将此IR转换为具有代表性的Envoy配置,并将其另存为文件,该文件与运行中的大使k8s服务关联的吊舱中。然后,大使“热重启”在大使吊舱中运行的Envoy流程,这触发了新配置的加载。

最初的实施有很多好处。涉及的机制从根本上讲是简单的,将Ambassador config转换为Envoy config是可靠的​​,并且与Envoy的基于文件的热重启集成是可靠的。

但是,此版本的大使也面临显着挑战。首先,尽管热重启对于我们大多数客户的用例都是有效的,但是它并不是很快,并且一些客户(尤其是那些拥有大量应用程序部署的客户)发现它限制了他们更改配置的频率。热重启还会删除连接,特别是寿命长的连接(如WebSockets或gRPC流)。

但是,更重要的是,IR的第一个实现允许快速制作原型,但足够原始,以至于很难进行实质性更改。尽管从一开始这就是一个痛苦点,但随着Envoy转移到 Envoy v2 API。很明显,v2 API将为大使带来许多好处-正如Matt Klein在其博客文章中概述的那样,“通用数据平面API“-包括访问新功能和解决上述连接断开问题的方法,但很明显,现有的IR实施方法无法实现这一目标。

Ambassador >= v0.50: Envoy v2 APIs (ADS), Testing with KAT, 和 Golang

大使社区数据线 团队在2018年对大使内部进行了重新设计。这是由两个主要目标驱动的。首先,我们要整合Envoy的v2配置格式,这将支持诸如 SNI , 限速gRPC身份验证API。其次,由于Envoy配置的复杂性不断增加(特别是在大规模应用程序部署中运行时),我们还希望对它进行语义验证。

初期阶段

我们首先按照多遍编译器的方式对大使内部进行重组。使类层次结构更加紧密地反映了大使配置资源,IR和Envoy配置资源之间关注点的分离。还对大使的核心部分进行了重新设计,以促进Datawire外部社区的贡献。我们决定采用此方法有几个原因。首先,Envoy Proxy是一个快速发展的项目,我们意识到我们需要一种方法,即看似微小的Envoy配置更改不会导致在Ambassador中进行几天的重新设计。另外,我们希望能够提供配置的语义验证。

当我们开始与Envoy v2更加紧密地合作时,很快就发现了测试难题。随着大使支持越来越多的功能,大使在处理不太常见但完全有效的功能组合时出现了越来越多的错误。这驱使创建新的测试要求,这意味着需要对大使的测试套件进行重新设计以自动管理功能的许多组合,而不是依靠人工来编写每个测试。此外,我们希望测试套件能够快速运行以最大化工程效率。

因此,作为大使馆改组的一部分,我们介绍了 捕鱼大亨网络版验收测试(KAT) 框架。 KAT是一个可扩展的测试框架,该框架:

  1. (与大使一起)部署一堆服务到捕鱼大亨网络版集群
  2. 针对启动的API运行一系列验证查询
  3. 对这些查询结果执行一堆断言

KAT专为提高性能而设计-它预先对测试设置进行批处理,然后与高性能客户端异步运行步骤3中的所有查询。 KAT中的流量驱动程序使用 网真,这使调试问题变得更加容易。

将Golang介绍给大使馆

有了KAT测试框架后,我们很快就遇到了Envoy v2配置和热重启的一些问题,这为切换到使用Envoy的聚合发现服务(ADS)API而不是热重启提供了机会。这完全消除了重新启动配置更改的要求,我们发现这可能导致在高负载或长期连接的情况下断开连接。

但是,在考虑迁移到ADS时,我们面临一个有趣的问题。 ADS并不像人们期望的那么简单:向Envoy发送更新时存在明确的排序依赖性。 Envoy项目具有排序逻辑的参考实现,但仅在Go和Java中才有,大使主要在Python中。我们有些苦恼,并决定前进的最简单方法是接受我们世界的多语种性质,并在Go中执行ADS实现。

我们还发现,在使用KAT的情况下,我们的测试已经达到了Python在许多网络连接下的性能受到限制的地步,因此我们也利用了Go的优势,主要在Go中编写了KAT的查询和后端服务。毕竟,如果您已大胆尝试,那么对Golang的依赖又是什么?

有了新的测试框架,新的IR(生成有效的Envoy v2配置)和ADS,我们认为我们已经完成了大使0.50的主要体系结构更改。 ,我们又遇到了一个问题。在Azure 捕鱼大亨网络版服务上,不再检测到大使注释更改。

通过与高度响应的AKS工程团队合作,我们能够确定问题所在-即AKS中的捕鱼大亨网络版 API服务器通过代理链暴露,要求客户端进行更新以了解如何使用服务器的FQDN进行连接API服务器,通过AKS中的可变Webhook提供。不幸的是,正式的捕鱼大亨网络版 Python客户端中没有对此功能的支持,因此这是我们选择切换到Go而不是Python的第三处。

这就提出了一个有趣的问题:“为什么不放弃所有的Python代码,而只用Go完全重写Ambassador?”这是一个有效的问题。重写的主要问题是大使和特使在不同的概念层次上运作,而不是简单地用不同的语法表达相同的概念。可以肯定的是,我们已经用一种新的语言表达了概念上的桥梁,这并不是一个微不足道的挑战,如果没有非常好的测试覆盖面,那么这也不是一件容易的事。

在这一点上,我们使用Go覆盖非常具体,功能完备的功能,可以更轻松地验证其正确性,从而可以验证完整的Golang重写。将来,谁知道呢?但是对于0.50.0,此功能拆分让我们俩都可以利用Golang的优势,同时让我们对0.50中已经存在的所有更改保持更大的信心。

得到教训

在建设过程中我们学到了很多东西 大使0.50。我们的一些主要收获:

  • 捕鱼大亨网络版和Envoy是非常强大的框架,但它们也是快速移动的目标-有时没有替代品来阅读源代码并与维护者交谈(幸运的是,维护者都可以轻松访问!)
  • 捕鱼大亨网络版 / Envoy生态系统中受支持最好的库是用Go编写的。当我们喜欢Python时,我们不得不采用Go,这样我们就不会被迫自己维护太多组件。
  • 有时需要重新设计测试工具,以使软件向前发展。
  • 重新设计测试工具的实际成本通常是将旧测试移植到新的工具实现中。
  • 为边缘代理用例设计(和实施)有效的控制平面一直是一项挑战,而来自捕鱼大亨网络版,Envoy和Ambassador的开源社区的反馈非常有用。

将大使迁移到Envoy v2配置和ADS API是一个漫长而艰难的旅程,需要大量的体系结构和设计讨论以及大量的编码,但是早期的结果反馈是积极的。 0.50大使现在可用,因此您可以进行测试并与社区分享有关我们的反馈 松弛通道 或上 推特.