[大厂实践] 零配置服务网格与按需集群发现

本文介绍了Netflix通过扩展Envoy支持按需集群发现机制帮助团队无缝迁移服务网格的实践。原文: Zero Configuration Service Mesh with On-Demand Cluster Discovery

在这篇文章中,我们将讨论Netflix采用服务网格的历史、动机,以及如何与Kinvolk和Envoy社区合作,在复杂的微服务环境中简化服务网格,即按需集群发现。

Netflix IPC简史

在大型公司中,Netflix很早就开始使用云计算了。从2008年开始迁移,到2010年,Netflix的流媒体就完全在AWS上运行了[1]。今天,有大量工具(既有开源的,也有商业的)都是为云原生环境设计的。然而,在2010年,这些几乎都不存在(CNCF直到2015年才成立)!由于没有现成解决方案可用,不得不自己构建。

对于服务间的进程间通信(IPC,Inter-Process Communication),通常需要中间层负载均衡器提供的丰富功能集。此外还需要解决方案来解决在云中工作的现实: 高度动态的环境,节点不断启动关闭,服务需要快速响应更改并绕过故障。为了提高可用性,我们设计了可以单独失败并避免单点故障的系统组件。这些设计原则引导我们实现客户端负载均衡,而2012年圣诞节前夕的宕机事件[2]进一步巩固了这一决定。在上云的最初几年里,我们为服务发现构建了Eureka[3]为IPC构建了Ribbon[4](内部称为NIWS)。Eureka解决了服务如何发现以及与哪些实例通信的问题,而Ribbon提供了负载均衡的客户端逻辑,以及许多其他弹性特性。这两项技术,以及许多其他弹性和混沌工具,产生了巨大的变化,显著提升了可靠性。

Eureka和Ribbon提供了简单但功能强大的界面,使得采用很容易。为了使一个服务与另一个服务通信,需要知道两件事: 目标服务名,以及通信是否应该是安全的。Eureka为此提供的抽象是用于非安全通信的虚拟IP(VIP,Virtual IP)和用于安全通信的安全VIP(SVIP,Secure VIP)。服务向Eureka发布一个VIP名称和端口(例如: myservice,端口8080),或者一个SVIP名称和端口(例如: myservice-secure,端口8443),或者同时发布两者。IPC客户端针对VIP或SVIP实例化,Eureka客户端代码通过从Eureka服务器获取IP和端口对来处理该VIP的转换。客户端还可以选择性启用IPC功能,如重试或断路,或定义一组合理的默认值。

[大厂实践] 零配置服务网格与按需集群发现_第1张图片

在该体系架构中,服务到服务的通信不再经过负载均衡器,因此没有单点故障。缺点是,Eureka作为主机注册VIP的真实来源,是一个新的故障点。但是,如果Eureka出现故障,服务可以继续相互通信,尽管随着时间推移,主机信息会随着VIP实例的启动、关闭而变得陈旧。但与完全无法通信相比,在停机期间以降级但可用的状态运行的能力仍然是个显著改进。

为什么需要服务网格?

过去的十年中,尽管不断变化的业务需求和不断发展的行业标准在许多方面增加了IPC生态系统的复杂性,但上述架构为我们提供了良好服务。首先,我们增加了不同IPC客户机的数量。内部IPC流量现在是纯REST、GraphQL[5]gRPC[6]的混合。其次,我们已经从纯Java环境转变为多语言环境,支持node.js[7]Python[8]以及各种OSS和现成软件。第三,我们继续为IPC客户端添加更多功能: 自适应并发控制[9]断路[10]、对冲和故障注入等功能已经成为工程师的标准工具,使我们的系统更加可靠。与十年前相比,我们现在支持更多特性、更多语言、更多客户端。在所有这些实现之间保持功能均等并确保以相同方式运行非常具有挑战性,我们想要一个单一的、所有功能经过良好测试的实现,这样就可以在一个地方进行更改和修复错误。

这就是服务网格的作用所在,我们可以将IPC功能集中在一个实现中,并使每种语言的客户端尽可能简单,只需要知道如何与本地代理通信。Envoy非常适合作为代理,它是一个经过实战测试的OSS产品,在行业中大规模使用,具有许多关键弹性特性[11],当我们需要扩展其功能时,有很好的扩展点[12]通过中央控制平面配置代理[13]的能力是一个杀手级功能,这允许我们动态配置客户端负载均衡,就好像中央负载均衡器一样,但避免了负载均衡器作为服务到服务请求路径中的故障单点。

向服务网格迁移

一旦决定迁移到服务网格,下个问题就变成了应该如何迁移?我们为迁移确定了一些约束条件。首先,希望保留现有界面,特定VIP名和安全的抽象可以很好的为我们服务,我们不想破坏向后兼容性。第二,希望自动化迁移,并使其尽可能无缝。这两个约束意味着我们需要在Envoy中支持Discovery抽象,以便IPC客户端可以继续在底层使用。幸运的是,Envoy已经为此准备好了抽象[14]。VIP可以表示为Envoy集群,代理可以使用集群发现服务(CDS,Cluster Discovery Service)从控制平面获取。集群中的主机表示为Envoy端点,可以使用端点发现服务(EDS,Endpoint Discovery Service)来获取。

我们很快就遇到了无缝迁移的绊脚石,Envoy要求将集群指定为代理配置的一部分。如果服务A需要与集群B和C通信,那么需要将集群B和C定义为A的代理配置的一部分。这在规模上具有挑战性,因为任何给定服务都可能与数十个集群通信,而每个应用的集群集都是不同的。此外,Netflix一直在变化,不断有新业务上线,如直播、广告[15]和游戏,架构也在不断发展。这意味着与服务通信的集群将随着时间的推移而变化。我们评估了许多不同方法来填充集群配置,假设有Envoy原语可供使用:

  1. 让服务所有者定义其服务需要与之通信的集群。这个选项看起来很简单,但在实践中,服务所有者并不总是知道,或者想知道,他们与哪些服务进行通信。服务通常导入由其他团队提供的库,这些库在底层与多个其他服务通信,或者与遥测和日志记录等其他运维服务通信。这意味着服务所有者需要知道这些辅助服务和库是如何在底层实现的,并在发生变化时调整配置。

  2. 基于服务调用图自动生成Envoy配置。这种方法对于已经存在的服务很简单,但是当上线新服务或添加一个新的上游通信集群时,这种方法就很有挑战性了。

  3. 将所有集群推送到每个应用。这个选项很简单,但很快就发现,将数百万个端点推送到每个代理并不可行。

考虑到我们的目标是无缝采用,这些选项中每一个的缺点都足够明显,因此我们探索了另一个选项: 如果可以在运行时按需获取集群信息,而不是预先定义,那会怎么样?当时,服务网格的工作仍处于起步阶段,只有少数工程师在从事这项工作。我们联系了Kinvolk,看看他们是否可以与我们和Envoy社区合作实现这个功能。这种协作的结果是按需集群发现[16](ODCDS,On-Demand Cluster Discovery)。有了这个特性,代理现在可以在第一次尝试连接集群时查找集群信息,而不用在配置中预定义所有集群。

有了这个功能,我们需要为代理提供集群信息以供查找。我们开发了一个实现Envoy XDS服务的服务网格控制平面。然后,需要从Eureka获取服务信息,以便返回到代理。我们将Eureka VIP和SVIP表示为独立的Envoy集群发现服务(CDS)集群(因此服务myservice可以有集群myservice.vipmyservice.svip)。集群中单个主机表示为单独的端点发现服务(EDS)端点。这允许我们重用相同的Eureka抽象,并且像Ribbon这样的IPC客户端可以以最小的更改迁移到服务网格。随着控制平面和数据平面的变化,流程如下所示:

  1. 客户端请求发到Envoy
  2. 根据Host/:authority头提取目标集群(这里使用的头是可配置的,这是我们的方法)。如果已经知道该集群,跳转到步骤7
  3. 集群不存在,暂停当前请求
  4. 向控制平面集群发现服务(CDS)端点发出请求,控制平面根据服务配置和Eureka注册信息生成定制的CDS响应
  5. Envoy收到响应,通过端点发现服务(EDS)触发端点拉取,EDS根据VIP或SVIP的Eureka状态信息返回集群端点
  6. 继续处理客户端请求
  7. Envoy正常处理请求,基于负载均衡算法选择一个端点并发出请求

整个流程在几毫秒内完成,但只有在对集群的第一个请求时触发。之后,Envoy的行为就像在配置中定义了集群一样。关键是该系统让我们可以在不需要配置的情况下无缝的将服务迁移到服务网格,满足了之前定义的主要采用约束之一。我们提供的抽象仍然是VIP名称加安全,可以通过配置单个IPC客户端连接到本地代理而不是直接连接上游应用程序来迁移到服务网格。我们继续用Eureka作为VIP和实例状态的真实来源,让我们能够在迁移时为网格上应用提供异构环境的支持。还有一个额外的好处是可以通过只获取实际通信的集群数据来降低Envoy内存使用率。

[大厂实践] 零配置服务网格与按需集群发现_第2张图片

按需获取数据有一个缺点,集群第一个请求的延迟会增加。我们遇到过这样的用例: 服务在第一次请求时需要非常低的访问延迟,增加几毫秒的额外时间会增加太多开销。对于这些用例,服务需要预先定义与之通信的集群,或者在发出第一个请求之前建立连接。我们还考虑了在代理启动时根据历史请求模式从控制平面预推送集群。总的来说,我们认为用一小部分服务受影响的代价降低系统杂性是合理的。


你好,我是俞凡,在Motorola做过研发,现在在Mavenir做技术工作,对通信、网络、后端架构、云原生、DevOps、CICD、区块链、AI等技术始终保持着浓厚的兴趣,平时喜欢阅读、思考,相信持续学习、终身成长,欢迎一起交流学习。为了方便大家以后能第一时间看到文章,请朋友们关注公众号"DeepNoMind",并设个星标吧,如果能一键三连(转发、点赞、在看),则能给我带来更多的支持和动力,激励我持续写下去,和大家共同成长进步!

参考资料

[1]

Four reasons we choose Amazons Cloud as our computing platform: https://netflixtechblog.com/four-reasons-we-choose-amazons-cloud-as-our-computing-platform-4aceb692afec

[2]

A closer look at the Christmas Eve outage: https://netflixtechblog.com/a-closer-look-at-the-christmas-eve-outage-d7b409a529ee

[3]

Netflix shares cloud load balancing and failover tool Eureka: https://netflixtechblog.com/netflix-shares-cloud-load-balancing-and-failover-tool-eureka-c10647ef95e5

[4]

Announcing Ribbon: tying the Netflix mid tier services together: https://netflixtechblog.com/announcing-ribbon-tying-the-netflix-mid-tier-services-together-a89346910a62

[5]

How Netflix scales it's API with GraphQL federation part 1: https://netflixtechblog.com/how-netflix-scales-its-api-with-graphql-federation-part-1-ae3557c187e2

[6]

Practical API design at Netflix Part 1 - Using protobuf fieldmask: https://netflixtechblog.com/practical-api-design-at-netflix-part-1-using-protobuf-fieldmask-35cfdc606518

[7]

Debugging node.js in production: https://netflixtechblog.com/debugging-node-js-in-production-75901bb10f2d

[8]

Python at Netflix: https://netflixtechblog.com/python-at-netflix-bba45dae649e

[9]

Performance under load: https://netflixtechblog.medium.com/performance-under-load-3e6fa9a60581

[10]

Making the Netflix API more resilient: https://netflixtechblog.com/making-the-netflix-api-more-resilient-a8ec62159c2d

[11]

Envoy Adaptive Concurrency Control L7 Filter: https://github.com/envoyproxy/envoy/issues/7789

[12]

Wasm Network Filter: https://www.envoyproxy.io/docs/envoy/latest/configuration/listeners/network_filters/wasm_filter.html

[13]

xDS configuration API overview: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/operations/dynamic_configuration

[14]

Envoy Terminology: https://www.envoyproxy.io/docs/envoy/latest/intro/arch_overview/intro/terminology

[15]

Ensuring the successful launch of Ads on Netflix: https://netflixtechblog.com/ensuring-the-successful-launch-of-ads-on-netflix-f99490fdf1ba

[16]

On-Demand Cluster Discovery: https://github.com/envoyproxy/envoy/pull/18723

- END -

本文由 mdnice 多平台发布

你可能感兴趣的:(程序人生)