云原生下的灰度体系建设

头图.png

做者 | 墨封 来源 | 阿里巴巴云原生公众号node

一周前,咱们介绍了《面对大规模 K8s 集群,如何先于用户发现问题》web

本篇文章,咱们将继续为你们介绍 ASI SRE(ASI,Alibaba Serverless infrastructure,阿里巴巴针对云原生应用设计的统一基础设施) 是如何探索在 Kubernetes 体系下,建设 ASI 自身基础设施在大规模集群场景下的变动灰度能力的。api

咱们面临着什么

ASI 诞生于阿里巴巴集团全面上云之际,承载着集团大量基础设施全面云原生化的同时,自身的架构、形态也在不断地演进。网络

ASI 总体上主要采用 Kube-on-Kube 的架构,底层维护了一个核心的 Kubernetes 元集群,并在该集群部署各个租户集群的 master 管控组件:apiserver、controller-manager、scheduler,以及 etcd。而在每一个业务集群中,则部署着各种 controller、webhook 等 addon 组件,共同支撑 ASI 的各项能力。而在数据面组件层面,部分 ASI 组件以 DaemonSet 的形式部署在节点上,也有另外一部分采用 RPM 包的部署形式。架构

1.jpg

同时,ASI 承载了集团、售卖区场景下数百个集群,几十万的节点。即使在 ASI 建设初期,其管辖的节点也达到了数万的级别。在 ASI 自身架构快速发展的过程当中,组件及线上变动至关频繁,早期时单日 ASI 的组件变动能够达到数百次。而 ASI 的核心基础组件诸如 CNI 插件、CSI 插件、etcd、Pouch 等,不管任意之一的错误变动均可能会引发整个集群级别的故障,形成上层业务不可挽回的损失。app

2.jpg

简而言之,集群规模大、组件数量多,变动频繁以及业务形态复杂是在 ASI,或其余 Kubernetes 基础设施层建设灰度能力和变动系统的几大严峻挑战。当时在阿里巴巴内部,ASI/Sigma 已有数套现有的变动系统,但都存在必定的局限性。less

  • 天基:具有通用的节点发布的能力,但不包括集群、节点集等 ASI 的元数据信息。
  • UCP:早期 sigma 2.0 的发布平台,年久失修。
  • sigma-deploy:sigma 3.x 的发布平台,以镜像 patch 的形式更新 deployment/daemonset。
  • asi-deploy:早期 ASI 的发布平台,管理了 ASI 自身的组件,仅支持镜像 patch,只针对 Aone 的 CI/CD 流水线作适配,以及支持在多个不一样环境间灰度,但灰度粒度较粗。

由此,咱们但愿借鉴前面几代 sigma/ASI 的发布平台历史,从变动时入手,以系统能力为主,再辅以流程规范,逐步构建 ASI 体系下的灰度体系,建设 Kubernetes 技术栈下的运维变动平台,保障数以千计的大规模集群的稳定性。运维

预设和思路

ASI 自身架构和形态的发展会极大地影响其自身的灰度体系建设方式,所以在 ASI 发展的早期,咱们对 ASI 将来的形态作了以下大胆的预设:ide

  1. 以 ACK 为底座:ACK(阿里云容器服务)提供了云的各类能力,ASI 将基于复用这些云的能力,同时将阿里巴巴集团内积累的先进经验反哺云。
  2. 集群规模大:为提升集群资源利用率,ASI 将会以大集群的方式存在,单个集群提供公共资源池来承载多个二方租户。
  3. 集群数量多:ASI 不只按 Region 维度进行集群划分,还会按照业务方等维度划分独立的集群。
  4. Addon 数量多:Kubernetes 体系是一个开放架构,会衍生出很是多 operator,而这些 operator 会和 ASI 核心组件一块儿共同对外提供各类能力。
  5. 变动场景复杂:ASI 的组件变动场景将不止镜像发布形式,Kubernetes 声明式的对象生命周期管理注定了变动场景的复杂性。

基于以上几个假设,咱们可以总结在 ASI 建设初期,亟待解决的几个问题:单元测试

  1. 如何在单个大规模集群中建设变动的灰度能力?
  2. 如何在多个集群间创建规模化的变动灰度能力?
  3. 在组件数量、种类众多的状况下,如何保证进行组件管理并保证组件每次的发布不会影响线上环境?

3.png

咱们转换一下视角,脱离集群的维度,尝试从组件的角度来解决变动的复杂性。对于每一个组件,它的生命周期能够大致划分为需求和设计阶段,研发阶段和发布阶段。对于每一个阶段咱们都但愿进行规范化,并解决 Kubernetes 自己的特色,将固定的规范落到系统中,以系统能力去保证灰度过程。

结合 ASI 的形态和变动场景的特殊性,咱们从如下几点思路出发去系统化建设 ASI 的灰度体系:

  • 需求和设计阶段

    • 方案 TechReview
    • 组件上线变动会审
  • 组件研发阶段

    • 标准化组件研发流程
  • 组件发布变动阶段

    • 提供组件工做台能力进行组件的规模化管理
    • 建设 ASI 元数据,细化灰度单元
    • 建设 ASI 单集群、跨集群的灰度能力

灰度体系建设

1. 研发流程标准化

ASI 核心组件的研发流程能够总结为如下几个流程:

针对 ASI 自身的核心组件,咱们与质量技术团队的同窗共同建设了 ASI 组件的 e2e 测试流程。除了组件自身的单元测试、集成测试外,咱们单独搭建了单独的 e2e 集群,用做常态化进行的 ASI 总体的功能性验证和 e2e 测试。

4.jpg

从单个组件视角入手,每一个组件的新功能通过研发后,进行 Code Review 经过并合入 develop 分支,则当即触发进行 e2e 流程,经过 chorus(云原生测试平台) 系统构建镜像后,由 ASIOps(ASI 运维管控平台) 部署到对应的 e2e 集群,执行标准的 Kubernetes Conformance 套件测试任务,验证 Kubernetes 范围内的功能是否正常。仅当全部测试 case 经过,该组件的版本才可标记为可推平版本,不然后续的发布将会受到管控限制。

然而正如上文提到,Kubernetes 开放的架构意味着它不只仅包含管控、调度等核心组件,集群的功能还很大程度依赖于上层的 operator 来共同实现。所以 Kubernetes 范围内的白盒测试并不能覆盖全部的 ASI 的适用场景。底层组件功能的改变颇有大程度会影响到上层 operator 的使用,所以咱们在白盒 Conformance 的基础上增长了黑盒测试用例,它包含对各种 operator 自身的功能验证,例如从上层 paas 发起的扩缩容,校验发布链路的 quota 验证等能力,常态化运行在集群中。

5.jpg

2. 组件规模化管理

针对 ASI 组件多、集群多的特色,咱们在原有 asi-deploy 功能之上进行拓展,以组件为切入点,加强组件在多集群间的管理能力,从镜像管理演进成了YAML 管理

6.jpg

基于 Helm Template 的能力,咱们将一个组件的 YAML 抽离成模板、镜像和配置三部分,分别表示如下几部分信息:

  • 模板:YAML 中在全部环境固定不变的信息,例如 apiVersion,kind 等;
  • 镜像:YAML 中与组件镜像相关的信息,指望在单一环境或者全部集群中保持一致的信息;
  • 配置:YAML 中与单环境、单集群绑定的信息,容许存在多样化的内容,不一样集群中的配置可能不一样;

所以,一个完整的 YAML 则由模板、镜像和配置共同渲染而成。而 ASIOps 则再会对镜像信息和配置信息这部分 YAML 分别进行集群维度和时间维度(多版本)进行管理,计算组件当前版本信息在众多集群众多分布情况以及组件在单集群中版本的一致性情况。

针对镜像版本,咱们从系统上促使其版本统一,以保证不会因版本太低而致使线上问题;而针对配置版本,咱们则从管理上简化它的复杂性,防止配置错误发入集群。

7.jpg

有了组件的基础原型后,咱们但愿发布不只仅是“替换 workload 里的 image 字段”这样简单的一件事。咱们当前维护了整个 YAML 信息,包含了除了镜像以外的其余配置内容,须要支持除了镜像变更外的变动内容。所以咱们尝试以尽量接近 kubectl apply 的方式去进行 YAML 下发。

咱们会记录三部分的 YAML Specification 信息:

  • Cluster Spec:当前集群中指定资源的情况;
  • Target Spec:如今要发布进集群的 YAML 信息;
  • DB Spec:上一次部署成功的 YAML 信息,与 kubectl apply 保存在 annotation 中的 last-applied-configuration 功能相同。

8.jpg

对于一个由镜像、配置和模板共同构建的 YAML,咱们会采集上述三种 Spec 信息,并进行一次 diff,从而得到到资源 diff patch,再进行一次 filter out,筛去不容许变动的危险的字段,最后将总体的 patch 以 strategic merge patch 或者 merge patch 的形式发送给 APIServer,触发使得 workload 从新进入 reconcile 过程,以改变集群中该 workload 的实际情况。

除此以外,因为 ASI 组件之间具备较强的相关性,存在许多场景须要同时一次性发布多个组件。例如当咱们初始化一个集群,或者对集群作一次总体的 release 时。所以咱们在单个组件部署的基础上增长了 Addon Release 的概念,以组件的集合来代表整个 ASI 的 release 版本,而且根据每一个组件的依赖关系自动生成部署流,保证总体发布的过程当中不会出现循环依赖。

9.png

3. 单集群灰度能力建设

在云原生的环境下,咱们以终态的形式去描述应用的部署形态,而 Kubernetes 提供了维护各种 Workload 终态的能力,Operator 对比 workload 当前状态与终态的差距并进行状态协调。这个协调的过程,换言之 workload 发布或者回滚的过程,能够由 Operator 定义的发布策略来处理这个“面向终态场景内的面向过程的流程”。

相比 Kubernetes 上层的应用负载,底层的基础设施组件在发布的过程当中更关心组件自身的灰度发布策略和灰度暂停能力,即不论任何类型的组件,都须要能在发布过程当中具有及时中止发布的能力,以提供更多的时间进行功能检测、决策以及回滚。具体而言,这些能力能够概括为以下几类:

  • updateStrategy:流式升级/滚动升级
  • pause/resume:暂停/恢复能力
  • maxUnavailable:不可用副本数到达必定时可以快速中止升级
  • partition:升级暂停能力,单次仅升级固定数量副本数,保留必定数量的老版本副本

ASI 中针对 Kubernetes 原生 workload 能力、节点能力都进行了加强。依托于集群中 Kruise 和 KubeNode 这类 operator 的能力以及上层管控平台 ASIOps 的共同协做,咱们对 Kubernetes 基础设施组件实现了上述灰度能力的支持。对于 Deployment / StatefulSet / DaemonSet / Dataplane 类型的组件,在单集群中发布时支持的能力以下:

10.jpg

后文将简要介绍咱们针对不一样 Workload 类型的组件进行灰度的实现,详细的实现细节能够关注咱们开源的项目 OpenKruise 以及后续准备开源的 KubeNode。

1)Operator Platform

大多数 Kubernetes 的 operator 以 Deployment 或者 StatefulSet 的方式部署,在 Operator 发布的过程当中,一旦镜像字段变更,全部 Operator 副本均会被升级。这个过程一旦新版本存在问题,则会形成不可挽回的问题。

针对此类 operator,咱们将 controller-runtime 从 operator 中剥离出来,构建一个中心化的组件 operator-manager(OpenKruise 开源实现中为 controller-mesh)。同时每一个 operator pod 中会增长一个 operator-runtime 的 sidecar 容器,经过 gRPC 接口为组件的主容器提供 operator 的核心能力。

11.png

operator 向 APIServer 创建 Watch 链接后,监听到事件并被转化为待 operator 协调处理的任务流(即 operator 的流量),operator-manager 负责中心化管控全部 operator 的流量,并根据规则进行流量分片,分发到不一样的 operator-runtime,runtime 中的 workerqueue 再触发实际 operator 的协调任务。

在灰度过程当中,operator-manager 支持按照 namespace 级别,哈希分片方式,将 operator 的流量分摊给新旧版本的两个副本,从而能够从两个副本处理的负载 workload 来验证此次灰度发布是否存在问题。

2)Advanced DaemonSet

社区原生的 DaemonSet 支持了 RollingUpdate,可是其滚动升级的能力上仅支持 maxUnavailable 一种,这对于单集群数千上万节点的 ASI 而言是没法接受的,一旦更新镜像后全部 DaemonSet Pod 将会被升级,而且没法暂停,仅能经过 maxUnavailable 策略进行保护。一旦 DaemonSet 发布了一个 Bug 版本,而且进程可以正常启动,那么 maxUnavailable 也没法生效。

此外社区提供 onDelete 方式,能够在手动删除 Pod 建立新 Pod,由发布平台中心端控制发布顺序和灰度,这种模式没法作到单集群中的自闭环,全部的压力都上升到发布平台上。让上层发布平台来进行Pod驱逐,风险比较大。最好的方式就是 Workload 能自闭环提供组件更新的能力。所以咱们在 Kruise 中增强了 DaemonSet 的能力使其支持上述几种重要的灰度能力。

以下是一个基本的 Kruise Advanced DaemonSet 的例子:

apiVersion: apps.kruise.io/v1alpha1
kind: DaemonSet
spec:
  # ...
  updateStrategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 5
      partition: 100
      paused: false

其中 partition 意为保留老版本镜像的 Pod 副本数,滚升级过程当中一旦指定副本数 Pod 升级完成,将再也不对新的 Pod 进行镜像升级。咱们在上层 ASIOps 中控制 partition 的数值来滚动升级 DaemonSet,并配合其余 UpdateStrategy 参数来保证灰度进度,同时在新建立的 Pod 上进行一些定向验证。

12.jpg

3)MachineComponentSet

MachineComponentSet 是 KubeNode 体系内的 Workload,ASI 中在 Kubernetes 以外的节点组件(没法用 Kubernetes 自身的 Workload 发布的组件),例如 Pouch,Containerd,Kubelet 等均是经过该 Workload 进行发布。

节点组件以 Kubernetes 内部的自定义资源 MachineComponent 进行表示,包含一个指定版本的节点组件(例如 pouch-1.0.0.81)的安装脚本,安装环境变量等信息;而 MachineComponentSet 则是节点组件与节点集合的映射,代表该批机器须要安装该版本的节点组件。而中心端的 Machine-Operator 则会去协调这个映射关系,以终态的形式,比对节点上的组件版本以及目标版本的差别,并尝试去安装指定版本的节点组件。

13.jpg

在灰度发布这一部分,MachineComponentSet 的设计与 Advanced DaemonSet 相似,提供了包括 partition,maxUnavailable 的 RollingUpdate 特性,例如如下是一个 MachineComponentSet 的示例:

apiVersion: kubenode.alibabacloud.com/v1
kind: MachineComponentSet
metadata:
  labels:
    alibabacloud.com/akubelet-component-version: 1.18.6.238-20201116190105-cluster-202011241059-d380368.conf
    component: akubelet
  name: akubelet-machine-component-set
spec:
  componentName: akubelet
  selector: {}
  updateStrategy:
    maxUnavailable: 20%
    partition: 55
    pause: false

一样上层 ASIOps 在控制灰度升级节点组件时,与集群侧的 Machine-Operator 进行交互,修改指定 MachineComponentSet 的 partition 等字段进行滚动升级。

相比于传统的节点组件发布模式,KubeNode 体系将节点组件的生命周期也闭环至 Kubernetes 集群内,并将灰度发布的控制下沉到集群侧,减小中心侧对节点元数据管理的压力。

4. 跨集群灰度能力建设

阿里巴巴内部针对云产品、基础产品制定了变动红线 3.0,对管控面组件、数据面组件的变动操做的分批灰度、控制间隔、可观测、可暂停、可回滚进行了要求。但变动对象以 region 的单元进行灰度不知足 ASI 的复杂场景,所以咱们尝试去细化 ASI 上管控面、数据面的变动所属的变动单元的类型。

咱们围绕集群这一基础单元向上,向下分别进行抽象,获得如下几个基本单元:

  • 集群组:具备共同业务方(ASI 承接的二方用户)、网络域(售卖区/OXS/集团)、环境(e2e/测试/预发/金丝雀/小流量/生产)信息,所以在监控、告警、巡检、发布等方面的配置具备共同性。
  • 集群:ASI 集群概念,对应一个 Kubernetes 集群预案。
  • 节点集:一组具备共同特征的节点集合,包括资源池、子业务池等信息。
  • Namespace:单个集群中的单个 Namespace,一般 ASI 中一个上层业务对应一个 Namespace。
  • 节点:单台宿主机节点,对应一个 Kubernetes Node。

14.jpg

针对每种发布模式(管控组件、节点组件),咱们以最小爆炸半径为原则,将他们所对应的灰度单元编排串联在一块儿,以使得灰度流程可以固化到系统中,组件开发在发布中必须遵照流程,逐个单元进行部署。编排过程当中,咱们主要考虑如下几个因素:

  • 业务属性
  • 环境(测试、预发、小流量、生产)
  • 网络域(集团 V、售卖区、OXS)
  • 集群规模(Pod/Node 数)
  • 用户属性(承载用户的 GC 等级)
  • 单元/中心
  • 组件特性

同时咱们对每一个单元进行权重打分,并对单元间的依赖关系进行编排。例如如下是一条 ASI 监控组件的发布流水线,因为该监控组件在全部 ASI 场景都会使用同一套方案,它将推平至全部 ASI 集群。而且在推平过程当中,它首先会通过泛电商交易集群的验证,再进行集团 VPC 内二方的发布,最后进行售卖区集群的发布。 而在每一个集群中,该组件则会按照上一节中咱们讨论的单集群内的灰度方式进行 1/5/10 批次的分批,逐批进行发布。

15.jpg

进行了灰度单元编排以后,咱们则能够得到到一次组件推平流水线的基础骨架。而对于骨架上的每一个灰度单元,咱们尝试去丰富它的前置检查和后置校验,从而可以在每次发布后确认灰度的成功性,并进行有效的变动阻断。同时对于单个批次咱们设置必定的静默期去使得后置校验可以有足够的时间运行完,而且提供给组件开发足够的时间进行验证。目前单批次前置后置校验内容包括:

  • 全局风险规则(封网、熔断等)
  • 发布时间窗口(ASI 试行周末禁止发布的规则)
  • KubeProbe 集群黑盒探测
  • 金丝雀任务(由诺曼底发起的 ASI 全链路的扩缩容任务)
  • 核心监控指标大盘
  • 组件日志(组件 panic 告警等)
  • 主动诊断任务(主动查询对应的监控信息是否在发布过程当中有大幅变化)

16.jpg

将整个多集群发布的流程串联在一块儿,咱们能够获得一个组件从研发,测试至上线发布,整个流程经历的事件以下图:

17.jpg

在流水线编排的实现方面,咱们对社区已有的 tekton 和 argo 进行了选型调研,但考虑到咱们在发布流程中较多的逻辑不适合单独放在容器中执行,同时咱们在发布过程当中的需求不只仅是 CI/CD,以及在设计初期这两个项目在社区中并不稳定。于是咱们参考了 tekton 的基础设计(task / taskrun / pipeline / pipelinerun)进行了实现,而且保持着和社区共同的设计方向,在将来会调整与社区更接近,更云原生的方式。

成果

通过近一年半的建设,ASIOps 目前承载了近百个管控集群,近千个业务集群(包括 ASI 集群、Virtual Cluster 多租虚拟集群,Sigma 2.0 虚拟集群等),400 多个组件(包括 ASI 核心组件、二方组件等)。同时 ASIOps 上包含了近 30 余条推平流水线,适用于 ASI 自身以及 ASI 承载的业务方的不一样发布场景。

同时天天有近 400 次的组件变动(包括镜像变动和配置变动),经过流水线推平的此时达 7900+。同时为了提升发布效率,咱们在先后置检查完善的条件下开启了单集群内自动灰度的能力,目前该能力被大多数 ASI 数据面的组件所使用。

以下是一个组件经过 ASIOps 进行版本推平的示例:

18.png

同时咱们在 ASIOps 上的分批灰度以及后置检查变动阻断,也帮助咱们拦住了必定因为组件变动引发的故障。例如 Pouch 组件在进行灰度时,因为版本不兼容致使了集群不可用,经过发布后触发的后置巡检发现了这一现象,并阻断了灰度进程。

19.png

ASIOps 上的组件大多数都是 ASI/Kubernetes 底层的基础设施组件,近一年半以来没有由于由组件变动所引发的故障。咱们努力将指定的规范经过系统能力固化下来,以减小和杜绝违反变动红线的变动,从而将故障的发生逐步右移,从变动引起的低级故障逐步转变至代码 Bug 自身引发的复杂故障。

展望

随着 ASI 的覆盖的场景逐步扩大,ASIOps 做为其中的管控平台须要迎接更复杂的场景,规模更大的集群数、组件数的挑战。

首先咱们亟待解决稳定性和效率这一权衡问题,当 ASIOps 纳管的集群数量到达必定量级后,进行一次组件推平的耗时将至关大。咱们但愿在建设了足够的先后置校验能力后,提供变动全托管的能力,由平台自动进行发布范围内的组件推平,并执行有效的变动阻断,在 Kubernetes 基础设施这一层真正作到 CI/CD 自动化。

同时目前咱们须要手动对灰度单元进行编排,肯定灰度顺序,在将来咱们但愿建设彻底整个 ASI 的元数据,并自动对每次发布范围内的全部单元进行过滤、打分和编排。

最后,目前 ASIOps 暂时只作到针对组件相关的变动进行灰度的能力,而 ASI 范围内的变动远不止组件这一点。灰度体系应该是一个通用的范畴,灰度流水线须要被赋能到注入资源运维、预案执行的其余的场景中。 此外,整个管控平台的灰度能力没有与阿里巴巴有任何紧耦合,彻底基于 Kruise / KubeNode 等 Workload 进行打造,将来咱们会探索开源整套能力输出到社区中。

相关文章
相关标签/搜索