GitOps 实战:ArgoCD 与 Flux 的 Kubernetes 持续部署

本文讨论 ArgoCD 与 Flux 在 Kubernetes 持续部署中的核心机制、配置差异和选型思路。结合真实团队常见场景,分析两套 GitOps 工具的适用边界、常见配置坑与落地步骤,适合正在搭建部署体系的开发者和平台工程师阅读。

GitOps 真的只是“用 Git 存 YAML”吗

接触过不少团队,把 ArgoCD 或 Flux 装好之后,第一件事就是把它当成一个“高级发布按钮”来用——写一个 Application 或 Kustomization 指向某个 Git 目录,勾上自动同步,然后就不再看了。直到某天线上配置被误改,或者目录里的清单和集群状态对不上,才发现事情没有想象中简单。

AI technology illustration

GitOps 的核心并不复杂:用 Git 仓库保存系统期望状态的所有声明,然后由集群内的控制器不断把实际状态拉向期望状态。放在 Kubernetes 持续部署里,这个期望状态就是一组 YAML,控制器的工作类似一个持续的 kubectl apply。但这里有两个关键点经常被忽略:一是期望状态必须足够完整,二是控制器必须有权限处理一切配置偏移。

ArgoCD 和 Flux 分别是怎么工作的

ArgoCD 和 Flux 虽然被放在一起比较,但架构哲学差别很大。ArgoCD 是一个完整的“应用”管理模型。它把整个目标目录抽象成一个 Application 资源,里面直接描述来源、目标集群和同步策略,并通过一个比较厚的管理控制器完成同步、UI 展示、RBAC 和回滚操作。它的 Web UI 做得相当好,可以看到每个应用的健康状态、资源树和同步历史,这对团队跨部门协作很有吸引力。

Flux 的思路更偏平台化。它没有把一切装进一个大控制器,而是用 source-controller、kustomize-controller、helm-controller、notification-controller 等一组控制器拼接出交付链路。Flux 不会告诉你“应用”是什么,它只提供机制:gitrepository 负责拉取代码,Kustomization 和 HelmRelease 负责定义渲染后的资源怎么 apply。想用的时候,自己组合。

一个典型的团队是这么陷入 GitOps 的:镜像构建已经放在 CI 里,测试环境的部署靠脚本执行 kubectl set image,生产环境则由运维手工操作。随着服务拆分,一次发布要更新几十个镜像,线上状态越来越混乱。引入 GitOps 后,他们真正解决的不是“自动部署”,而是“让部署行为可追溯”。ArgoCD 和 Flux 都能做到这一点,但工作的方式会很不一样。

一份部署清单的配置对比

下面用两段 YAML 说明它们描述应用方式的差异。ArgoCD 是这样定义的:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app
  namespace: argocd
spec:
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  source:
    repoURL: https://git.example.com/platform/my-app.git
    path: manifests/prod
    targetRevision: main
  syncPolicy:
    automated:
      selfHeal: true

Flux 则需要先声明一个 GitRepository,再由 Kustomization 引用:

apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: my-app
  namespace: flux-system
spec:
  interval: 5m
  path: ./manifests/prod
  prune: true
  sourceRef:
    kind: GitRepository
    name: my-app
  targetNamespace: production

这个对比能看出两个明显区别。ArgoCD 直接通过 repoURL 知道自己要从哪个仓库拉取,而 Flux 需要先有一个 GitRepository 对象作为 Source,Kustomization 再引用它。也就是说,Flux 把“从哪拉”和“怎么部署”拆成了两个阶段,这样同一个 Source 可以被多个 Kustomization 复用。另外,ArgoCD 默认不会自动清理被手工删除的资源;Flux 的 prune: true 则要求垃圾回收。

两个工具在工程中的关键差异

真正做选型的时候,不能用社区贴文里的功能列表来做决定。如果团队只有一两个集群,希望快速获得可视化的同步界面,ArgoCD 通常更合适。如果团队是平台组,需要同时服务十几个业务集群,并且已经打算自建内部发布平台,Flux 的组件化会更容易嵌入,它的 CRD 也更薄,避免被过多上层语义限制住。

一个经常被忽略的细节是多集群支持。ArgoCD 倾向于把多个集群注册到同一个中央实例上统一管理,因此你可以在一个地方查看全局状态。Flux 则默认每个集群独立安装一个控制器,通过 Git 仓库中的目录结构来区分环境和集群。两种方式各有代价:集中式会引入单点和网络边界问题,独立式则要求平台团队对不同集群的部署结果有足够强的可观测工具。

评估维度 ArgoCD Flux
核心交付模型 Application 聚合应用完整状态 Source + Kustomization/HelmRelease 组合
可视化界面 功能完备,状态和操作都直观 以 CLI、事件和 API 为主,UI 依赖第三方
多集群管理 在一个 ArgoCD 中注册外部集群 每个集群独立安装,通过 Git 仓库组织
Helm 支持 支持 Helm 渲染和 values 覆盖 HelmRelease 原生支持,与 Source 链路结合紧密
密钥管理 常配 sealed-secrets 或 sops SOPS 集成好,也容易扩展外部密钥服务
默认同步行为 手动触发,可按需自动同步 按 interval 轮询,自动同步是常态
适用团队 中小团队、研发运维边界偏重运维 平台工程团队、需要自定义交付链路的场景

表格里没有绝对优劣。ArgoCD 的强 UI 本身就是一种约束,它把应用模型固定下来,对应用多但业务简单的小团队很友好;而 Flux 这种组合方式一旦熟悉之后,很容易做出非常灵活的发布策略。选择时还要看现状:你当前的 CI 是否已经有通知能力,你是否需要灰度发布、金丝雀分析这类更偏向 Argo Rollouts 或者 Flagger 的功能。

还有一点值得细看,就是两个工具在配置漂移上的默认态度。ArgoCD 会持续对比 Git 状态和集群实际状态,把差异结果显示在 UI 上,但除非你开启 automated sync,否则它不会主动纠正。Flux 的 controller 则是按 interval 轮询,发现差异后会自动 apply,这更符合“系统持续趋向期望状态”的模型。对于习惯手动发布流程的团队,ArgoCD 的默认行为更柔和;对于已经高度自动化的平台,Flux 的自动收敛更省心。

落地 GitOps 时最容易踩的坑

先说自动同步。很多团队一上来就开启自动同步加 selfHeal,然后某天发现一个用于扩展的 Deployment 的 tag 被覆盖掉。这其实是 GitOps 的预期行为,但业务端不一定会理解。这个问题在共享资源尤其明显,比如 Namespace、RBAC、Ingress。把不同团队的资源都放进一个 Application,很容易出现一次同步把别人的配置拉回旧版本的现象。更合理的做法是控制 Application/Flux 对象的边界,按照业务域或环境拆开。

第二个坑是密钥。明文私钥和数据库密码放到 Git 仓库,等于把安全底线交给仓库私有性。ArgoCD 生态更常见的是 sealed secrets,Flux 对 SOPS 有比较好的原生支持。但要注意,两者都需要额外的 controller 或 key 管理,这会增加部署复杂度,需要提前设计好。

第三个坑是绕过 Git 的手工修复。生产环境遇到紧急问题,第一反应是 kubectl edit 或 helm upgrade –force,这对非 GitOps 系统是常规操作,但 GitOps 环境下,控制器会在下一轮同步中把资源重新拉回仓库状态。你可以关闭同步来争取恢复时间,但根本解法是把热修复流程也搬进 Git,例如允许 release 分支直接合并并触发同步。

下面几条是对上面的小结:

  • 自动同步不是默认选项,要先用手动同步理解行为。
  • Application 的粒度不能太粗,也不能太细,否则管理成本爆炸。
  • 不要只把 ArgoCD 或 Flux 自身放在 Git 边界之外。

落地建议:从最小闭环开始

如果你正在规划把 ArgoCD 或 Flux 引入现有环境,建议先从一两个服务开始,不要一开始就追求覆盖所有集群和应用。先选一个不太核心的服务,把它的部署清单全部搬到 Git,然后通过工具同步。这个闭环里至少包含仓库、目录结构、部署方式、回滚方式四条主线。

  1. 仓库结构参考:mono-repo 中划分 infra/ 和 apps/,每个应用按环境分出目录,项目级 Kustomize overlay 管理差异。
  2. 部署动作改由合并 MR / PR 触发,通过 Git 的 commit 历史替代脚本日志。
  3. 不要把资源分成“Git 管理的”和“手工管理的”两种,只要它能被 Kubernetes 声明,就应该纳入 Git。
  4. 回滚流程写成文档,让所有人知道 revert 是一次部署,而不是 kubectl rollout undo。

回滚在 GitOps 里不是撤销,而是把仓库恢复到历史 commit,并让控制器把这个历史状态作为新的期望状态继续执行。

这不是一个二选一的问题

最后想说一点,ArgoCD 与 Flux 的选择并不需要一次定终身。很多团队会从 ArgoCD 开始,因为上手快,之后再慢慢将部分链路迁到 Flux,或者直接用 ArgoCD 管理 Flux 部署出来的资源——反过来也是可行的。真正重要的不是工具名,而是你是否愿意让 Git 成为集群运行的唯一事实来源。只要这一点确立了,工具的差异只是组织协作方式的延伸。

还在犹豫的话,可以先把两种方案都放在一个 test cluster 里跑一遍:用同一个 Git 仓库,分别用 ArgoCD 和 Flux 同步一个示例服务。观察它们在不同异常场景下的反应,比如手工改掉一个副本数、删掉一个 Secret、提交一个错误配置。很快你就会知道哪个模式更适合你的团队。

原创文章,作者:fudengji,如若转载,请注明出处:https://fudengji.cn/article/618/

(0)
上一篇 5小时前
下一篇 5小时前

相关推荐