做者 | 张晓宇(衷源) 阿里云容器平台技术专家html
关注『阿里巴巴云原生』公众号,回复关键词“1010**”,可获取本文 PPT。**node
**导读:**资源利用率一直是不少平台管理和研发人员关心的话题。本文做者经过阿里巴巴容器平台团队在这一领域的工做实践,整理出了一套资源利用提高的方案,但愿可以带给你们带来一些讨论和思考。算法
不知道你们有没有过这样的经历:当咱们拥有了一套 Kubernetes 集群,而后开始部署应用的时候,咱们应该给容器分配多少资源呢?数据库
这很难说。因为 Kubernetes 本身的机制,咱们能够理解容器的资源实质上是一个静态的配置。api
试问,咱们能作到容器资源的按需分配吗?接下来,咱们将在本次分享中和你们一块儿进行探讨这个问题的答案。安全
首先请容许咱们根据咱们的实际状况抛出咱们实际生产环境的挑战。或许你们还记得 2018 年的天猫双 11,这一天的总成交额达到了 2135 亿。由此一斑可窥全豹,可以支撑如此庞大规模的交易量背后的系统,其应用种类和数量应该是怎样的一种规模。微信
在这种规模下,咱们经常听到的容器调度,如:容器编排,负载均衡,集群扩缩容,集群升级,应用发布,应用灰度等等这些词,在被“超大规模集群”这个词修饰后,都再也不是件容易处理的事情。规模自己也就是咱们最大的挑战。如何运营和管理好这么一个庞大的系统,并遵循业界 dev-ops 宣传的那样效果,犹如让大象去跳舞。可是马老师曾说过,大象就该干大象该干的事情,为何要去跳舞呢。网络
大象是否能够跳舞,带着这个问题,咱们须要从淘宝、天猫等 APP 背后系统提及。架构
这套互联网系统应用部署大体可分为三个阶段,传统部署,虚拟机部署和容器部署。相比于传统部署,虚拟机部署有了更好的隔离性和安全性,可是在性能上不可避免的产生了大量损耗。而容器部署又在虚拟机部署实现隔离和安全的背景下,提出了更轻量化的解决方案。咱们的系统也是沿着这么一条主航道上运行的。假设底层系统比如一艘巨轮,面对巨量的集装箱---容器,咱们须要一个优秀的船长,对它们进行调度编排,让系统这艘大船能够避开层层险阻,操做难度下降,且具有更多灵活性,最终达成航行的目的。负载均衡
在开始之初,想到容器化和 Kubernetes 的各类美好场景,咱们理想中的容器编排效果应该是这样的:
然而理想很丰满,现实很骨感。迎接咱们的倒是杂乱和形态万千的窘迫。
杂乱,是由于做为一个异军突起的新型技术栈,不少配套工具和工做流的建设处于初级阶段。Demo 版本中运行良好的工具,在真实场景下大规模铺开,各类隐藏的问题就会暴露无遗,层出不穷。从开发到运维,全部的工做人员都在各类被动地疲于奔命。另外,“大规模铺开”还意味着,要直接面对形态万千的生产环境:异构配置的机器、复杂的需求,甚至是适配用户的既往的使用习惯等等。
除了让人心力交瘁的混乱,系统还面临着应用容器的各类崩溃问题:内存不足致使的 OOM,CPU quota 分配太少,致使进程被 throttle,还有带宽不足,响应时延大幅上升...甚至是交易量在面对访问高峰时候因为系统不给力致使的断崖式下跌等等。这些都使咱们在大规模商用 Kubernetes 场景中积累很是多的经验。
问题总要进行面对的。正如某位高人说过:若是感受哪里不太对,那么确定有些地方出问题了。因而咱们就要剖析,问题究竟出在哪里。针对于内存的 OOM,CPU 资源被 throttle,咱们能够推断咱们给与容器分配的初始资源不足。
资源不足就势必形成整个应用服务稳定性降低。例如上图的场景:虽然是同一种应用的副本,或许是因为负载均衡不够强大,或者是因为应用自身的缘由,甚至是因为机器自己是异构的,相同数值的资源,可能对于同一种应用的不一样副本并具备相等的价值和意义。在数值上他们看似分配了相同的资源,然而在实际负载工做时,极有可能出现的现象是肥瘦不均的。
而在资源 overcommit 的场景下,应用在整个节点资源不足,或是在所在的 CPU share pool 资源不足时,也会出现严重的资源竞争关系。资源竞争是对应用稳定性最大的威胁之一。因此咱们要尽力在生产环境中清除全部的威胁。
咱们都知道稳定性是件很重要的事情,尤为对于掌控上百万容器生杀大权的一线研发人员。或许不经心的一个操做就有可能形成影响面巨大的生产事故。
所以,咱们也按照通常流程作了系统预防和兜底工做。
可是对于陡然增长几分钟的突增流量,这么多组合拳的花费不菲,彷佛有些不划算。或许咱们能够提出一些解决方案,达到咱们的预期。
回顾一下咱们的应用部署状况:节点上的容器通常分属多种应用,这些应用自己不必定,也通常不会同时处于访问的高峰。对于混合部署应用的宿主机,若是能都错峰分配上面运行容器的资源或许更科学。
应用的资源需求可能就像月亮同样有阴晴圆缺,有周期变化。例如在线业务,尤为是交易业务,它们在资源使用上呈现必定的周期性,例如:在凌晨、上午时,它的使用量并非很高,而在午间、下午时会比较高。
打个比方:对于 A 应用的重要时刻,对于 B 应用可能不那么重要,适当打压 B 应用,腾挪出资源给 A 应用,这是个不错的选择。这听起来有点像是分时复用的感受。可是若是咱们按照流量峰值时的需求配置资源就会产生大量的浪费。
除了对于实时性要求很高的在线应用外,咱们还有离线应用和实时计算应用等:离线计算对于 CPU 、Memory 或网络资源的使用以及时间不那么敏感,因此在任什么时候间段它均可以运行;实时计算,可能对于时间敏感性就会很高。
早期,咱们业务是在不一样的节点按照应用的类型独立进行部署。从上面这张图来看,若是它们进行分时复用资源,针对实时性这个需求层面,咱们会发现它实际的最大使用量不是 2+2+1=5,而是某一时刻重要紧急应用需求量的最大值,也就是 3 。若是咱们可以数据监测到每一个应用的真实使用量,给它分配合理值,那么就能产生资源利用率提高的实际效果。
对于电商应用,对于采用了重量级 Java 框架和相关技术栈的 Web 应用,短期内 HPA 或者 VPA 都不是件容易的事情。
先说 HPA,咱们或许能够秒级拉起了 Pod,建立新的容器,然而拉起的容器是否真的可用呢。从建立到可用,可能须要比较久的时间,对于大促和抢购秒杀-这种访问量“洪峰”可能仅维持几分钟或者十几分钟的实际场景,若是咱们等到 HPA 的副本所有可用,可能市场活动早已经结束了。
至于社区目前的 VPA 场景,删掉旧 Pod,建立新 Pod,这样的逻辑更难接受。因此综合考虑,咱们须要一个更实际的解决方案弥补 HPA 和 VPA 的在这一单机资源调度的空缺。
咱们首先要对解决方案设定一个能够交付的标准那就是—— “既要稳定性,也要利用率,还要自动化实施,固然若是可以智能化那就更好”,而后再交付标准进行细化:
上图是咱们最初的工具流程设计:当一个应用面临很高的业务访问需求时,体如今 CPU、Memory 或其余资源类型需求量变大,咱们根据 Data Collector 采集的实时基础数据,利用 Data Aggregator 生成某个容器或整个应用的画像,再将画像反馈给 Policy engine。 Policy engine 会瞬时快速修改容器 Cgroup 文件目录下的的参数。
咱们最先的架构和咱们的想法同样朴实,在 kubelet 进行了侵入式的修改。虽然咱们只是加了几个接口,可是这种方式确实不够优雅。每次 kubenrnetes 升级,对于 Policy engine 相关组件升级也有必定的挑战。
为了作到快速迭代并和 Kubelet 解耦,咱们对于实现方式进行了新的演进。那就是将关键应用容器化。这样能够达到如下功效:
固然在后续演进中,咱们也在尝试和 HPA,VPA 进行打通,毕竟这些和 Policy engine 存在着互补的关系。所以咱们架构进一步演进成以下情形。当 Policy engine 在处理一些更多复杂场景搞到无力时,上报事件让中心端作出更全局的决策。水平扩容或是垂直增长资源。
下面咱们具体讨论一下 Policy engine 的设计。Policy engine 是单机节点上进行智能调度并执行 Pod 资源调整的核心组件。它主要包括 api server,指挥中心 command center 和执行层 executor。
指挥中心按期从 data aggregator 获取容器的实时画像,包括聚合的统计数据和预测数据,首先判断节点状态,例如节点磁盘异常,或者网络不通,表示该节点已经发生异常,须要保护现场,再也不对Pod进行资源调整,以避免形成系统震荡,影响运维和调试。若是节点状态正常,指挥中心会策略规则,对容器数据进行再次过滤。好比容器 CPU 率飙高,或者容器的响应时间超过安全阈值。若是条件知足,则对知足条件的容器集合给出资源调整建议,传递给executor。
在架构设计上,咱们遵循了如下原则:
插件化:全部的规则和策略被设计为能够经过配置文件来修改,尽可能与核心控制流程的代码解耦,与 data collector 和 data aggregator 等其余组件的更新和发布解耦,提高可扩展性;
稳定,这包括如下几个方面:
自愈:资源调整等动做的执行可能会产生一些异常,咱们在每一个控制器内都加入了自愈回滚机制,保证整个系统的稳定性;
不依赖应用先验知识:为全部不一样的应用分别进行压测、定制策略,或者提早对可能排部在一块儿的应用进行压测,会致使巨大开销,可扩展性下降。咱们的策略在设计上尽量通用,尽可能采用不依赖于具体平台、操做系统、应用的指标和控制策略。
在资源调整方面,Cgroup 支持咱们对各个容器的 CPU、内存、网络和磁盘 IO 带宽资源进行隔离和限制,目前咱们主要对容器的 CPU 资源进行调整,同时在测试中探索在时分复用的场景下动态调整 memory limit 和 swap usage 而避免 OOM 的可行性;在将来咱们将支持对容器的网络和磁盘 IO 的动态调整。
上图展现了咱们在测试集群获得的一些实验结果。咱们把高优先级的在线应用和低优先级的离线应用混合部署在测试集群里。SLO 是 250ms,咱们但愿在线应用的 latency 的 95 百分位值低于阈值 250ms。
在实验结果中能够看到:
这说明了咱们的控制策略的有效性。
下面咱们总结一下在整个项目的进行过程当中,咱们收获的一些经验和教训,但愿这些经验教训可以对遇到相似问题和场景的人有所帮助。
总结起来,咱们的工做主要实现了如下几方面的收益:
展望将来,咱们但愿在如下几个方面增强和扩展咱们的工做:
**Q1:**直接修改 cgroup 容器必定会得到资源吗? **A1:**容器技术隔离的技术基础就是 cgroup 层面。在宿主机腾出足够资源的状况下,给 cgroup 设置更大的值能够获取更多的资源。同理,对于通常优先级不高的应用,设置较低的 cgroup 资源值就会达到抑制容器运行的效果。
**Q2:**底层是如何区分在线和离线优先级的? **A2:**底层是没法自动获取谁是在线,谁是离线,或者谁的优先级高,谁的优先级低的。这个咱们能够经过各类 Kubernetes 提供的扩展实现。最简单的是经过 label,Annotation 标识。固然经过扩展 QoS class 也是一种思路。社区版本的 QoS class设置太过于保守,给予用户发挥的空间不大。咱们经过这些方面也进行了加强。在合适的时候或许会推向社区。自动感知是个方向,感知谁是干扰源,感知谁是某种资源型应用,这块咱们还在研发中。作到真正的动态,确定是具有自动感知的智能系统。
Q3:“与社区版 Vertical-Pod-Autoscaler 不一样,Policy engine 不主动驱逐腾挪容器,而是直接修改容器的 cgroup 文件”,想问一下,不主动驱逐的话,若是 Node 的资源达到上线了会怎么处理? **A3:**这是一个好问题。首先这里要先区分是哪一种资源,若是是 CPU 型的,咱们能够调整低优先级容器的 cgroup 下 cpu quota 的值,首先抑制低优先级的容器对于 CPU 的争抢。而后再适当上调高优先级容器的相关资源值。若是是内存型资源,这个不能直接去缩小低优先级容器的 cgroup 值,不然会形成 OOM,对于学习内存型资源的调整,咱们会在其余分享中继续讨论。这个技术比较特殊。
**Q4:**只修改 cgroup,怎么保证 K8s 对单个物理机可以分配更多的容器? **A4:**文字直播有了必定说明,容器的资源消耗并不是是一成不变的,不少时候它们的资源消耗呈现潮汐现象,相同的资源条件下部署更多应用,完成更多做业就是达到资源利用的最大化的效果。资源出现超卖才是咱们这个主题讨论的最大价值。
**Q5:**也就是说,低优先级的容器,request 设置的比 limit 小不少,而后大家再动态的调整 cgroup? **A5:**在现有 QoS 场景下,你能够理解被调整的 Pod 都是 burstable 的。可是咱们并非直接调整 Pod 元数据的 limit 的值,而是调整 limit 在 cgroup 反映的值,这个值在资源竞争缓和的时候还会被调整回去的。咱们并不建议单机的 cgroup 数据和 etcd 的中心数据割裂过久。若是长期偏离,咱们会像 VPA 发出警报,联动 VPA 作调整。固然在容器运行的高峰期,任何重建容器的操做都是不明智的。
**Q6:**总体的理解就是大家开始就让物理机超配了必定比例的 pod,而后经过策略动态调整容器的 cgroup 值? **A6:**若是资源彻底是富足冗余的,这个动态调整也有必定意义。就是并不是资源用满场景下,高优先级应用会被干扰,实际上,当主机的 CPU 达到必定比例,打个比方例如 50%,应用的时延就变大。为了彻底确保高优先级应用的 SLO,牺牲低优先级的 CPU 正常运行也是有价值的。
**Q7:**Policy engine 有没有考虑开源? **A7:**有计划进行开源,Policy engine 更多的是和自身的应用属性相关,电商应用或者大数据处理应用的策略都是不相同的,咱们开源会首先开源框架和附带一些简单的策略,更多的策略能够用户自定义。
**Q8:**我以前遇到的大部分应用都没法正确感知 cgroup 的配置,所以不少状况都须要在启动参数里面根据 cpu 或者 mem 设置参数,那么也就是说即便改变了 cgroup 对于他们来讲都无效,那么使用场景也就有限了 **A8:**限制容器的资源使用这个仍是有价值的。限制低优先级应用自己也能够提高高优先级应用的 SLO,虽然效果没有那么明显。稳定性的考量一样也很重要。
**Q9:**Policy engine 目前在阿里的使用如何?在生产上有多上的规模使用这种方式进行动态调整?是否和社区的 HPA VPA 配合使用? **A9: **Policy engine 在阿里某些集群已经使用。至于规模暂时没法透漏。涉及到不少组件之间的联动,社区的 HPA 和 VPA 目前都不太能知足咱们的需求。所以阿里的 HPA 和 VPA 都是咱们自行开发的,可是和社区的原理是一致的。阿里 HPA 的开源能够关注 Openkruise 社区。VPA 开源计划我这里尚未确切消息。
**Q10:**当单机节点资源不足以提供容器扩容时,目前是否能够进行 HPA 或 VPA 扩容呢? **A10:**单机节点不足的时候,应用能够经过 HPA 进行增长副本应对。可是 VPA 若是选择原节点进行更新的话,是失败的。只能调度到其余资源丰富的节点。在流量陡升的场景下,重建容器未必能知足需求,极可能致使雪崩,即重建过程当中,整个应用其余未升级的副本接受更多流量,OOM 掉,新启动的容器再瞬间被 OOM,因此重启容器须要慎重。快速扩容(HPA)或者快速提高高优先级资源,抑制低优先级容器资源的方式效果更明显。
关注『阿里巴巴云原生』公众号,回复关键词“1010”,可获取本文 PPT。
“ 阿里巴巴云原生微信公众号(ID:Alicloudnative)关注微服务、Serverless、容器、Service Mesh等技术领域、聚焦云原生流行技术趋势、云原生大规模的落地实践,作最懂云原生开发者的技术公众号。”
原文出处:https://www.cnblogs.com/alisystemsoftware/p/11658705.html