前言
GitOps 是实现持续部署的云原生方式。它的名字来源于标准且占主导地位的版本控制系统 Git。GitOps 的 Git 在某种程度上类似于 Kubernetes 的 etcd,但更进一步,因为 etcd 本身不保存版本历史记录。毋庸置疑,任何源代码管理服务,包括 GitLab、GitHub、Bitbucket、Azure DevOps 或类似的服务,都可以使用。在 GitOps 中,VCS 是单一事实来源。
作为开发人员,我们以声明式的方式实现基础设施定义、数据库模式、应用程序配置和策略,然后将代码推送到 Git 仓库。运维人员获取所需状态并将其应用到我们的控制平面。这个控制平面主要是一个 Kubernetes 控制平面。GitOps 是一个伴随云原生生态系统而出现和发展的术语。因此,所有 GitOps 提供商都与 Kubernetes 集成。Kubernetes 正在发展成为统领所有其他控制平面的唯一控制平面。在接下来的文章中,我会详细讨论这个术语。
OpenGitOps
我们从 OpenGitOps 社区开始讨论GitOps 。OpenGitOps 旨在标准化 GitOps 原则,定义并帮助采用 GitOps 的最佳实践。OpenGitOps 同时也是 CNCF 的沙盒级项目。它由七个成员创立:亚马逊、Azure、Github、RedHat、CodeFresh、WeaveWorks 和 Crayon。可以说,这些成员是对 GitOps 生态系统贡献最大的公司之一。OpenGitOps 社区定义了四个主要的 GitOps 原则:
- 由 GitOps 管理的系统必须以声明式的方式表达其期望状态:声明式状态是近年来基础设施即代码 (IaC) 工具的标志之一。声明式意味着描述要实现的目标,而不是命令要做什么。举个例子,"我希望两台服务器运行"是声明式的,但"运行两台服务器"是命令式的。当你重复这两个句子时,第一个句子会导致两台服务器运行,而第二个句子会导致四台服务器运行。声明式语句天生具有幂等性,这在 IaC 领域至关重要。
- 所需状态的存储方式强制执行不变性、版本控制并保留完整的版本历史记录:不变性、版本控制和完整的版本历史记录表明需要使用版本控制系统,因为 VCS 上保存的配置默认是版本控制的。它只能通过提交、推送和/或拉取请求进行更改。这保证了所需级别的不变性,并且所有更改都可以追溯并在需要时回滚。
- 软件代理自动从源头拉取所需状态声明:在传统的 CI/CD 方法中,容器镜像被构建并推送到容器注册表。资源定义文件(原始清单、Helm Charts、Kustomize 文件)使用镜像标签进行修改。之后,使用 helm、kubectl 将它们推送到集群。这需要将服务帐户令牌存储在集群外部并用于应用更改。因此,密码必须安全地保存在 CI/CD 管道中。与此不同,GitOps 工具提供了基于拉取的方法,这意味着 GitOps 操作员在集群中运行并定期从 git 存储库拉取配置更改,或订阅 git 存储库事件并等待触发更改。检测到更改后,操作员通过调用 kubeapi 将其应用到集群。这更安全、更自然。
- 软件代理持续观察实际系统状态并尝试应用所需状态:GitOps 操作员从 git 存储库拉取更改,并定期将所需状态与集群状态进行比较。这称为漂移检测。任何更改都会应用于集群。任何人对其管理的资源所做的手动更改都将被还原。这称为协调。Git 拉取请求是更改正在运行的集群状态的唯一方法。这有助于将容器级别的不变性扩展到基础设施级别,从而避免许多问题。
GitOps 的爆炸式增长
早在2017 年,Weaveworks公司(是一家由 Alexis Richardson 联合创立的公司)就发表关于 GitOps 的文章,强调了我们如今使用的很多原则,例如一切皆代码、所有期望状态必须以声明式定义、自动偏差检测等等。在这篇文章之后,又陆续发表了另外三篇文章。正如文章中提到的,它们也使用了自动协调功能。Weaveworks 引入了 GitOps 的概念,将 Git、Kubernetes 和持续交付 (CD) 融合成一个统一的运维模型。
Weaveworks 积极参与开源社区,组织活动、参加会议并参与 GitOps 相关的讨论。这种社区建设工作有助于促进整个生态系统的协作和知识共享。
Weaveworks 提出Ansiblediff、Terradiff 和 Kubediff 作业,用于检测 Kubernetes 集群上的漂移,并自动协调提交给 Git 的各种资源定义的所需状态提出检测偏差(集群的实际状态与 Git 中定义的期望状态存在偏差)。
我们可以将 WeaveWorks 所做的工作视为持续交付最佳实践与我们环境中实际应用情况之间的偏差检测。他们将我们的持续交付生态系统与这些最佳实践进行了协调。我们可以说,那些文章中提到的很多内容在当时也是共识,但将它们全部用到我们今天使用的名称上,并以 git 作为主题,才是 GitOps 的真正意义所在。
GitOps 工具
从那时起,GitOps 的原则基本保持不变,但涌现出了许多不同的工具。在包括科技巨头在内的开源社区的大力贡献下,标准化逐渐成型。
GitOps 领域出现了两个最重要的工具:Argo CD 和 Flux。在撰写本文时,它们都是 CNCF 孵化级项目,并且都提供了许多强大的功能和辅助工具。GitOps 仅解决了 CI/CD 中的持续部署部分,因此我们需要来自不同产品的其他部分。这些其他部分包括渐进式交付工具(蓝绿部署、金丝雀部署)、持续集成工具、镜像控制器(等待新镜像推送并更新资源定义)等等。
Argo 项目家族包括工作流(持续集成)、事件(事件驱动的工作流自动化)、部署(渐进式交付)工具,除了 CD 工具之外,它还包含许多辅助工具。另一方面,Flux 项目家族除了 Flux 本身之外,还包含 Flagger 作为渐进式交付工具,并且在 GitOps Toolkit 框架下拥有许多辅助工具。当我们比较持续交付 (CD) 工具时,这两个项目都是非常出色的项目;如果我们将这种比较扩展到其他工具,Argo 家族似乎更加完整,因为 Argo Workflows(任何持续交付 (CI) 工具都可以与 Argo CD 或 Flux 配合使用)。它还有一个仪表板,虽然对大多数人来说意义不大,但在某些情况下确实很有帮助。如果您已经掌握了其他可观察性和可视化工具,则无需再添加太多仪表板。
还有一些 GitOps 工具,它们不如这两个工具成熟,但确实很有前景。Rancher Fleet 就是其中之一。他们秉持"规模化 GitOps"的理念,并致力于管理集群 Fleet,就像 Rancher 多年来一直在尝试的那样。但我们必须承认,如果没有 GitOps,这一切都不可能实现。你也可以使用 Argo CD 和 Flux 来管理集群。
GitOps 项目的数量呈爆炸式增长。除了我们熟悉的项目之外,还有 PipeCD、Werf、Atlantis 等等。
Argo CD 和 Flux 已经成为许多企业级 PAAS 服务的基石。例如,Azure Arc 和 WeaveCloud(不出所料)使用了 Flux,Openshift GitOps 和 Codefresh 使用了 Argo CD。
Flux 演示
要遵循本指南,您需要以下资源:
- 一个 Kubernetes 集群。。
- 一个具有代码库权限的 GitHub 个人访问令牌。请参阅 GitHub 文档,了解如何创建个人访问令牌。
- Flux CLI
导出您的凭据
导出您的 GitHub 个人访问令牌和用户名:
export GITHUB_TOKEN=<your-token>
export GITHUB_USER=<your-username>
验证kubernetes 集群
java
ninjamac@ninjamacdeMacBook-Air fluxcd % flux check --pre
► checking prerequisites
✔ Kubernetes 1.32.2 >=1.30.0-0
✔ prerequisites checks passed
在集群中安装flux
java
ninjamac@ninjamacdeMacBook-Air fluxcd % flux bootstrap github \
--owner=$GITHUB_USER \
--repository=fluxcd \
--branch=main \
--path=. \
--personal
将 podinfo 仓库添加到 Flux
本示例使用公共仓库 github.com/stefanprodan/podinfo,podinfo 是一个用 Go 语言编写的小型 Web 应用程序。
创建一个指向 podinfo 仓库 master 分支的 GitRepository 清单:
java
flux create source git podinfo \
--url=https://github.com/stefanprodan/podinfo \
--branch=master \
--interval=1m \
--export > ./podinfo-source.yaml
提交并将 podinfo-source.yaml 文件推送到 fluxcd仓库:
java
git add -A && git commit -m "Add podinfo GitRepository"
git push origin main
部署 podinfo 应用
配置 Flux 以构建并应用位于 podinfo 仓库中的 kustomize 目录。
使用 flux create 命令创建应用 podinfo 部署的 Kustomization。
java
flux create kustomization podinfo \
--target-namespace=default \
--source=podinfo \
--path="./kustomize" \
--prune=true \
--wait=true \
--interval=30m \
--retry-interval=2m \
--health-check-timeout=3m \
--export > ./podinfo-kustomization.yaml
提交 Kustomization 清单并将其推送到代码库:
java
git add -A && git commit -m "Add podinfo Kustomization"
git push origin main
监控 Flux 同步应用程序
使用 flux get 命令监控 podinfo 应用程序。

使用kubectl get 命令检查pod service 等信息:

对主分支中 podinfo Kubernetes 清单所做的更改会反映在您的集群中。
当从 podinfo 仓库中移除 Kubernetes 清单时,Flux 会将其从您的集群中移除。当您从 fluxcd 仓库中删除 Kustomization 时,Flux 会移除之前从该 Kustomization 应用的所有 Kubernetes 对象。
当您使用 kubectl edit 修改 podinfo 部署时,更改会还原到与 Git 中描述的状态一致。
暂停更新
暂停 Kustomization 的更新允许您直接编辑从 Kustomization 应用的对象,而不会根据 Git 中的状态还原您的更改。
要暂停 Kustomization 的更新,请运行命令 flux suspend kustomization <name>。
要恢复更新,请运行命令 flux resume kustomization <name>。
自定义 podinfo 部署
要从您无法控制的仓库自定义部署,您可以使用 Flux 内联补丁。以下示例展示了如何使用内联补丁更改 podinfo 部署。
将以下内容添加到 podinfo-kustomization.yaml 文件的字段规范中:
java
patches:
- patch: |-
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
name: podinfo
spec:
minReplicas: 3
target:
name: podinfo
kind: HorizontalPodAutoscaler
提交并推送 podinfo-kustomization.yaml 的更改:
java
git add -A && git commit -m "Increase podinfo minimum replicas"
git push origin main
同步完成后,运行 kubectl get pods 应该会显示 3 个 pod。

总结
对于任何新技术,我们都必须思考的几个问题之一是它解决了哪些问题。之前的工具遗漏了什么?GitOps 工具带来了哪些新特性?
在 GitOps 工具出现之前,声明式期望状态就已经被使用。正如我们提到的,这是 GitOps 出现之前现代 IaC 工具的标志之一。声明式期望状态也应用于 Kubernetes 本身。可以说,GitOps 工具已经很好地采用了这种做法。
在 GitOps 工具出现之前,使用版本控制来存储期望状态也是一种常见的范例,但 GitOps 通过强制使用版本控制系统 (VCS) 将这种方法更进一步。其他工具可以从开发人员的机器上应用期望状态。使用 GitOps 时,必须将更改推送到远程 Git 存储库才能进行部署。
GitOps 为 IaC 生态系统带来的另一个新特性是从 Git 存储库中提取期望状态,而不是使用 CD 工具进行推送。这带来了一种新的安全强化方式。
我们可以毫不夸张地说,GitOps 工具带来的最大改进是持续的漂移检测和协调。这显然是真正的游戏规则改变者。通过此功能,我们可以构建不可变的基础设施并消除人为错误。如今,甚至有一些工具将此功能引入了 Terraform 领域。Flux Terraform Provider(实验性)和 Crossplane Terrajet Providers(在某种程度上,因为它们使用 Terraform Providers 生成 Kubernetes CRD)就是其中两个。
正如那句名言所说,没有灵丹妙药。每种技术都有其优缺点。我们在前面的段落中已经提到了 GitOps 的优点。多年来,凭借围绕云原生生态系统聚集的庞大社区,GitOps 工具已经解决了许多问题。大多数问题在早期的 GitOps 工具中都存在,但随着时间的推移,这些问题逐渐演变。现在是采用 GitOps 的好时机。列举一些目前相对存在的问题,大型云供应商提供的 PaaS 产品并不多(我们可以在这里列举 Anthos Config Management 和 Azure Arc),我们需要一个 Kubernetes 集群来应用 GitOps(对包括我在内的大多数社区成员来说这不是问题),Git 提供了回滚机制来回滚更改,但 git 有不同的回滚命令,因此必须谨慎处理,GitOps 和水平 Pod 自动伸缩器的协同工作也是另一个需要仔细思考的点。 GitOps 也不支持不同环境之间的传播,必须使用另一个 CI/CD 工具来处理。