2023年10月31日-11月2日,2023云栖大会在中国杭州·云栖小镇举行,携程容器与混合云研发总监乐鸿辉在【云服务器 & 计算服务】专场中带来了题为《混合云弹性如何帮助携程应对业务的低迷与快速恢复》的主题演讲,分享了携程的云原生之旅、混合云弹性实践以及最终实践效果。
以下是他的演讲内容整理,供阅览。
乐鸿辉 携程容器与混合云研发总监
一、携程的云原生之旅
携程从2017年之前就开始了容器化,很早就对在线应用进行了先期探索;2018年时,基于云原生架构业务的未来趋势判断,用K8s代替了原有的Mesos架构,并以K8s为起点构建容器平台,进行云原生化改造。
云原生架构不仅是容器化,更是整个infrastructure架构以及应用层的现代化,使其具备有弹性、轻量、可迁移的特性。到2020年,我们经历了疫情,直接导致业务进入了低迷期,但是对做基础架构的人来讲是一个非常好的机会。所以这几年也是非常繁忙的一段时间,业务技术团队以及我们对整个架构做了很大的改造,去打造一个弹性的、混合多云的系统。
目前,我们已经基于容器平台把近60%以上的算力进行了容器化,包括部分有状态的服务。同时,我们也构建了一个混合多云的架构,充分利用弹性调度的手段,进行降本增效,提升运营的效率。
这张图是航空客运量的数据,可以看到在疫情期间的波动非常大,整个业务上的不确定性对我们造成一个非常大的压力,这个业务的波动会反映在对整个基础设施上的需求和挑战。
以前,我们是基于IDC这样传统的容量预测,相对来讲是一个可预测的范围,什么时候去建设IDC、什么时候去准备什么样的资源。但是一旦进入疫情期间,这个是非常难做到的,基本上以前的历史数据已经无效了。
另一个问题,疫情期间对公司的业务影响比较大,所以降本压力非常大,要尽量杜绝资源浪费。同时,一旦恢复,将会迎来一个猛烈的反弹,对资源有快速扩展的需求。既要降本,又要应对未来极速扩展的需求,对整个技术体系的容量管理和弹性是非常大的一个挑战。
应用容量的管理,在之前是手工进行的,面临以下三个问题:
- 管理效率低。因为都是手工管理,虽然有一些辅助的预测工具,但是携程有一万多个应用、两万多个部署组,需要消耗大量的研发人员、SRE的精力。
- 容量风险高。手工扩容容易存在偏差,一旦出现数据波动,应用极有可能造成恐慌性的扩容,造成容量挤兑。
- 基于以上问题,研发倾向于提前超量扩容,最终导致严重的资源浪费。
二、混合云弹性实践:提出韧性优先架构
针对以上挑战与问题,弹性系统是非常好的解决方案。但从手工管理到弹性的自动化系统,对容器平台构建者而言,怎么让我们的研发人员、乃至整个公司信任这套系统,并在关键时刻起作用呢?我们把这个问题从三个维度进行了拆解。
- 弹得快,即跟上流量。
- 靠得住,即关键时候不掉链子。
- 容量足,容量不足一切都是免谈的。
第一个,是弹得快,是性能问题。首先,我们到底需要多高的性能?第一反应肯定是性能越高越好,但是同样意味着边际成本会越来越高。所以,如何评估合理的目标非常重要。我们是基于场景来评估性能目标的,这些场景包括日内扩容、节假日扩容,对未来的增长预期,系统的冗余系数。基于上述场景的数据及评估,来敲定目标SLO。然后,梳理核心链路,对链路进行拆解,进行数据埋点、启动压测,分析瓶颈再优化的过程。
在优化上,除了代码优化,更重要的是架构上的优化。如果只在部分场景使用了容器、K8s,但其它的架构生态还是基于传统的静态思路构建,而不进行调整,那么会对整体的性能与可靠性造成非常大的影响。整体来讲,云原生更重要的是整个架构的现代化过程。
第二个问题,如何确保关键时刻不掉链子。对于研发人员来讲,可以从局部做好每个系统的优化、压测,做好可靠性保障,提升局部的可靠性。但是如果从架构、从自上而下的角度来思考问题,局部的故障是不可能避免的。如果局部出现故障,怎么去保证整体的可靠性,保证对业务的承诺是能够达到的?以下介绍几个经典的高可用的设计经验:
第一,做到故障的隔离。要保证系统一旦出现局部问题的时候,避免从一个局部的故障演变成一个整体的故障。在这基础之上,可以在故障域之间做冗余部署,一旦发生故障,就可以利用切换手段完成故障转移。可能大家、包括我们自己也会走一些弯路,我们以前经常关注的是冗余部署和故障转移,往往忽视了故障隔离,但是其实「故障隔离」是其中最重要的一个点,如果做不到故障隔离,后面两个其实都是无效的。
基于上述思想,我们提出了韧性优先架构。
从结构上来看,利用Region 、AZ等公共云提供的天然故障域,在这故障域之内,构建partition这样更小的故障域。不同于业界、社区,我们的K8s是不跨故障域部署的,而是部署在partition内的。
基于这样的架构诉求,不可避免得会出现很多的集群,在提供给上游的客户或上游的系统用的时候,我们要简化它的复杂性。所以在这之上,每个Region也部署了一套Federation,上层PaaS与使用方对接Federation,由Federation提供Region内部署的调度能力及管控能力。
基于这样的结构,我们引入了一些约束。对韧性优先架构的约束主要有以下两点:
第一,核心的、弹性的高频链路应该收敛在故障域内,在东西向不能出现频繁的控制链路/数据链路的交互,因为这会打破故障隔离的原则;
第二,应用要在多个故障域 partition之间进行冗余部署,在变更的规范上,不允许同时跨越多个AZ、多个partition、多个故障域之间的变更,因为这些变更动作同样也会打破故障隔离的前提。一般核心链路涉及到的环节和系统非常多,只有这些环节和系统都做到了这样的架构对齐,才会真正实现韧性优先,这是一个百密一疏和持续性的工作。
基于这样的架构思想,我们也设计了多集群的HPA方案,实现HPA功能的韧性优先。
首先,分析HPA有哪些关键链路。第一个,最核心的是对应用容量的自动扩缩容,第二个是HPA的资源的变更,第三个是多区域之间容量的再平衡。因为扩缩容会影响应用承载流量的能力,它也是最高频的,这条链路最为核心,所以它的故障域设计上要做到最小,故障域限定在K8s Cluster。即扩缩容的动作在K8s Cluster内就可以封闭,无需跟外部进行交互。而再平衡主要是为了平衡各集群及AZ的容量,小时级别的不可用都不太影响业务流量的承载,它的故障域要求会松一点,为整个Region。HPA资源的变更类似,故障域定义为Region。
基于这样的设计与实现,如果Cluster A挂了,流量会自动把负载均衡地传导到Cluster B,在Cluster B扩缩容的组件会自动扩容。也就是说整个架构,不论是个别Cluster宕掉或者Federation宕掉,对上层的业务来说完全是无感的,会正常地进行扩缩容。
另一方面,怎么解决容量的问题。携程以前是基于IDC构建的,容量扩展周期较长。目前是通过打通阿里云,以混合云的架构,利用云的弹性来扩展容量。
具体来看,在携程容器的IP是全局可路由的,然后AZ内是应用共享同一个流量调度单元,做到调用尽量收敛。在这样的一个结构下,也提出了一些约束:AZ之间容量的驱动是由流量的驱动来进行的,但是AZ内的容量负载,甚至是故障切换,是由Federation进行调控实例数比例来进行的。
三、效果:最高峰1分钟扩容近2000个容器实例
上图是阿里云的某一个AZ的资源使用的展示。可以看到,波动是非常剧烈的,也非常感谢阿里云在ECS的弹性供应上有非常强的能力,帮助我们应对流量的尖峰和波动。
从过去一年的指标看,弹性系统可靠性没有发生过影响业务的故障。像今年这么大挑战情况下,基本上系统的可靠性达到了历史最高峰。在假日高峰,能够做到一分钟有近2000个容器实例的扩容。扩展性上,最高将30%的容量调度到阿里云;效率上,90%以上的应用开了HPA,同时HPA本身的参数是由autopilot产品来负责去优化与管控,以达到最优或者遵循统一的策略,这样基本不需要人的参与去运维。
成本方面,通过弹性系统,在线应用CPU的宿主机利用率在25%到30%之间。当然宿主机利用率的上限也受到多AZ容灾设计上的限制,如2个AZ的容灾架构一般宿主机的利用率不要超过50%。
因为每个应用是按需使用资源的,所以应用跟应用之间,业务跟业务之间它有一个错峰的效应。基于错峰的效应,整个五一期间,把容量需求的峰值消减了28%以上,同样也可以达到降本的效果。