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

本文涉及的产品
容器服务 Serverless 版 ACK Serverless,952元额度 多规格
容器服务 Serverless 版 ACK Serverless,317元额度 多规格
简介: 本文将会介绍在阿里经济体全面接入云原生的过程中,我们在应用部署方面所做的改进优化、实现功能更加完备的增强版 workload、并将其开源到社区,使得现在每一位 Kubernetes 开发者和阿里云上的用户都能很便捷地使用上阿里巴巴内部云原生应用所统一使用的部署发布能力。

image.png

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

阿里应用场景与原生 workloads

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

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

  • 面向丰富业务场景的策略功能
  • 极致的部署发布效率
  • 运行时的稳定性和容错能力

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

我们再来看一下 Kubernete 原生所提供的两种常用 workload 的能力:

image.png

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

阿里自研的扩展 workloads

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

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

image.png

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

原地升级

CloneSet、Advanced StatefulSet 均支持指定 Pod 升级方式:

  1. ReCreate:重建 Pod 升级,和原生 Deployment/StatefulSet 一致;
  2. InPlaceIfPossible:如果只修改 image 和 metadata 中的 labels/annotations 等字段,则触发 Pod 原地升级;如果修改了其他 template spec 中的字段,则退化到 Pod 重建升级;
  3. InPlaceOnly:只允许修改 image 和 metadata 中的 labels/annotations 等字段,只会使用原地升级。

所谓原地升级,就是在升级 template 模板的时候,workload 不会把原 Pod 删除、新建,而是直接在原 Pod 对象上更新对应的 image 等数据。

image.png

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

原地升级给我们带来的好处实在太多了:

  • 首先就是发布效率大大提升了,根据非完全统计数据,在阿里环境下原地升级至少比完全重建升级提升了 80% 以上的发布速度:不仅省去了调度、分配网络、分配远程盘的耗时,连拉取新镜像的时候都得益于 node 上已有旧镜像、只需要拉取较少的增量 layer);
  • IP 不变、升级过程 Pod 网络不断,除本次升级外的其他容器保持正常运行;
  • Volume 不变,完全复用原容器的挂载设备;
  • 保障了集群确定性,使排布拓扑能通过大促验证。

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

流式+分批发布

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

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

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

1.png

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

  1. 先扩出来 1 个新版本的 Pod,5 个存量 Pod 保持不动;
  2. 新 Pod ready 后,逐步把旧版本 Pod 做原地升级;
  3. 直到剩余 3 个旧版本 Pod 时,因为满足了 partition 终态,会把新版本 Pod 再删除 1 个;
  4. 此时 Pod 总数仍然为 5,其中 3 个旧版本、1 个新版本。

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

发布顺序可配置

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

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

  • 优先级(1):按给定 label key,在发布时根据 Pod labels 中这个 key 对应的 value 值作为权重:

2.png

  • 优先级(2):按 selector 匹配计算权重,发布时根据 Pod 对多个 weight selector 的匹配情况计算权重总和:

3.png

  • 打散:将匹配 key-value 的 Pod 打散到不同批次中发布:

4.png

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

sidecar 容器管理

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

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

  1. 当应用和 workload 数量众多时,我们很难统一的 sidecar 增减管理;
  2. 应用开发者不知道(甚至也不关心)自己的应用需要配置哪些 sidecar 容器;
  3. 当 sidecar 镜像需要升级时,要把所有应用的 workload 全部升级一遍,很不现实。

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

image.png

开放能力应用

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

  • CloneSet:提供了更加高效、确定可控的应用管理和部署能力,支持优雅原地升级、指定删除、发布顺序可配置、并行/灰度发布等丰富的策略,可以满足更多样化的应用场景;
  • Advanced StatefulSet:基于原生 StatefulSet 之上的增强版本,默认行为与原生完全一致,在此之外提供了原地升级、并行发布(最大不可用)、发布暂停等功能;
  • SidecarSet:对 sidecar 容器做统一管理,在满足 selector 条件的 Pod 中注入指定的 sidecar 容器;
  • UnitedDeployment:通过多个 subset workload 将应用部署到多个可用区;
  • BroadcastJob:配置一个 job,在集群中所有满足条件的 Node 上都跑一个 Pod 任务。

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

而后续,我们还计划将阿里巴巴内部扩展的 HPA、调度插件等通用化能力开放出来,让每一位 Kubernetes 开发者和阿里云上的用户都能很便捷地使用上阿里内部开发应用的云原生增强能力。

Q & A

Q1:目前阿里最大规模的业务 pod 数量有多少,发布一次需要多少时间?
A1:这个只能透露数量目前最大规模的单个应用下数量是以万为单位的,一次发布时间要看具体分批灰度的时长了。如果分批较多、观察时间较长的话,可能是会持续一两周的。

Q2:pod 的资源 request 和 limit 是怎么配置的?request 和 limit 是什么比例来配置?过多的 request 造成浪费,过少可能会导致热点 node 负载超高。
A2:这个主要还是根据应用的需求来定的,目前大部分在线应用都是 1:1 的关系,部分离线和job 类型的会配置 request>limit。

Q3:kruise 升级问题,升级 kurise apiversion 版本的情况下,原有的版本的部署如何升级?
A3:目前 kruise 中资源的 apiVersion 还都是统一的。我们计划在今年下半年将部分较为成熟的 workload 进行版本升级,用户在自己的 K8s 集群内升级后,存量的旧版本资源会自动通过 conversion 升级到新版本。

Q4:OpenKruise 有提供 go-client 吗?
A4:目前提供两个方式:1. 引入 github.com/openkruise/kruise/pkg/client 包,下面有生成好的 clientset / informer / lister 等工具;2. 使用 controller-runtime 的用户(包括 kubebuilder、operator-sdk),直接引入 github.com/openkruise/kruise-api 轻量化依赖,然后加到 scheme 里就能直接用了。

Q5:阿里 K8s 版本升级是如何做的?
A5:阿里集团内部使用 Kube-On-Kube 的架构进行大规模的 Kubernetes 集群管理,用一个元 K8s 集群管理成百上千个业务 K8s 集群。其中元集群版本较为稳定,业务集群会进行频繁升级,业务集群的升级流程事实上就是对元集群中的 workloads(原生 workloads 以及 kruise workloads) 进行版本或配置升级,与正常情况我们对业务 workloads 的升级流程相似。

Q6:这个灰度之后,流量是怎么切的?
A6:在原地升级前,kruise 会先通过 readinessGate 将 Pod 置为 not-ready,此时 endpoint 等控制器会感知到并把 Pod 从端点摘掉。然后 kruise 更新 pod image 触发容器重建,完成后再把 Pod 改为 ready。

Q7:daemonset 的分批是通过类似 deployment 的暂停功能实现的么?统计已经发布数量然后暂停,然后继续,然后再暂停。
A7:总体过程上类似,升级过程中对新旧版本进行统计并判断是否已达到指定终态。但相比 deployment,daemonset 需要处理比较复杂的边界情况(例如初次发布时集群中并没有指定的 Pod),具体细节可以持续关注我们即将开源的代码。

Q8:多集群发布页面上怎么开始发布的?
A8:直播中演示的是一个 demo 的发布系统结合 Kruise Workloads 的例子,从交互上是通过用户选择对应的集群,点击开始执行进行发布;从实现上实际是对新版本的 YAML 与集群中的 YAML 计算 diff 后 Patch 进集群,再操作 DaemonSet 的控制字段(partition / paused 等),控制灰度进程。

本文转自<阿里巴巴云原生技术圈>——阿里巴巴云原生小助手

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
26天前
|
Cloud Native 安全 物联网
云原生技术在现代软件开发中的应用与挑战####
云原生,这一词汇如同一股强劲的科技风暴,席卷了整个信息技术领域,它不仅重塑了软件的开发模式,还引领了一场关于效率、可扩展性和弹性的深刻变革。本文旨在深入探讨云原生技术的核心概念,分析其在现代软件开发中的广泛应用,并直面伴随其发展而来的挑战,为读者勾勒出一幅既充满机遇又不乏考验的云原生技术图景。 ####
|
7天前
|
Kubernetes Cloud Native 持续交付
云原生技术在现代软件开发中的应用与挑战
【10月更文挑战第37天】随着云计算技术的不断演进,云原生技术已经成为推动软件开发现代化的重要力量。本文将深入探讨云原生技术的核心概念、优势以及面临的挑战,并通过一个实际的代码示例,展示如何在云原生环境中部署一个简单的应用。我们将从云原生的基础架构出发,逐步引导读者理解其在现代软件开发中的关键作用。
20 1
|
18天前
|
监控 Cloud Native 持续交付
云原生技术深度解析:重塑现代应用开发与部署范式####
本文深入探讨了云原生技术的核心概念、关键技术组件及其在现代软件开发中的重要性。通过剖析容器化、微服务架构、持续集成/持续部署(CI/CD)等关键技术,本文旨在揭示云原生技术如何促进应用的敏捷性、可扩展性和高可用性,进而推动企业数字化转型进程。不同于传统摘要仅概述内容要点,本部分将融入具体案例分析,直观展示云原生技术在实际应用中的显著成效与挑战应对策略,为读者提供更加丰富、立体的理解视角。 ####
|
21天前
|
敏捷开发 Cloud Native 持续交付
云原生技术在现代企业中的应用与实践
【10月更文挑战第23天】本文将深入探讨云原生技术在现代企业中的广泛应用,并结合具体案例分析其对企业数字化转型的推动作用。我们将从云原生技术的基本原理出发,逐步揭示其在提高业务敏捷性、降低成本和增强系统可靠性方面的优势。同时,文章还将分享一系列成功实施云原生技术的企业案例,为读者提供实践中的参考和启示。最后,我们将讨论云原生技术面临的挑战及未来的发展趋势,为企业在这一领域的进一步探索提供指导。
|
22天前
|
Cloud Native 持续交付 云计算
云原生技术深度探索:构建现代化应用的基石####
【10月更文挑战第21天】 本文将深入探讨云原生技术的核心概念、关键技术及其在现代软件开发中的应用。我们将从容器化、微服务架构、持续集成/持续部署(CI/CD)、无服务器架构等关键方面展开,揭示这些技术如何共同作用,帮助企业实现高效、弹性且易于维护的应用部署与管理。通过实例分析,展现云原生技术在实际项目中的显著优势,为读者提供一套全面理解并应用云原生技术的指南。 ####
31 2
|
27天前
|
运维 Cloud Native 持续交付
云原生技术在现代IT架构中的深度应用与挑战####
【10月更文挑战第17天】 本文深入剖析了云原生技术的精髓,探讨其在现代IT架构转型中的核心作用与面临的挑战。云原生不仅是一种技术实现,更是企业数字化转型的重要推手,通过容器化、微服务、持续集成/持续部署(CI/CD)等关键要素,重塑软件开发、部署与运维模式。文章首先概述了云原生的基本原则与核心组件,随后分析了其如何促进企业敏捷性、可扩展性和资源利用率的提升,同时也指出了在安全性、复杂性管理及人才技能匹配等方面存在的挑战,并提出了相应的对策建议。 ####
66 6
|
29天前
|
Kubernetes Cloud Native 持续交付
云原生技术:重塑现代应用开发与部署模式####
本文深入探讨了云原生技术的核心概念、发展历程及其在现代软件开发和部署中的关键作用。通过分析云原生架构的特点,如容器化、微服务、持续集成与持续部署(CI/CD),以及它如何促进应用的可伸缩性、灵活性和效率,本文旨在为读者提供一个关于云原生技术全面而深入的理解。此外,还将探讨实施云原生策略时面临的挑战及应对策略,帮助组织更好地把握数字化转型的机遇。 ####
|
29天前
|
运维 监控 Cloud Native
云原生技术在现代企业中的应用与挑战####
【10月更文挑战第15天】 本文深入探讨了云原生技术如何重塑企业的IT架构,并分析了其带来的机遇与面临的挑战。通过案例分析,揭示了云原生技术在提升业务敏捷性、降低运维成本方面的显著优势,同时也指出了在安全性、多云管理等方面的潜在难题,为企业决策者提供了有价值的参考。 ####
25 3
|
13天前
|
监控 Cloud Native 微服务
云端漫步:探索云原生应用的构建与部署
【10月更文挑战第32天】在数字时代的浪潮中,云原生技术如同一艘航船,承载着企业的梦想驶向未知的海洋。本文将带你领略云原生应用的魅力,从基础概念到实战操作,我们将一步步揭开云原生的神秘面纱,体验它如何简化开发、加速部署,并提升系统的可扩展性与可靠性。让我们一起启航,探索云原生的世界!
|
16天前
|
Cloud Native 安全 持续交付
云原生技术在现代软件开发中的应用与挑战####
本文深入探讨了云原生技术在现代软件开发中的广泛应用及其面临的主要挑战,旨在为开发者和企业提供实用的指导和策略。云原生技术通过其独特的架构和方法论,极大地提升了软件的可扩展性、弹性和敏捷性。然而,随着技术的不断演进,如何有效应对其在安全性、复杂性和成本控制等方面的挑战,成为了业界关注的焦点。本文将详细阐述云原生技术的核心概念、实际应用案例,并针对当前面临的主要挑战提出相应的解决策略。 ####

热门文章

最新文章