分享|eBay边缘节点的云原生网络实践
作者|陈佑雄
编辑|林颖
供稿|eBay Network SIG/PaaS Team
本文共10899字,预计阅读时间20分钟
更多干货请关注“eBay技术荟”公众号
1 背景介绍
1.1 边缘节点
边缘节点,又被称为POP(point-of-presence)节点。通常,边缘节点设备更接近用户终端设备,其主要作用是加快终端用户访问数据中心网络资源的速度。从节点构成上来说,边缘节点一般是由缓存设备和负载均衡设备组成。
1.2 云原生网络
云原生网络(Cloud-native Network)是指:结合云原生的特点,采用云原生部署的方式来构建的网络。这些提供负载均衡功能的云原生网络应用需要运行在Linux容器,比如Kubernetes集群。而在云原生网络实现之前,它们要运行在专门的物理设备上,如硬件负载均衡设备。
通过云原生网络,我们期望边缘节点能够具备以下特征:1.3 UFES
UFES(Unified Front End Services)是一个eBay进行了很多年的项目(于2017年启动),旨在构建一个基于云原生网络(cloud-native network)的低延迟、高稳定性的网络前端和边缘计算平台。也正是通过这个项目,我们搭建了大量的边缘节点,并且在这些节点上部署了能实现L4和L7负载均衡功能的软件(其中L4的实现是基于IPVS,L7的实现基于Envoy)。这里L4负载均衡主要是指对OSI网络模型中的传输层负载均衡,常见的协议如TCP;而L7负载均衡主要是应用层,常见的协议如HTTP。
UFES项目主要针对于eBay的公网流量。eBay公网流量主要来自下几个领域:2 传统基于硬件负载均衡的架构
在启动UFES项目之前,eBay的公网流量都是经过边缘路由器(Edge router)来接入边缘节点的。边缘节点是由工作在Active-Standby模式下的Netscaler硬件负载均衡设备对组成的。我们给不同的域名配置了一组专有的硬件负载均衡设备。比如对于桌面端主站,我们在全球配置了十七组设备,这就意味着全球用户都是通过这十七个边缘节点访问eBay主站。这些硬件在负载均衡上面,配置了大量的L7转发规则,比如在桌面端主站上面配置了以下规则:
② www.ebay.com/sch/—>将请求转发到搜索服务所以在www.ebay.com的后端其实有数百个应用在为它提供服务,这些应用虽然没有通过暴露公网地址的方式直接接收用户请求,但是利用边缘节点设备的转发规则,最终为全球用户提供服务。
图2-1 基于硬件负载均衡的网络架构
(点击可查看大图)
2.1 边缘节点的特征
边缘节点的主要作用是将外网的请求接入数据中心,并且根据不同的L7转发规则将用户请求转发到不同的应用集群进行相应的处理。所以边缘节点上会配置公网的VIP地址,它主要有以下几个特征:
2.2 硬件负载均衡遇到的挑战
由于eBay传统的边缘节点是基于硬件设备基础上的,而这种专门的物理设备除了价格很贵以外,在实际应用中还会遇到以下一些挑战:
3 原生网络的边缘节点架构
正是因为硬件负载均衡设备存在着种种问题,而且公司的方向是将所有的应用都迁移到Tess (eBay的kubernetes),即迁移到云原生,也包括网络的云原生。其中最重要的一个目标便是将边缘节点的硬件负载均衡设备替换成能够支持k8s原生部署的软件实现。
为了满足上述目标,基于云原生网络的边缘节点架构如下图所示,其中边缘节点被拆分成两部分:前端代理(Front Proxy)以及数据中心网关(DC gateway)。图3-1 云原生网络的边缘节点架构
(点击可查看大图)
3.1 前端代理
前端代理(Front Proxy)是一层软件负载均衡。它连接着用户和eBay,是所有进入eBay流量的前端代理。这一层部署在所有的边缘节点和数据中心,主要代理公网的流量,包括桌面端、手机浏览器端以及原生手机应用端。前端代理的主要功能如下:
3.2 数据中心网关
这一层在UFES项目早期并没有设计,它的主要是作为数据中心的接入层,将前端代理的流量转发到后端的应用集群。我们在每一个可用区配置一个网关,而所有的转发规则都配置在数据中心网关。这一层的流量也是跨数据中心的,其权重比例为:本数据中心承担99%流量,远端数据中心承担1%流量。
数据中心网关的主要作用包括以下几点:4 基于IPVS和Contour的边缘网关
4.1 基于IPVS的L4负载均衡
对于L4组件控制面(如图4-1),这里的L4 Director是复刻了google的开源项目“seesaw”并进行了定制,L4 director会在用户空间生成IPVS 服务的哈希表,并基于Linux内核通信的 Netlink 套接字,发送到kernel,更多细节可以参考作者之前一篇博客干货|eBay的4层软件负载均衡实现。
图4-1 L4 组件控制面板
(点击可查看大图)
L4组件数据包封装的采用的是IPVS IPIP隧道模式,如图4-2所示,L4 director会将IPIP数据包发送到后端真实的服务器(即Envoy)进行解包,再进一步处理,所以需要将VIP的地址绑定到后端服务器的tunl0接口,后端Envoy Pod会从上游服务获取到响应之后直接返回(Direct Server Return)到客户端。
图4-2 L4数据包封装
(点击可查看大图)
4.2 基于Envoy/Contour的L7负载均衡
考虑到Envoy能够支持热部署、可观测性、可恢复性、多种负载均衡以及强大的L7支持等特征(如上表所示),并且Envoy是为云原生应用而生,基于Envoy的微服务架构,服务网格是云原生网络的一个发展方向,而且其本身已在eBay生产环境上应用过,这些都促使了我们选择Envoy作为数据面。
图4-3 基于Contour的架构图
(点击可查看大图)
4.3 基于IPVS和Contour的边缘节点架构
有了L4和L7的软件实现之后,完整的边缘节点架构图如下图4-4所示:
图4-4 边缘节点架构图
(点击可查看大图)
② 基于k8s的控制面,支持k8s原生部署。③ 可水平扩展,可通过扩容的方式增加集群数量,以提高整体带宽。④ 支持直接服务器返回(Direct Server Return) ,用户请求会经过IPVS Pod到达后端服务器,服务端直接返回。⑤ BGP宣告VIP网段到路由器,通过ECMP支持多活。
图4-5 边缘节点架构图
(点击可查看大图)
5 UFES动态内容缓存
缓存(caching)是边缘节点提供的另一个重要的功能。它通过在边缘节点提供动态负载缓存功能,以减少由底层网络和后端系统引起的延迟,来改善用户的体验。通过缓存,主要能实现以下几个目标:
图5-1 UFES缓存架构图
(点击可查看大图)
6 PaaS自动化集成
前面介绍了很多UFES相关的背景,而UFES更接近于底层。接下来,我们要解决PaaS这一层的问题:
6.1 Zebra
自动化的第一步是需要定义一种资源,用来描述L7规则。这里我们定义了一套IngressTemplate,有点类似k8s里面的Ingress,但是这套IngressTemplate是定义在内部一个基于MongoDB的配置管理系统(Configuration management system,CMS)。
基于antlr4的分析语法器能将上述L7规则转换成Json格式的IngressTemplate(如下图所示)。
这么做的主要目的是为了能够将L7规则与某一种特定的领域专用语言(domain specific language/ DSL)解耦,并且能够将这套IngressTemplate很容易地转换到其它的L7进行实现。另外,Netscaler的L7规则实际上是一个逻辑表达式,而且这种解析应用更加灵活,比如A||B与B||A转换出来的IngressTemplate是一样的。
我们在Zebra上提供了大量的API,用来管理L7规则,主要包括:
图6-1 PaaS/UFES集成架构图
(点击可查看大图)
3)流量验证
软件负载均衡设备通过PaaS自动化配置完成后,还需要做的一件事情是运行流量验证(traffic validator),并通过自动化的CI运行。
它的工作原理是抓取生产环境下真实的用户访问记录,并提取出URL访问的模式且记录下相应的返回码,然后将同样的URL集合在新创建的软件负载均衡上运行一遍。如果返回码完全匹配,则认为通过验证;否则可能是有某些L7规则出现不匹配,这就需要查找原因并重新配置。
6.2 L7统一管理终端
图6-2 L7统一管理终端
(点击可查看大图)
6.3 PaaS集成的反思
现在再回过头来看整个PaaS的集成,其实一开始并不符合云原生的原则。虽然我们定义了WISB,但这本身还是一个命令式(Imperative Programming)而非声明式(Declarative Programming)的编程。这里将IngressTemplate保存在私有的MongoDB(CMS)。整个Zebra系统在某种意义上,变成了一套k8s里IngressRoute的spec builder,因为Zebra最终的输出是通过LBMS创建很多k8s的Service以及IngressRoute。这样导致的结果是,我们需要为了适配不同的场景,而往Zebra堆加很多功能。这些功能虽然也带有流量管理、服务发现机制,但是最终它只是某种意义上的一个迁移的工具,很多功能当某一天迁移结束后也就失去作用了。
另外一方面,这里又涉及到业务驱动和技术驱动的差别。前者见效快,但是长期的投入会比较多;后者见效慢,而且投入会比前者更多,但它会去构建一些核心的和高频使用的组件。正如Jian总说的,越是被高频率使用的组件我们越会有更多的机会去迭代和增强,而且其生命周期也是最长的,这才是最值得长期投入的。PaaS的集成其实也是一个业务和技术的妥协,早期在技术并不很成熟的情况下先保证业务,后续再逐渐将控制面也迁移到k8s。在eBay的应用上,在k8s的时候也遇到了同样的问题,一开始我们的平台部门还没有适配原生部署,所以我们采取的方式是同化方式(内部称为assimilation),也就是启动一个fat container,这个container和VM行为几乎完全兼容,Pod启动之后并没有部署代码,而是通过fat container里面的Agent去部署应用。目前我们正在面临的问题是如何将这一套同化的方法再迁移到原生部署上。所以如果能再有机会重新开始一次,我觉得有几点是我们可以重新考虑的:7 Contour/Envoy的定制和扩展
7.1 扩展Contour
1)定制apiVersion为contour.ufes.io/v1 beta1
通常每一个VIP会有两个IngresRoute,一个配置了80(HTTP)的L7规则,一个是443(HTTPS)的。这里是一个IngressRoute的示例:
从这个扩展资源中,我们可以看到,我们给IngressRoute增加了很多属性。如additionalProperties,这是用来记录硬件设备上的L7规则名字以及优先级的。另外,我们还定制了安全相关的filter,用来重启或者丢弃用户的请求。在硬件负载均衡设备上,每条L7规则都会有一个名字以及执行的优先级,而IngressRoute上Route配置的顺序决定了执行顺序,所以需要在生成Route的时候根据优先级做好排序。
2)引入HTTPMatchRequest
HTTPMatchRequest其实是Istio VirtualService里面的功能。因为Contour社区只支持简单的Prefix匹配,我们通过引入HTTPMatchRequest,就能够支持更加复杂的规则,比如以下的一些常见的规则:
这里我们也可以看到IngressRoute同时还能支持IngnoreCase,但社区目前还不支持。
3)IngressRouteSpec增加Listener
eBay的每一个公网域通常有多个VIP(如桌面浏览器端分配了3个VIP),需要支持Envoy监听在不同的VIP,这里给IngressRouteSpec增加了Listener:
下面是使用了独立的listener之后我们可以看到Envoy监听在不同的VIP:
4)支持Weighted Endpoint以及停止Endpoint接收流量
UFES的做法是,给前端网关创建一个k8s Service,它的ExternalIP就是公网的IP,而这个服务的Endpoint是由PaaS层维护的,里面通常是三个数据中心网关的私有IP,并且在Endpoint标记如下注释所示:
然后修改Contour的EDS,能够适配Endpoint的annotation并将值推送到Envoy:
最终更新的是Envoy Clusters的upstream hosts状态,如表7.1:
表7.1 Envoy cluster upstream hosts属性
5)集成eBay的CA
这里我们的解决方案是将证书的一个引用地址保存到secret里面,然后会有一个证书代理负责从不同的两个组件分别拿到证书和key,而Contour通过GRPC从证书代理获取证书和key,再通过SDS推送给Envoy。下面是对IngressRoute的定制,使得TLS能够同时支持secretName和IdOrURL。
7.2 扩展Envoy
这种应用场景是,L7规则需要先根据前缀重写URL,再做重定向。这里对Envoy的定制是能够根据收到的请求动态生成重定向响应,我们在重定向下添加了一个新的配置:prefix_rewrite。同时为了删除重定向的查询字符串,我们添加了一个新标志:strip_query,然后再执行重定向。
这个PR已经合并到社区:https://github.com/envoyproxy/envoy/pull/2661
2)支持通配泛域(wildcard domain)作为默认路由
假设Envoy配置了以下两条路由,如果我们去访问http://nomatch.com/api/application_data, envoy会因为匹配不到路由,从而返回404。
在source/common/router/config_impl.cc,相应的改动为:
3)创建Envoy HTTP filter根据 L7匹配执行Drop和Reset
Drop和Reset是已经负载均衡设备上两种很常见的响应行为。顾名思义,它能够将用户的请求直接丢弃(Drop)或者重置(Reset)。这种一般是和安全有关,比如检测到攻击时,我们可以创建一个L7规则快速地将请求丢弃掉,而不会对后端服务器造成压力。
这里主要创建了一个access_control_filter.cc的HTTP过滤器,其主要代码如下:
正是因为有了这个过滤器,我们可以在IngressRoute里面使用reset/drop的服务,用来执行重置和直接丢弃请求的响应。
UFES对于Contour和Envoy的定制和扩展其实不止我提到的这些。有些扩展已经回馈到社区,而有的可能并不适合社区,但是这些都是为了解决了我们生产环境的实际问题。因为社区开源的项目更多的是将不同应用场景和环境下的公共需求加以提取、抽象并且实现。而对于这种定制的需求,只能根据业务的需要进行定制开发,而这也是能够用好开源项目的一个必要条件。
8 小结
到目前eBay三大公网域的流量已经全部迁移到软件负载均衡设备,每天都能接收几十亿次以上的用户进入数据中心的请求,而且我们已经停止购买边缘节点的硬件负载均衡设备。云原生网络最大的好处是:它能够通过开源软件的方式,实现黑盒硬件所提供的功能,并在性能上没有损失,还能实现弹性扩容。由此可见其好处,是值得长期投入的。
UFES项目在这一方面是eBay的先驱,它本身有很多不完美的地方,比如各种显得有些随意的注释;没有定义完整的资源模型;甚至VIP之前都是人工分配;随着VIP的数量增多以及配置量的增加,控制面也有性能的问题正在解决。一部分的原因是因为在项目启动初期,社区的方案都还没有成熟,比如k8s的Ingress controller至今还没成熟的方案;另一个原因是因为eBay有一些定制的需求也是社区没有考虑到的,但是这个项目还是成功的,它在生产环境上稳定运行将近一两年并没有出大的事故,这在给我们积累信心的同时,也证明云原生网络这条路是有希望的,进而也促进我们决心实施的另外一个项目——旨在替换数据中心的硬件负载均衡设备的基于Istio/IPVS的应用网关。另外一点是,UFES这个项目是经过多个阶段的迭代,比如第一个阶段只是建立一些基于硬件负载均衡设备的POP,带来的收益是:桌面应用端访问延迟减少了200+毫秒;手机浏览器端减少了160+毫秒。而第二个阶段是在边缘节点实现软件的负载均衡,花费了将近两年的时间,这一个阶段还经历了将边缘节点拆分成前端代理和数据中心网关。第三个阶段是动态内容缓存以及网页内容预取(Content Pre-fetching)。第四个阶段是全面接管公网的VIP以及集成anycast,这个也是我们目前正在做的,这使得公网的流量被全面通过软件负载均衡接管,大大节省了购买硬件负载均衡设备的开销;另外通过任播技术,这样不仅提高了网络的可用性,还减少了网络故障收敛的时间。9 未来展望
这个是目前我们正在进行中的一个项目,有个别的公网应用已经启用了anycast,通过anycast可以带来以下几个好处:
2)将公网流量接入数据中心基于Istio的应用网关。
在UFES项目中我们实现了边缘节点的云原生网络,但是数据中心的应用架构还是基于两层的硬件负载均衡设备。未来的目标是:将数据中心的硬件负载均衡也迁移到云原生网络上。
(向上滑动启阅)
写在最后:
这个项目的PaaS集成,作者从开始就参与进来,深刻体会了其中的艰辛。一方面是要实现各种自动化和各种集成,开发任务很重。另一方面要承担部分OPS的工作,包括几十个SLB,每个SLB又有若干个VIP需要自动化的初始配置,而且一旦遇到UFES的问题还需要来回多次配置软件负载均衡设备。更重要的一点,还有site incident的“达尔摩斯之剑”,公网流量的管理没有小事,所以能走到现在这一步真的很不容易。虽然这个项目的执行过程比较艰辛,并且如正文所说的这个项目存在一些不完美的地方,但是从结果看这个项目还是成功的,所有为这个项目的付出都是有意义的,值得在这里记录一下,感谢每一个为这个项目付出的小伙伴。其中包括Qiu Yu大牛(基于IPVS的L4负载均衡主要实现者),他还实现了基于一致性哈希的IPVS调度器的kernel模块,也参与了Contour的定制。还有Daxiong,他接力完成了UFES前端代理和数据中心网关的拆分相关的PaaS集成,并且对接了生产环境流量。还有Ji Yuan,作为L7统一管理终端的实现者,也对这个项目的成功上线做出了重要的贡献。此外还有现在与我一起并肩作战的小伙伴:Zewei(参与第四个阶段的集成)以及Leona(帮忙在维护L7 admin console)。另外,我希望借这篇文章阐释一下我对PaaS端对端的理解,希望能给大家带来一些启发。PaaS不仅仅是集成,它也提供了一个机会——如何从无到有的构建一个云原生网络的系统。从小看,能够了解每个数据包是如何从客户端经过物理网络、主机网络、Linux内核、容器网络再到达数据中心的后端应用层,最后返回给用户的整个过程;往大的看,可以知道如何在有很多系统依赖的情况下构建一个高稳定性的系统,并且尽可能地利用自动化减少人为操作。最后,边缘节点的云原生网络实现一路走过来虽然并不是那么一帆风顺,但是放到云计算到云原生变革的这个大背景里,这也是一种技术发展必然的趋势。同时,我们内部实现的架构和采用的技术也一直在迭代演进。目前我们正在实现数据中心基于Istio的云原生网络以及服务网格。这一技术也是充满了挑战,但是作者相信:“长风破浪会有时,直挂云帆济沧海”。往期精彩
从OpenStack到Kubernetes|如何在大规模产线...
干货|eBay的4层软件负载均衡实现
干货|eBay Feature测试环境上k8s的实践
亿展宏图 第七篇|动态图算法
点击阅读原文,一键投递
eBay大量优质职位虚席以待
我们的身边,还缺一个你