如何为云原生应用带来稳定高效的部署能力?

时间:2021-07-15 | 标签: | 作者:Q8 | 来源:酒祝 墨封网络

小提示:您能找到这篇{如何为云原生应用带来稳定高效的部署能力?}绝对不是偶然,我们能帮您找到潜在客户,解决您的困扰。如果您对本页介绍的如何为云原生应用带来稳定高效的部署能力?内容感兴趣,有相关需求意向欢迎拨打我们的服务热线,或留言咨询,我们将第一时间联系您!

< background-color: rgb(255, 255, 255); color: rgb(36, 41, 46);">作者 | 酒祝  阿里云技术专家、墨封  阿里云开发工程师

< font-size: 16px;">直播完整视频回顾:躲猫猫事件公关危机< font-size: 16px;">https://www.bilibili.com/video/BV1mK4y1t7WS/

关注“阿里巴巴云原生”公众号,后台回复 “528” 即可下载 PPT

< font-size: 16px;">5 月 28 日,我们发起了第 3 期 SIG Cloud-Provider-Alibaba 网研会直播。本次直播主要介绍了阿里经济体大规模应用上云过程中遇到的核心部署问题、采取的对应解决方案,以及这些方案沉淀为通用化能力输出开源后,如何帮助阿里云上的用户提升应用部署发布的效率与稳定性。

< font-size: 16px;">本文汇集了此次直播完整视频回顾及资料下载,并整理了直播过程中收集的问题和解答,希望能够对大家有所帮助~

< ">前言

< font-size: 16px;">随着近年来 Kubernetes 逐渐成为事实标准和大量应用的云原生化,我们往往发现 Kubernetes 的原生 workload 对大规模化应用的支持并不十分“友好”。如何在 Kubernetes 上为应用提供更加完善、高效、灵活的部署发布能力,成为了我们探索的目标。

< font-size: 16px;">本文将会介绍在阿里经济体全面接入云原生的过程中,我们在应用部署方面所做的改进优化、实现功能更加完备的增强版 workload、并将其开源到社区,使得现在每一位 Kubernetes 开发者和阿里云上的用户都能很便捷地使用上阿里巴巴内部云原生应用所统一使用的部署发布能力。

  • < font-size: 16px;">第一期网研会回顾< font-size: 16px;">Kubernetes SIG-Cloud-Provider-Alibaba 首次网研会(含 PPT 下载)

  • < font-size: 16px;">第二期网研会回顾< font-size: 16px;">在生产环境中,阿里云如何构建高性能云原生容器网络?(含 PPT 下载)

< font-size: 16px;">< ">阿里应用场景与原生 workloads

< font-size: 16px;">阿里巴巴容器化道路的起步在国内外都是比较领先的。容器这个技术概念虽然出现得很早,但一直到 2013 年 Docker 产品出现后才逐渐为人所熟知。而阿里巴巴早在 2011 年就开始发展了基于 LXC 的容器技术,经过了几代的系统演进,如今阿里巴巴有着超过百万的容器体量,这个规模在世界范围内都是顶尖的。

< font-size: 16px;">随着云技术发展和云原生应用的兴起,我们近两年间逐步将过去的容器迁到了基于 Kubernetes 的云原生环境中。而在这其中,我们遇到了不少应用部署方面的问题。首先对于应用开发者来说,他们对迁移到云原生环境的期望是:

  • < font-size: 16px;">面向丰富业务场景的策略功能

  • < font-size: 16px;">极致的部署发布效率

  • < font-size: 16px;">运行时的稳定性和容错能力

< font-size: 16px;">阿里的应用场景非常复杂,基于 Kubernetes 之上生长着很多不同的 PaaS 二层,比如服务于电商业务的运维中台、规模化运维、中间件、Serverless、函数计算等,而每个平台都对部署、发布要求各有不同。

< font-size: 16px;">我们再来看一下 Kubernete 原生所提供的两种常用 workload 的能力:

< font-size: 16px;">简单来说,Deployment 和 StatefulSet 在一些小规模的场景下是可以 work 的;但到了阿里巴巴这种应用和容器的规模下,如果全量使用原生 workload 则是完全不现实的。目前阿里内部容器集群上的应用数量超过十万、容器数量达到百万,有部分重点核心应用甚至单个应用下就有上万的容器。再结合上图的问题,我们会发现不仅针对单个应用的发布功能不足,而且当发布高峰期大量应用同时在升级时,超大规模的 Pod 重建也成为一种“灾难”。

< font-size: 16px;">阿里自研的扩展 workloads

< font-size: 16px;">针对原生 workload 远远无法满足应用场景的问题,我们从各种复杂的业务场景中抽象出共通的应用部署需求,据此开发了多种扩展 workload。在这些 workload 中我们做了大幅的增强和改进,但同时也会严格保证功能的通用化、不允许将业务逻辑耦合进来。

< font-size: 16px;">这里我们重点介绍一下 CloneSet 与 Advanced StatefulSet。在阿里内部云原生环境下,几乎全量的电商相关应用都统一采用 CloneSet 做部署发布,而中间件等有状态应用则使用了 Advanced StatefulSet 管理。

< font-size: 16px;">Advanced StatefulSet 顾名思义,是原生 StatefulSet 的增强版,默认行为与原生完全一致,在此之外提供了原地升级、并行发布(最大不可用)、发布暂停等功能。而 CloneSet 则对标原生 Deployment,主要服务于无状态应用,提供了最为全面丰富的部署发布策略。

< font-size: 16px;">原地升级

< font-size: 16px;">CloneSet、Advanced StatefulSet 均支持指定 Pod 升级方式:

  1. < font-size: 16px;">ReCreate:重建 Pod 升级,和原生 Deployment/StatefulSet 一致;

  2. < font-size: 16px;">InPlaceIfPossible:如果只修改 image 和 metadata 中的 labels/annotations 等字段,则触发 Pod 原地升级;如果修改了其他 template spec 中的字段,则退化到 Pod 重建升级;

  3. < font-size: 16px;">InPlaceOnly:只允许修改 image 和 metadata 中的 labels/annotations 等字段,只会使用原地升级。

< font-size: 16px;">所谓原地升级,就是在升级 template 模板的时候,workload 不会把原 Pod 删除、新建,而是直接在原 Pod 对象上更新对应的 image 等数据。

< font-size: 16px;">如上图所示,在原地升级的时候 CloneSet 只会更新 Pod spec 中对应容器的 image,而后 kubelet 看到 Pod 中这个容器的定义发生了变化,则会把对应的容器停掉、拉取新的镜像、并使用新镜像创建启动容器。另外可以看到在过程中,这个 Pod 的 sandbox 容器以及其他本次未升级的容器还一直处于正常运行状态,只有需要升级的容器会受到影响。



< font-size: 16px;">原地升级给我们带来的好处实在太多了:

  • < font-size: 16px;">首先就是发布效率大大提升了,根据非完全统计数据,在阿里环境下原地升级至少比完全重建升级提升了 80% 以上的发布速度:不仅省去了调度、分配网络、分配远程盘的耗时,连拉取新镜像的时候都得益于 node 上已有旧镜像、只需要拉取较少的增量 layer);

  • < font-size: 16px;">IP 不变、升级过程 Pod 网络不断,除本次升级外的其他容器保持正常运行;

  • < font-size: 16px;">Volume 不变,完全复用原容器的挂载设备;

  • < font-size: 16px;">保障了集群确定性,使排布拓扑能通过大促验证。

< font-size: 16px;">后续我们将会有专文讲解阿里在 Kubernetes 之上做的原地升级,意义非常重大。如果没有了原地升级,阿里巴巴内部超大规模的应用场景几乎是无法在原生 Kubernetes 环境上完美落地的,我们也鼓励每一位 Kubernetes 用户都应该“体验”一下原地升级,它给我们带来了不同于 Kubernetes 传统发布模式的变革。

< font-size: 16px;">流式+分批发布

< font-size: 16px;">前一章我们提到了,目前 Deployment 支持 maxUnavailable/maxSurge 的流式升级,而 StatefulSet 支持 partition 的分批升级。但问题在于,Deployment 无法灰度分批,而 StatefulSet 则只能一个一个 Pod 串行发布,没办法并行的流式升级。

< font-size: 16px;">首先要说的是,我们将 maxUnavailable 引入了 Advanced StatefulSet。原生 StatefulSet 的 one by one 发布,大家其实可以理解为一个强制 maxUnavailable=1 的过程,而 Advanced StatefulSet 中如果我们配置了更大的 maxUnavailable,那么就支持并行发布更多的 Pod 了。

< font-size: 16px;">然后我们再来看一下 CloneSet,它支持原生 Deployment 和 StatefulSet 的全部发布策略,包括 maxUnavailable、maxSurge、partition。那么 CloneSet 是如何把它们结合在一起的呢?我们来看一个例子:

< font-size: 16px;">apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
# ...
spec:
 replicas: 5          # Pod 总数为 5
 updateStrategy:
   type: InPlaceIfPossible
   maxSurge: 20%      # 多扩出来 5 * 20% = 1 个 Pod (rounding up)
   maxUnavailable: 0  # 保证发布过程 5 - 0 = 5 个 Pod 可用
   partition: 3       # 保留 3 个旧版本 Pod (只发布 5 - 3 = 2 个 Pod)

< font-size: 16px;">针对这个副本数为 5 的 CloneSet,如果我们修改了 template 中的 image,同时配置:maxSurge=20%  maxUnavailable=0  partition=3。当开始发布后:

  1. < font-size: 16px;">先扩出来 1 个新版本的 Pod,5 个存量 Pod 保持不动;

  2. < font-size: 16px;">新 Pod ready 后,逐步把旧版本 Pod 做原地升级;

  3. < font-size: 16px;">直到剩余 3 个旧版本 Pod 时,因为满足了 partition 终态,会把新版本 Pod 再删除 1 个;

  4. < font-size: 16px;">此时 Pod 总数仍然为 5,其中 3 个旧版本、1 个新版本。

< font-size: 16px;">如果我们接下来把 partition 调整为 0,则 CloneSet 还是会先扩出 1 个额外的新版 Pod,随后逐渐将所有 Pod 升级到新版,最终再次删除一个 Pod,达到 5 个副本全量升级的终态。

< font-size: 16px;">发布顺序可配置

< font-size: 16px;">对于原生的 Deployment 和 StatefulSet,用户是无法配置发布顺序的。Deployment 下的 Pod 发布顺序完全依赖于它修改 ReplicaSet 后的扩缩顺序,而 StatefulSet 则严格按照 order 的反序来做一一升级。

< font-size: 16px;">但在 CloneSet 和 Advanced StatefulSet 中,我们增加了发布顺序的可配置能力,使用户可以定制自己的发布顺序。目前可以通过以下两种发布优先级和一种发布打散策略来定义顺序:

  • < font-size: 16px;">优先级(1):按给定 label key,在发布时根据 Pod labels 中这个 key 对应的 valu舆情监测服务哪家好e 值作为权重:

< font-size: 16px;">apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
spec:
 # ...
 updateStrategy:
   priorityStrategy:
     orderPriority:
       - orderedKey: some-label-key

  • < font-size: 16px;">优先级(2):按 selector 匹配计算权重,发布时根据 Pod 对多个 weight selector 的匹配情况计算权重总和:

< font-size: 16px;">apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
spec:
 # ...
 updateStrategy:
   priorityStrategy:
     weightPriority:
     - weight: 50
       matchSelector:
         matchLabels:
           test-key: foo
     - weight: 30
       matchSelector:
         matchLabels:
           test-key: bar

  • < font-size: 16px;">打散:将匹配 key-value 的 Pod 打散到不同批次中发布:

< font-size: 16px;">apiVersion: apps.kruise.io/v1alpha1
kind: CloneSet
spec:
 # ...
 updateStrategy:
   scatterStrategy:
   - key: some-label-key
     value: foo



< font-size: 16px;">可能有同学会问为什么要配置发布顺序呢?比如 zookeeper 这类应用在发布时,需要先把所有非主节点升级,最后再升级主节点,这样才能保证在整个发布过程中只会发生一次切主。这时用户就可以通过流程打标、或者写一个 operator 自动为 zookeeper 的 Pod 打上节点职责的标签,而后配置非主节点的发布权重较大,使得发布时能够尽量减少切主的次数。

< font-size: 16px;">sidecar 容器管理

< font-size: 16px;">轻量化容器也是阿里巴巴在云原生阶段的一次重大改革,过去阿里的容器绝大多数都是以“富容器”的方式运行的,所谓“富容器”即在一个容器中既运行业务、也跑着各种各样的插件和守护进程。而在云原生时代,我们在逐渐把原先“富容器”中的旁路插件拆分到独立的 sidecar 容器中,使主容器逐渐回归业务自身。

< font-size: 16px;">这里对于拆分的好处就不赘述了,我们来看下另一个问题,就是拆分之后这些 sidecar 容器如何做管理呢?最直观的方式是在每个应用的 workload 中显示去定义 Pod 中需要的 sidecar,但这样带来的问题很多:

  1. < font-size: 16px;">当应用和 workload 数量众多时,我们很难统一的 sidecar 增减管理;

  2. < font-size: 16px;">应用开发者不知道(甚至也不关心)自己的应用需要配置哪些 sidecar 容器;

  3. < font-size: 16px;">当 sidecar 镜像需要升级时,要把所有应用的 workload 全部升级一遍,很不现实。

< font-size: 16px;">因此,我们设计了 SidecarSet,将 sidecar 容器的定义与应用 workload 解耦。应用开发者们不再需要再关心自己的 workload 中需要写哪些 sidecar 容器,而通过原地升级, sidecar 维护者们也可以自主地管理和升级 sidecar 容器。

< font-size: 16px;">开放能力应用

< font-size: 16px;">到了这里,大家是不是对阿里巴巴的应用部署模式有了一个基本的了解呢?其实上述的能力都已经开源到了社区,我们的项目就叫做 < font-size: 16px;">OpenKruise< font-size: 16px;">,目前它已经提供了 5 种扩展 workload:

  • < font-size: 16px;">CloneSet< font-size: 16px;">:提供了更加高效、确定可控的应用管理和部署能力,支持优雅原地升级、指定删除、发布顺序可配置、并行/灰度发布等丰富的策略,可以满足更多样化的应用场景;

  • < font-size: 16px;">Advanced StatefulSet< font-size: 16px;">:基于原生 < font-size: 16px;">StatefulSet< font-size: 16px;"> 之上的增强版本,默认行为与原生完全一致,在此之外提供了原地升级、并行发布(最大不可用)、发布暂停等功能;

  • < font-size: 16px;">SidecarSet< font-size: 16px;">:对 sidecar 容器做统一管理,在满足 selector 条件的 Pod 中注入指定的 sidecar 容器;

  • < font-size: 16px;">UnitedDeployment< font-size: 16px;">:通过多个 subset workload 将应用部署到多个可用区;

  • < font-size: 16px;">BroadcastJob< font-size: 16px;">:配置一个 job,在集群中所有满足条件的 Node 上都跑一个 Pod 任务。

< font-size: 16px;">此外,我们还有更多的扩展能力还在开源的路上!近期,我们会将内部的 Advanced DaemonSet 开放到 OpenKruise 中,它在原生 DaemonSet 的 maxUnavailable 之上,额外提供了如分批、selector 等发布策略,分批的功能使 DaemonSet 在发布的时候能够只升级其中部分 Pod,而 selector 更是允许发布的时候指定先在符合某些标签的 node 上升级,这为我们在大规模集群中升级 DaemonSet 带来了灰度能力和稳定性的保障。

< font-size: 16px;">而后续,网络整合营销推广我们还计划将阿里巴巴内部扩展的 HPA、调度插件等通用化能力开放出来,让每一位 Kubernetes 开发者和阿里云上的用户都能很便捷地使用上阿里内部开发应用的云原生增强能力。

< font-size: 16px;">最后,我们也欢迎每一位云原生爱好者来共同参与 OpenKruise 的建设。与其他一些开源项目不同,OpenKruise 并不是阿里内部代码的复刻;恰恰相反,OpenKruise Github 仓库是阿里内部代码库的 upstream。因此,每一行你贡献的代码,都将运行在阿里内部的所有 Kubernetes 集群中、都将共同支撑了阿里巴巴全球顶尖规模的应用场景!

如何为云原生应用带来稳定高效的部署能力?

上一篇:优化Shopee Listing应该这样做(下)
下一篇:谷歌不收录?4个步骤将你的URL提交给Google


版权声明:以上主题为“如何为云原生应用带来稳定高效的部署能力?"的内容可能是本站网友自行发布,或者来至于网络。如有侵权欢迎联系我们客服QQ处理,谢谢。
相关内容
推荐内容
扫码咨询
    如何为云原生应用带来稳定高效的部署能力?
    打开微信扫码或长按识别二维码

小提示:您应该对本页介绍的“如何为云原生应用带来稳定高效的部署能力?”相关内容感兴趣,若您有相关需求欢迎拨打我们的服务热线或留言咨询,我们尽快与您联系沟通如何为云原生应用带来稳定高效的部署能力?的相关事宜。

关键词:如何为云原生应用带来稳

关于 | 业务 | 案例 | 免责 | 隐私
客服邮箱:sales@1330.com.cn
电话:400-021-1330 | 客服QQ:865612759
沪ICP备12034177号 | 沪公网安备31010702002418号