GitOps 工作流程图:用 Argo CD 或 Flux 实现拉取式交付

用图讲清 GitOps 工作流:OpenGitOps 原则、应用仓库与配置仓库、基于 Argo CD 或 Flux 的拉取式同步、通过 Pull Request 晋级以及回滚。

· 创始人兼开发者

发布于

GitOps 工作流程图:用 Argo CD 或 Flux 实现拉取式交付

在传统的流水线中,CI 构建代码后,用 kubectl apply 或 helm upgrade 把结果推送进集群。这样也能工作,但流水线需要每个集群的管理员凭据;不去问集群,谁也说不准到底在运行什么;而被手动修改过的部署,会悄无声息地偏离仓库里的定义。

GitOps 把方向反了过来。Git 保存期望状态,集群内的代理持续拉取它,并让集群与之保持一致。本文讲解 GitOps 的原则、大多数团队使用的双仓库工作流、晋级和回滚的方式,并画出完整的流程。

四条原则

CNCF 的 OpenGitOps 项目 用四条原则定义了 GitOps:

  1. 声明式: 系统的期望状态以声明式的方式表达。
  2. 版本化且不可变: 这一状态的存储方式要能保留完整、不可变的版本历史,实践中就是 Git。
  3. 自动拉取: 软件代理从源头拉取期望状态。
  4. 持续调和: 代理不断比较实际状态与期望状态,并修正两者的差异。

第三条正是 GitOps 与“从读取 Git 的流水线进行部署”的区别所在。由集群来拉取,外部的任何东西都不会向集群推送。

两个仓库:代码与配置

大多数团队会区分两类变更:

  • 应用仓库 存放源代码。CI 构建代码、运行测试、进行扫描,并把一个不可变的镜像标签推送到镜像仓库。
  • 配置仓库 存放各个环境的 Kubernetes 清单、Helm values 或 Kustomize overlay。它描述了什么应该在哪里运行,包括镜像标签。

两者之间的连接是一个小而明确的变更:CI 或镜像自动化工具在配置仓库中发起一个 Pull Request,提升预发环境的镜像标签。这个 Pull Request 就是部署申请,自带评审和审计记录。

集群中的控制器

Argo CD 和 Flux 是两个被广泛使用的 GitOps 控制器。它们都运行在集群内部,轮询配置仓库或接收它的 Webhook,渲染清单,与线上对象进行比较,然后应用差异。

它们的调和设置决定了系统有多严格:

  • 自动同步: 无需有人点按钮,就自动应用新的提交。
  • 清理(prune): 删除已从 Git 中移除的对象。
  • 自愈(self-heal): 撤销直接在集群中做出的变更。在 Argo CD 的 自动同步选项 中,自愈和自动同步是两个独立的开关。

正是自愈这一设置,让 Git 成为真正的事实来源。没有它,凌晨 3 点的一次 kubectl edit 就会变成永久而且看不见的变更。

晋级与回滚

环境就是配置仓库中的目录、overlay 或文件。晋级就是把一个版本从一个环境复制到下一个环境:

  1. Pull Request 提升预发环境的标签;合并后几分钟内,预发环境就会更新。
  2. 针对预发环境运行测试和检查。
  3. 第二个 Pull Request 把生产环境提升到同一个标签。合并它,就是生产部署。

回滚就是对那次合并执行 git revert。控制器看到旧标签,便会应用它。由于全部历史都在 Git 中,“上周二 14:00 生产环境运行的是什么?”这个问题有准确的答案。

由谁来发起 Pull Request

把新镜像接入配置仓库,常见的方式有两种:

  • 由 CI 发起。 流水线的最后一步克隆配置仓库,修改一行,提交到某个分支并发起 Pull Request。这种方式明确、易于调试,而且流水线只需要这一个仓库的令牌。
  • 由镜像自动化工具提交。 Flux 的镜像自动化控制器和 Argo CD Image Updater 项目可以监视镜像仓库,挑选符合策略的新标签,并把它们写回 Git。适合那些应该始终运行最新构建的预发环境。

很多团队会把两者结合起来:用自动化让预发环境保持最新,而生产环境的变更总是以经过评审的 Pull Request 形式到来,由人或发布任务发起。无论选择哪种方式,都要把它写在架构图上,因为“新版本是怎么到这里的?”是任何人看到 GitOps 方案时问的第一个问题。

一次发布的完整过程

跟随一个 shop 服务的 1.8.0 版本,从提交一路走到生产环境:

  1. 开发者把一个变更合并到应用仓库。CI 运行测试、构建镜像、进行扫描,并把 shop:1.8.0 推送到镜像仓库。
  2. CI 在配置仓库中发起一个 Pull Request,把预发环境的标签从 1.7.3 改为 1.8.0。评审者批准并合并。
  3. 一两分钟内,控制器发现新的提交,渲染预发环境的清单并更新部署。Kubernetes 滚动发布新的 Pod,新 Pod 从镜像仓库拉取镜像。
  4. 预发环境的冒烟测试通过。发布负责人发起第二个 Pull Request,把生产环境设置为 1.8.0。
  5. 合并之后,生产环境以同样的方式发布。如果错误率上升,回滚那次合并提交就会恢复到 1.7.3。

整个过程中,集群外部的任何东西都不需要集群凭据,而且每一步都留下了一个提交。

密钥

明文密钥不能放进 Git。常见做法有:

  • 在 Git 中加密存储, 使用 Sealed Secrets 或 SOPS 等工具,只在集群内部解密。
  • Git 中只放引用,值放在别处, 借助 External Secrets 这类从密钥管理服务读取的 Operator。

无论哪种方式,配置仓库都保持可评审,密钥的值也永远不会出现在 diff 中。

架构图

开发者推送代码到应用仓库;CI 构建、测试并把镜像 1.8.0 推送到镜像仓库,然后发起一个 Pull Request,提升配置仓库中预发环境的标签。Kubernetes 集群中的 GitOps 控制器拉取配置仓库,并把它应用到预发和生产命名空间。

12 个组件 · 8 个连接

在 Archboard 中打开
图表内容
  • Developer
  • App repo: code
  • CI: build, test, scan
  • Container registry
  • Config repo: desired state
  • Kubernetes cluster
  • GitOps controller
  • staging
  • shop v1.8.0
  • production
  • shop v1.7.3
  • push
  • trigger
  • image 1.8.0
  • PR: bump staging tag
  • pull every few minutes
  • apply
  • nodes pull images
一个 GitOps 工作流。CI 构建并推送镜像,然后发起一个 Pull Request,修改配置仓库中的镜像标签;集群内的控制器拉取配置仓库,把变更应用到预发或生产环境,并撤销手动造成的漂移。

这张图的读法如下:

  • 顶部一行,构建: 开发者推送到应用仓库,CI 构建并测试镜像 1.8.0,然后推送到镜像仓库。
  • 中间: CI 发起一个 Pull Request,提升配置仓库中预发环境的标签。这是 CI 唯一接触部署的地方。
  • 底部,集群: GitOps 控制器拉取配置仓库(虚线),并应用到预发命名空间(现在运行 1.8.0)和生产环境(在它自己的 Pull Request 合并之前仍运行 1.7.3)。节点从镜像仓库拉取镜像(点线)。
  • Markdown 块 写明了工作流规则:通过 Pull Request 晋级、通过 revert 回滚、通过自愈撤销漂移。

团队会发生哪些变化

  • CI 不再持有集群凭据。 是集群主动向外拉取,流水线只需要对一个仓库有写权限。
  • 评审覆盖了部署。 谁在什么时候、出于什么原因部署了什么,都记录在 Pull Request 历史里。
  • 漂移变得可见。 控制器会展示未同步的资源,而不是把它们藏起来。
  • 调试的位置变了。 “为什么这个没部署上去?”要从控制器的同步状态和事件中找答案,所以要让负责合并的人能看到它们。

GitOps 架构图上应该画什么

  • 两个仓库, 以及连接它们的 Pull Request。
  • 拉取的方向, 是从控制器到配置仓库,而不是从流水线到集群。
  • 每个环境, 连同它运行的版本,让晋级过程一目了然。
  • 同步设置: 自动同步、清理、自愈。

部署策略图 展示了发布本身如何采用金丝雀或蓝绿方式,CI/CD 流水线图 详细介绍了构建阶段,Kubernetes 架构图 展示了集群本身,从 Kubernetes YAML 生成架构图一文 则介绍了如何把配置仓库中的清单变成一张图。

在 Archboard 中构建

  1. 使用 Google 或 GitHub 登录,并新建一张图。
  2. 添加 C4 模型节点包中的一个 人员,DevOps 节点包中的两个 代码仓库 节点和一个 流水线,以及 Docker 节点包中的一个 镜像仓库。
  3. 添加基础节点包中的一个 框架 表示集群,并在其中放入一个表示 GitOps 控制器的 容器。
  4. 添加 Kubernetes 节点包中的两个 Namespace 节点,每个里面放一个 Deployment,并在标签中注明它运行的版本。
  5. 用一条从控制器指向配置仓库的虚线表示拉取,并添加一个基础节点包中的 Markdown 块,写明工作流规则。

这个示例共用 12 个图表节点,在 Free 套餐的限制之内。

常见问题

GitOps 和 CI/CD 有什么区别? CI/CD 负责构建、测试和交付软件。GitOps 是完成其中交付部分的一种方式:期望状态保存在 Git 中,由目标环境中的代理拉取并调和,而不是由流水线把变更推送进去。

应该用 Argo CD 还是 Flux? 两者实现的是同一种模型。Argo CD 有丰富的 Web 界面和以应用为中心的视图;Flux 是一组可组合的控制器,很多团队完全通过 Git 和 CLI 来驱动它。

应用仓库和配置仓库需要分开吗? 这是一种常见的约定,而不是硬性规定。分开的仓库能让部署历史保持清晰,并且无需重新构建代码就能修改配置。

用 GitOps 如何回滚? 回滚配置仓库中修改版本的那个提交。控制器会应用之前的状态。

GitOps 中如何处理密钥? 把它们加密后存进 Git,或者在 Git 中只存引用,由集群内的 Operator 从密钥管理服务中获取实际的值。

免费开始 — 1 个席位,无需信用卡。

相关文章

← 返回博客

一分钟打开画布

使用 Google 或 GitHub 登录。单席位免费,团队加入后再升级。