写点什么

网易 CI/CD 实践(中):CD 系统的部署架构与发布流程

2020 年 10 月 16 日

网易CI/CD实践(中):CD系统的部署架构与发布流程

上一篇文章中,我们主要介绍了网易轻舟的 CI 建设实践,在本文中,我们将主要来讲解网易轻舟的 CD 建设实践。


云原生时代,容器技术是实现云原生架构的基础,而 Kubernetes 是容器编排的事实标准。网易轻舟 CI/CD 容器部署系统的架构设计参考了 CNCF 应用兴趣小组提出的云原生应用交付模型,以 Kubernetes 作为底层基础设施平台,将应用的交付分为应用定义、应用发布与应用工作负载管理、自动化运维三个主题。


网易轻舟 CI/CD 容器部署系统是完全基于云原生技术实现的,通过 Kubernetes 的声明式特性,保证系统极强的容错性;使用部署模板的方式来简化应用的定义,在应用发布环节,支持多种发布策略,包括蓝绿发布、灰度发布、自定义分组等;利用 Kubernetes 控制器来控制发布流程,这不仅是 Kubernetes 实现“容器编排”的核心机制,同时也是一种编程范式。在 Kubernetes 中,通过自定义资源(CRD)可以定义满足用户需求的资源对象,并且通过控制器模式来驱动系统状态逐步向 CRD 中定义的期望状态逼近,这样能很好的保证应用交付的效率和准确性。


网易轻舟的 CD 建设实践

众所周知,“CD”其实是包含两层意思,持续交付及持续部署。持续交付指的是所有变更可以部署到生产环境中,但是出于业务安全考虑,部署操作仍需由运维人员手工部署到生产环境。持续部署则是在持续交付的基础上,将新版本直接自动化部署到生产环境的过程。持续交付和持续部署的区别在于部署操作自动化。


如果想实现持续部署,将代码版本直接生效到生产环境,主要依赖的是测试自动化以及自动化发布流程。网易轻舟团队实现了一个渐进式的发布流程,在整个流程执行过程中,通过扩展机制在容器发布过程中运行自动化测试来完成新版本的验证操作,并通过结果反馈来决定是否可以继续。在新版本还未完全生效到线上的时候就进行自动化验证,一旦新版本验证出现问题,可以快速回滚,不至于大面积影响线上用户。通过这个渐进式的发布流程模型,将测试自动化和自动化发布流程结合在一起,从而实现了持续集成。


接下来,我们介绍一下网易轻舟 CI/CD 容器部署系统的部署架构、应用定义、发布流程、发布策略等。


部署架构

网易轻舟 CI/CD 容器部署系统的整体部署架构主要分为管控集群和业务集群,这两个集群可以是同一个 Kubernetes 集群,也可以是部署在不同的 Kubernetes 集群中,并且可以支持多个不同的业务集群的容器部署。


网易轻舟 CI/CD 容器部署系统支持多云多集群的容器部署。管控集群与业务集群之间采用 Agent 进行安全可靠的双向通信。在管控集群,数据存储主要以 Kubernetes 自定义资源存储在 etcd 中,同时使用 Kubernetes 中广为流传的控制器模式,根据自定义资源中声明的容器规格,服务暴露方式等配置信息,通过一个发布流程生效到到相对应的业务集群。



上图为网易轻舟 CI/CD 容器部署系统,其中比较重要的组件是 API 层、管控集群 Operator、业务集群 Operator。


  • API 层:用户通过界面创建的应用工作负载配置、服务访问方式、发布策略、发布环境等信息,通过 API 层将数据以自定义资源的形式存放在 etcd 中。

  • 管控集群 Operator:主要包含了多个控制器。这些控制器主要负责监听各自关心的资源(CR)的创建或者修改,并由此判断是否需要进行发布操作,以及发布流程的启动和继续等。

  • 业务集群 Operator:主要包含了执行控制器(execution_controller),execution_controller 中会根据 ExecutionCRD 的定义来完成在本集群中需要执行的工作负载创建与更新操作。ExecutionCRD 的设计是为了实现对一个发布操作的抽象,可以定义工作负载的创建更新、副本数更新、流量切换等操作。


应用定义

在应用交付过程中,我们常会提到“应用”,但是你真的清楚一个应用到底都包含哪些内容吗?


在 K8s 中,Deployment 用于声明工作负载,Service、Ingress 用于统一访问入口,ConfigMap、Secret 可能用于声明程序配置项或者环境变量。一个应用的部署可能会包含上述多种 K8s 资源,但是在 K8s 中并没有“应用”这一层抽象。所以,在这里,我们认为“应用”的定义应该是希望能够把一个完整应用程序要部署的所有资源聚合起来,统一管理,统一部署。同时还提出了"应用模板"的概念,部署模板用于声明应用整体部署框架,具体的镜像、副本数、端口等参数,根据部署环境而决定的。


实际上,应用的定义可以对标 CNCF 云原生应用交付模型的 Topic1,当配置发生变化的时候,就会生成一个新的版本,每当有新版本生成,都会根据发布策略产生一个新的发布流程。这个自动化发布流程对应了 CNCF 的 Topic2。目前 Topic3 工作负载实际上还是利用了 K8s 原生的 Deployment、StatefulSet、Deamonset,可能后面也会存在对这些资源进行扩展的需求。



发布流程

网易轻舟 CI/CD 容器部署系统的发布流程是一条多阶段串行执行的工作流。根据 DeploymentCRD 定义变化(比如 Deployment 的镜像改变了),会根据发布策略产生一个 Upgrade 自定义资源(发布流程的资源抽象)。只有当一个阶段的任务全部全部完成之后,才能够进行下一个阶段。并且用户可以自定义在阶段结束之后,是直接自动继续下一个阶段,还是需要手动点击「继续」才能进行下一个阶段。在每一个阶段中,可以定义多个并行的指令,只有当所有指令都完成了,就表示阶段完成。



为了更好地支持流程的扩展,网易轻舟团队在阶段前后增加了钩子功能,在阶段开始执行之前和阶段执行完成执行钩子所定义的内容,可以是一个外部调用,也可以执行一些具体的命令。


这个钩子功能的主要使用场景:


  • 与自动化测试平台的集成:在一个阶段执行完成之后,通过接口调用触发自动化测试平台的验证,然后在下一个阶段开始之前轮询调用验证结果,如果验证通过便可以进入下一个阶段的流程,这就是实现持续部署的方式;

  • 金丝雀发布:定义指标阈值,每个阶段发布完成之后,查询指标是否处于健康状态,如果处于健康状态,可以通过并自动继续下一阶段;

  • 与服务网格(ServiceMesh)对接,实现灰度发布流量的精准控制:可以通过修改服务网格的相关流量配置,实现在发布流程不同版本之间精准的流量控制;


发布策略

目前,轻舟 CI/CD 容器部署系统已经集成了多种发布策略,包括 Kubernetes 原生的滚动更新,蓝绿发布,灰度发布以及自定义分组发布。轻舟 CI/CD 容器部署系统设计发布流程的初衷就是为了支持多种不同的发布策略,使用统一的发布流程来控制版本升级。


K8s 原生滚动更新

如果选择了 K8s 原生滚动更新的模式,整个发布流程只有一个阶段,这个阶段就是将用户定义的 PodSpec 以及滚动更新的策略更新到业务集群的 Deployment。之前其它的事情都可以全部交给 K8s 的 DeploymentController 完成,直到 Deployment 更新完成之后,流程结束。


灰度发布,自定义分组发布

在 K8s 原生的滚动更新策略的实现逻辑中,通过 MaxSurge 和 MaxUnavailable 来控制每次更新的比例或者数量,但是整个更新的过程是无法暂停的,而在真实的使用场景下,用户往往会选择对线上升级采用灰度发布的方式。


灰度发布是为了保证新版本应用能够平滑过渡的一种方式,让一部分的用户优先使用新版本应用,另外一部分的用户仍旧使用老版本的应用。但这样的场景,使用原生的 Deployment 滚动更新是无法完成的。


而 Upgrade 就是用来满足上面的场景,将不同版本对应到不同的 Deployment,通过新版本 Deployment 的扩容以及老版本 Deployment 的缩容,逐步地将新版本 Deployment 的副本数扩容到指定副本数,老版本 Deployment 的副本数缩容到 0。同时,在这整个发布过程中,Service 上的 SelectorLabel 会同时选中两个 Deployment 的 Pod。


假设有一个 10 的副本数的 Deployment,它的自定义分组的策略定义为:


strategy:                                                   type: Custom                       custom:                           # 可选的,type=Custom的时候生效    betaStageEnabled: false         # 不开启beta阶段    percentageList: [50, 100]       # 每个元素对应每个阶段的副本更新比例
复制代码


那么对应的整个发布流程的副本数变化如下所示(min 表示最小的可用副本数,max 表示最大的可用副本数):


DeploymentInitStage1Stage2
v110max: 5max:0
v20min:5min:10


蓝绿发布

在 Kubernetes 中实现蓝绿发布的主要方式是通过修改 Service 的 SelectorLabel,让 Service 选到新版本的 Pod。因此蓝绿发布的整个流程实际上可以分为三步骤:


  1. 部署新版本的工作负载,在 Pod 上打上新版本的标签(比如 cicd.skiff.netese.com/revision: v2);

  2. 更新 Service 的 SelectorLabel,使用新版本的标签 cicd.skiff.netese.com/revision: v2;

  3. 回归新版本,如果没有问题,将 v1 版本的 Deployment 缩为 0;


上面三个步骤实际上就直接对应了 Upgrade 中的三个阶段,并且每个阶段结束后,系统默认都会暂停,便于用户进行回归验证,验证通过之后再进入到下个阶段。通过上述流程,可以实现蓝绿发布的自动化。


流程监控

流程监控的主要工作是负责监控所有正在进行的流程状态,主要用于通知和告警。一般情况下,运维人员在操作上线流程的时候,希望收到告警通知:


  • 当发布流程暂停时;

  • 当流程暂停超过一定的时间时;

  • 发布流程中出现错误事件(资源不足,镜像拉取失败);

  • 发布完成,可以作为 webhook 对接其他系统;


发布流程监控同样是采用了 CRD+控制器的模式,当采集到符合条件的流程状态的时候,以标准的 HTTP 方式和统一的请求格式调用预先定义好的服务。目前,流程监控已经被用于对接告警和指标度量平台。


相关阅读:


网易CI/CD实践(上):CI系统的技术选型与部署流程


采访嘉宾简介:


汪灿丰,网易杭州研究院高级产品开发工程师,专注于云原生以及 DevOps 领域,目前主要负责网易轻舟 CICD 的研发工作。


梅光辉,网易杭研究院高级服务端开发工程师,目前主要负责网易轻舟 CICD 研发工作,在云原生以及容器 DevOps 领域有过深入的研究和实践。


2020 年 10 月 16 日 11:093513
用户头像
田晓旭 InfoQ 编辑

发布了 487 篇内容, 共 225.0 次阅读, 收获喜欢 1548 次。

关注

评论

发布
暂无评论
发现更多内容

产业区块链:产业是本质,区块链是工具

CECBC区块链专委会

新基建 CECBC 区块链技术 中国电子

Nginx 基础原理和命令行的真相

子杨

nginx 运维

Spring源码

云淡风轻

spring 源码

Vol.10 Java 25岁了!

pyfn2030

Java jdk 编程语言 Java25周年

一位测试工程师的自我介绍

姬翔

测试

我们可能都误解了什么是情商

七镜花园-董一凡

情绪

工厂模式(三)泛型工厂的概念以及示例代码

LSJ

k8s 上运行我们的 springboot 服务之——大文件读写

柠檬

Java nio

Django ListView DetailView等基于类的视图如何添加装饰器?

BigYoung

Python django LiveView 装饰器

谈谈控制感(11):这样提升控制感,谁都能做到

史方远

心理 成长

广告的发展历程

子悠

广告 计算广告 广告系统 互联网广告 RTB

Nginx 入门及命令行操作

子杨

nginx 运维

JUC整理笔记四之梳理VarHandle(上)

JFound

Java

平台化服务的基石:权限模型设计

孤岛旭日

企业架构 用户权限 数据建模

图片与标题的Ken Burns动效

寇云

CSS css3

毫无意义的人生唯有编织图案

xyz

Vite for Vue 是什么?

꯭🇫꯭

Vue vuejs vite Vue3

基于 Markdown 的中文文档排版规范

Murphy

markdown 排版规范 GitHub GFM 物联网学前班

终于找到了一篇文章!通俗地讲解计算机工作原理

图灵社区

cpu 存储器 编译器 计算机工作原理

贴吧电纸书资深用户,从7个方面详谈BOOX Poke2上手体验!

DT极客

ARTS_20200529

凌轩

Java ARTS 打卡计划

Mysql常用删除方式比较

云也退

MySQL

备案问题汇总

云也退

网站 备案

为什么你要学习 Go?

司徒公子

go golang 编程语言 谷歌Google

阿里巴巴为什么让初始化集合时必须指定大小?

王磊

Java 性能

Cassandra可调一致性的使用及原理

老任物联网杂谈

大数据 分布式 Cassandra 可调一致性

只需CSS的下拉式导航菜单

寇云

CSS css3

大厂为什么不招30岁以上程序员,看这篇就够了

金刚小书童

职业规划 技术管理 程序员成长 程序员次第 职业成长

Spring Bean生命周期——初始化和销毁

xiaoxi666

Java spring

幂等问题及解决方案

Joker

幂等 解决方案

如何存储1个二进制位&锁存器的核心和本质

姜海天

计算机 数字逻辑

网易CI/CD实践(中):CD系统的部署架构与发布流程-InfoQ