1 GitOps 工作模型及优势
我们都知道在 knative 中由三个模块化组成,分别是 knative-serving、knative-eventing、Tekton
只不过后期将 Tekton 组件从 knative 中剥离
Tekton 是真正由 K8S 原生并支持的 CI/CD
平台,Tekton 会基于一个 CRD 来定义出来每一个 step、以及每一个 step 向上封装的 task 来完成传统的 CI/CD
功能,而这个 task 也是一个 CRD 。
我们基于声明式的 API 接口 apply 到对应的 K8S 集群上,而随后 K8S 集群会自动启动一个 Pod 来完成所有的任务。
CI/CD 是一种在应用开发阶段引入自动化实现以较高频度向客户交付应用的方法
- CI 就是对应的持续集成、CD 则有两个概念分别是:
- Continuos Delivery(持续交付) 和 Continuous Deployment(持续部署)
- CI/CD 作为广为接受的自动化模型,存在三个典型阶段:持续集成、持续交付和持续部署
-
CI/CD 可以让持续自动化和持续监控贯穿于应用的整个生命周期(从集成到测试、到交付,再到部署),这些关联的事务通常被统一称作
CI/CD Pipeline
(CI/CD 流水线),它一般需要由开发和运维团队以敏捷方式协同支持
如果我们要对上图做一个简单的描述的话就是:
应用程序的程序员一旦开发了一段应用程序代码以后,我们大体上需要做以下几个步骤:
- 对代码做一些简单的分析
- 对代码做集成测试
- 对代码做合并操作
- 对代码做功能测试
- 最后以上几个步骤都没有问题那么就需要做构建
- 构建完毕以后对代码做打包生成对应系统平台所能够部署的二进制程序,或者将代码打包为一个可运行的镜像
- 最后用户在部署的时候就不用部署某一个程序的程序包,而是通过镜像将该程序启动为一个容器
CI 和 CD 的关系:
- CI/CD 本身是一个互相延申的这么一种关系。
-
CI 是指持续集成,它属于开发人员的自动化流程。
- CD 指持续交付和持续部署,两者都事关Pipeline后续的自动化,但有时也会单独使用以评估自动化程度。
1.1 持续交付和持续部署
持续交付:
- 通常是指开发人员对应用的更改会自动进行错误测试并上传到存储库(如 GitHub 或 Image Registry ),然后由运维团队将其部署到实时生产环境中的这么一过程
-
核心目标在于解决开发和运维团队之间可见性及沟通较差的问题,目标在于确保尽可能地减少部署新代码时所需的工作量(实现敏捷开发、敏捷部署)
持续部署:
- 通常是指自动将开发人员的更改从存储库发布到生产环境,以供客户使用;
-
主要解决因手动流程降低应用交付速度,从而使运维团队超负荷的问题
-
以持续交付为前提,完成Pipeline后续阶段的自动化
CI/CD术语:
- 通常,CI/CD这一术语既可能仅指持续集成和持续交付构成的关联环节,也可以指持续集成、持续交付和持续部署这三项构成的关联环节
-
甚至于,很可能有些人口中所谓的”持续交付”也包含了持续部署流程
1.2 CI/CD Pipeline
所谓的 CI/CD Pipeline ,就是把应用程序从源代码到交付到上线以后,执行正常运行并能够被我们客户所访问的中间经历的阶段。
其中这个中间经历的阶段真正实现起来是需要一堆工具的参与
CI/CD Pipeline:
- 为了交付新版本的软件而必须执行的一系列步骤
-
一套专注于使用 DevOps 或 SRE 方法来改进软件交付的实践
-
加入了监控和自动化来改进应用开发过程,尤其是在集成和测试阶段,以及交付和部署过程中
CI/CD Pipeline 总结:
CI/CD Pipeline 正真价值在于自动化,但是我们也能够手动完成 CI/CD Pipeline 的每一个步骤
CI/CD Pipeline 的要素:
- 构成 CI/CD Pipeline 的步骤被划分为不同的任务子集(subsets of tasks),称之为 Pipeline Stage(每一个 stage 中有一到多个 step 组成),而一个 Pipeline 就是由多个或串行或并行的 stage 所共同组成的,这个过程就被称为 pipeline,
比如:一个代码推送过来以后我们需要先构建、测试、交付、部署等等操作。
- step:
而这期间的每个动作就是不同的阶段,比如在构建过程成中需要克隆代码、编译代码、并将编译完成的代码构建成一个程序包的格式,这些我就称为一个 step
-
Pipeline 中典型的 Stage 包括:
- Build(构建):应用编译
- Test(测试):代码测试
- Release(发布):将应用交付到存储库
- Deploy(部署):将代码部署到生产环境
- Validation 和 Compliance(验证与合规):镜像安全性扫描(例如 Clair )等,具体的步骤取决于实际需求
- 我们就是要将这些 stage 对应到 pipeline 工具链上对应特定的工具,由此来解决并实现每一个阶段所应该完成的功能
最初,传统的 CI/CD 系统是为使用虚拟机的 Pipeline 而设计,但云原生技术却为 CI/CD Pipeline 的价值实现带来了新的突破
- 使用 Tekton 项目,用户可以构建 Kubernetes 风格的 Pipeline ,控制微服务的生命周期
- Tekton 是面向云原生领域而生的一个 CI/CD SERVER
1.3 什么是 CI/CD SERVER
为什么需要 CI/CD SERVER:
如果需要将我们的交付过程中的每一个阶段,以及每个交付阶段中所需要执行的步骤,串联起来并完成一个完整任务的话。那么这期间的每一步都可以手动的通过写一些脚本或者手动执行一些命令来完成。
比如刚才我们说过的构建阶段有多个步骤或者多个任务、测试阶段有多个步骤、而后发布和部署阶段也会有对应的步骤,那么我们该如何定义这些包含多个步骤的每个阶段?又怎样在必要的情况下让每个步骤自动触发或者手动触发并按顺序执行呢?
实现 CI/CD SERVER 的工具选择:
这时候需要一个应用软件,该软件就是用来专门提供一个接口,允许把某一个特定应用程序下的这些流水书线过程将其定义下来,并提供给定义下来的每一个阶段中,然后在每个阶段中的每一个步骤里按照顺序或流程来执行的过程,从而实现该过程的程序就称为 CI/CD SERVER
很显然 Tekton
、jenkins
就是这么一个 SERVER,Tekton
、jenkins
允许我们调用构建阶段的代码克隆工具、程序编译工具等等工具来完成构建阶段的所有功能,而这些工具则就是工具链中的工具。
比如我们构建完代码之后还需要使用到各种测试工具,那么在什么时候执行呢?如前一个步骤需要向后一个步骤传递什么参数?以及我们如何将这个流水线定义的更加通用?我们都能够基于这么一个流水线来进行定义,通过参数实例化来实现,这些就是一个 CI/CD SERVER 需要帮我们完成的功能。
而 Tekton
、Jenkins
就是这么一个 CI/CD 的 SERVER ,而工具链当中使用的这些工具和他们本身没有关系。
Tekton
、Jenkins
并不是工具链中的工具,而是将这些工具链组合起来并形成一个流水线
1.4 CI/CD 在 K8S 上的执行流程
1.4.1 传统 Push Pipeline 过程
基于上面描述的这些工具链、CI/CD SERVER 来实现 DEVOPS 的方法就可以看下图:
如上图:
在图中涉及到的步骤和流程分为以下几个阶段:
- developer(程序员)推送代码到 git 仓库中,这个过程就为 GIT REPO
- 随后 CI/CD SERVER 通过 WEBHOOK 所生成的事件并注意到新代码推送至 Git 仓库中,并更具推送的结果来触发流水线的执行,而这个里的流水线就是借助 CI/CD SERVER 提供的 API 定义出来可以执行的一些测试通过的流水线,CI SERVER 就会执行下面的步骤
- Build New Docker image
- Run test
- Push New Docker image:上传到 docker 仓库上
- 更新 K8S 的部署清单
- 在第二步中将新的镜像推送到镜像仓库中、并且将 yaml 清单更新,就可以将新的这个镜像部署到 K8S 之上并创建对应的 Pod
总结:
以上整个过程就是由程序员通过推送代码一步一步执行完成的,当然再上图中有一个相对重要的一部,就是想将新的镜像部署到 K8S 之上,那么在 update kubernetes deployment
阶段必须拥有访问 K8S API SERVER 所对应部署的所有权限,比如需要使用的用户名、密码 都需要存储在 CI/CD SERVER 中
1.4.2 CI/CD SERVER 结合 HELM 的 Push Pipeline 过程
如上图也是一个 push pipeline,只不过将整个 CICD 流水线分成了这样的阶段
- 第一阶段(测试环境):
首先 developer(程序员)push 代码通过 push 事件把自己对代码得变更推送到 Feature branch(特性分支) 之上,这时 Jenkins 通过事件得到通知以后就会执行后续流水线中的多个步骤,其中包括 CI 和 CD 的流水线。
在 CD 的流水线中包括将镜像推送到镜像仓库,最后通过 helm 部署刚才推送的镜像到 K8S 上生成 Pod 。
然后我们就在 K8S 环境上做各式各样的测试,确定测试没有问题以后就将测试结果通过邮件推送到相关的人员手中,让相关的人员得到通知,并触发第二段流水线的完成。
-
第二阶段(预发环境):
通常需要 Reviewer(审核人员)来进行审核测试,确保没有问题就执行最后的合并操作,这时候一旦代码的合并请求被创建,对应的代码就从 Feature branch(特性分支)合并到了 Staging branch(预发分支)。
支持预发分支就会触发 CI/CD 流水线,过程于第一阶段相像,将代码打包至镜像并推送到镜像仓库,以及将 helm 的部署清单推送到 Chart 仓库,最后在通过 helm 来实现将该镜像部署至 K8S 上,此时就被部署至预发环境的 K8S 上
-
第三阶段(生产环境):
当第二阶段测试完成没有问题就会就会执行和第二阶段相同的操作,只不过这次是将镜像不是到了生产环境中
1.5 织云的 DevOps 方法
Weave Cloud(织云) 的 DevOps 方法使用 Pull 机制这里主要是指 CD 流水线,它依赖于两种特殊组件
- Config Updater:用于监视 image 的变动并更新配置清单;
-
Deploy Synchronizer:维护应用的当前状态;
工作机制:Pull Pipeline 模型的中心是配置中心或配置仓库(config repo)
- 开发人员推送代码变更至代码仓库中;
-
CI Server 自动完成 CI Pipeline 并生成 Docker Image;
-
Config Updater,注意到 Image 的变动,并以此更新 config repo 中的配置清单;
-
Deploy Synchronizer 在察觉到集群当前状态已过期后,将从配置仓库中pull到变更的配置清单并部署到集群上;
以上这么做的好处就是将需要部署对应的 images 组件放置到了 K8S 集群中,从而提升了 K8S 的安全性,而这就是 GitOps 的理念,
1.6 Pipeline 模型的演进
Push Pipeline
- 传统上的大多数CI/CD工具都使用基于Push的模型,即代码从CI系统开始,可以经由一系列脚本代码自动化完成其执行路径,或手动完成相关的Stage;
Pull Pipeline
- WeaveNet倡导一种新的基于Image Pull的Pipeline模型,并且将凭据直接保存于集群之上
因而我们的 pipeline 就从传统的 Push Pipeline 风格进化到了 Pull Pipeline 风格,而 Pull Pipeline 通常指的是最后部署的这么一个过程,而在 Pull Pipeline 中通常指的是最后部署的这么一个过程,这一块中最重要的一个组件就是
operator
而这个 operator
的主要功能如下:
CI Pipeline 根据开发人员提交的代码变更构建并推送新的 Image 后,负责监视代码仓库的 Deployment Automator 负责拉取该 Image 并更新 config repo ,而 Deployment Synchronizer 随后会察觉到集群上的应用状态已然落后于 config repo,遂获取 config repo 中的配置文
在 pull pipeline 中有两个仓库,分别是:
- code repo:用于存放代码
- config repo:用于存放配置文件
1.7 一个典型的 GitOps Pipeline
在 GitOps 模型中存在两个 Git 仓库
- 代码仓库(code repo):开发人员使用
- 推送代码变更
- 配置仓库(config repo):运维人员使用
- 推送配置变更
- 包括基础设施配置以及应用配置
简要工作流程:
- 开发人员推送代码变量至代码仓库这里执行 build 操作,一般这里就直接构建为一个新的镜像,而后将镜像推送至镜像仓库,而这个过程额外还依赖下面两个工具:
- config update:
-
gitops tool:
该工具不仅仅包括将镜像部署至 K8S 之上,而且他自身运行的 operator 也是在 K8S 之上
-
CI 工具链完成测试和构建
-
CD 工具链完成测试和交付(新版本的 Image 推送至工件仓库)
-
Config Update(即Deployment Automator)将 Image 的变更信息推送至配置仓库
-
随后,根据使用的分支和发布策略,完成应用的部署
1.8 GitOps 的实施要点
GitOps 强调的重心在于,它要求应用程序、环境、部署操作和基础架构进行的所有变更,都应以声明式描述文件存储于配置仓库 Git中;
配置仓库存放:
- 基础设施变更:例如,以 Terraform 模块或 Cloudformation 脚本形式存在的声明,此外,aws 也支持使用 Kops 在基础设施上拉起一个集群等;
-
Kubernetes 的资源配置:主要包括
Deployments、Services、StatefulSets、PVC
和用到的镜像等相关的配置- 如果使用 Helm 包管理器打包管理一个应用程序相关的配置应该是更好的选择;
- 环境配置:这里仍然是指 Kubernetes 配置,它主要包括 Kubernetes 上的
ConfigMap
资源对象- 这些配置同样可以打包在
Helm Chart
之中;
- 这些配置同样可以打包在
代码仓库存放:
- 应用程序代码:存储于 git 之中,还需要通过声明式的 Dockerfile 将其打包为 docker image
- Dockerfile 自身同样也样存储于程序的代码仓库中;
基于 Pull Request 完成所有需要进行变更
- master(或main)分支用于反映系统的当前状态;
-
在 master 分支上打开新的 PR(Pull Request) 即可完成可能需要的任何更新;
-
PR 合并后,将触发 CD/GitOps 管道;回滚同样由 PR 触发;
自愈,该功能就是利用 CD 的 operator 来完成
- Git 配置仓库保存有应用的预期状态,而 Kubernetes 上保存有应用的当前状态
-
需要一个专用的 Operator 来负责实现该功能
在 GitOps 中,要求部署一个应用程序时,这里的部署或配置应用程序的时候很有可能需要不同的人员来完成。对应用程序环境配置、基础设置配置都需要集合起来完成,但是这些功能很有可能分别属于不同人员来实现,所以现在又有了所谓的 OAM 模型来专门面向云原生时代,并构建应用配置应用交付和应用部署。
1.9 开放式应用程序模型(OAM)
对于一个特定的应用,其声明式配置清单的管理会涉及到诸多方面
- Dockerfile:将应用程序打包成Docker Image
-
Kubernetes资源配置文件:Deployments、Services、Volumes和ConfigMaps等;
- 包含敏感信息的Secrets需要独立管理;
- 环境相关管理策略,例如应用的冗余数量,在预发和生产环境可能会有所不同;
-
与容灾相关的跨区可用性策略相关的调度机制;
-
网络安全策略;
-
路由策略;
-
……
这些信息分别来自
-
开发人员:定义应用程序组件
-
应用运维:组件实例及配置的声明
-
基础架构运维:基础设施组件的声明