ArgoCD GitOps 实战:K8s 声明式持续部署

ArgoCD GitOps 正在成为 Kubernetes 持续部署的事实标准。它的核心理念只有一句话:把 Git 仓库当作集群状态的唯一可信源,任何部署变更都先改 Git,再由控制器把差异同步到集群。相比传统由人手动执行 kubectl apply 或在 CI 流水线里硬编码部署步骤,GitOps 让”集群现在是什么样”和”Git 里定义的是什么样”始终保持一致,出了问题 git revert 一条命令就能回滚。

一、为什么需要 GitOps

在 GitOps 之前,团队的部署可信源往往是”某个人脑子里的操作步骤”或”上次跑成功的 Jenkins 任务”。当集群被临时改坏、又被遗忘时,没有人说得清生产环境到底该是什么状态。GitOps 把这个问题彻底结构化:Git 里的清单即期望状态,控制器周期性比对实际状态,发现漂移(Drift)就自动或告警式修正。这和 GitHub Actions 实战:从零搭建 CI/CD 流水线 中”CI 负责构建与推送镜像”形成天然分工——CI 产出制品,CD 由 ArgoCD 负责落地。

维度传统 CI/CDGitOps
部署触发流水线主动推送Git 合并即触发
可信源人或脚本记忆Git 仓库
集群漂移难以发现自动检测 OutOfSync
回滚手动重跑流水线git revert 即回滚
审计日志分散Git 历史即审计

举个真实例子:某次线上抖动,值班同学为快速止血直接 kubectl edit 改了副本数和一处环境变量,故障暂时压住,但这次变更没有进任何仓库。两周后一次例行发布把 Deployment 覆盖回旧清单,问题原样复现,却没人能说清当初为什么改。如果走 GitOps,每一次变更都是一条带评审记录的 PR,这种”幽灵修改”从根源上就不会发生。

二、核心架构:三组件与同步循环

ArgoCD 由三部分协作:API Server(提供 UI/CLI/REST)、Repository Server(拉取并缓存 Git/Helm 清单)、Application Controller(持续比对实际状态与期望状态)。控制器每 3 分钟(默认)轮询一次,一旦发现 OutOfSync 就按策略同步。理解这套循环,是后续排查”为什么没同步”的基础,它运行在 K8s 入门:Pod、Deployment、Service 核心概念 之上的控制层。

三、GitOps 工作流:一次变更的生命周期

理解 GitOps 最好的方式是跟踪一次变更从开发到上线的完整链路。开发在功能分支提交清单改动并发起 PR,CI(例如 GitHub Actions)负责构建镜像、跑测试并把新镜像 tag 写回清单仓库;合并到 main 后,ArgoCD 在下一个轮询周期发现 Git 与集群不一致,自动拉取新清单并执行同步。整个过程里,人只和 Git 打交道,集群被视为”可由 Git 重建的声明”。

这条链路带来三个实打实的好处。其一,环境一致性:测试、预发、生产可以共用同一套清单模板,仅通过 overlays 或不同路径区分,再也不会出现”我机器上是好的”。其二,可审计:任何一次上线都能在 Git 历史里精确到人和时间。其三,可恢复:灾难恢复时只要把 Git 仓库克隆下来重新 apply,集群就能在分钟级重建。

值得注意的是,GitOps 并不排斥传统的 CI。相反,二者是黄金搭档——CI 保证”制品正确”,GitOps 保证”部署正确”。把镜像构建这类重活留在 CI,把只改 Git 的轻量同步留给 ArgoCD,职责清晰、互不打扰。

四、快速安装:Helm 一键部署

官方推荐用 Helm 安装,最省心。下列命令会新建独立命名空间并部署整套组件。如果不想用 Helm,也可以直接 kubectl apply 官方提供的 manifests 或 Kustomize 版本,本质一致,只是包管理方式不同。

# 添加 ArgoCD 官方 Helm 仓库并安装到独立命名空间
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
kubectl create namespace argocd
helm install argocd argo/argo-cd \
  --namespace argocd \
  --set server.service.type=ClusterIP \
  --set configs.params.server.insecure=true

等待所有 Pod 进入 Running 后,即可通过端口转发访问 UI:kubectl port-forward svc/argocd-server -n argocd 8080:443

五、第一个应用:Application 清单详解

ArgoCD 的核心资源是 Application,它声明”从哪个 Git 仓库、哪个路径、同步到哪个集群命名空间”。下面是一个最小可运行示例:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: guestbook
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/manifests.git
    targetRevision: HEAD
    path: guestbook
  destination:
    server: https://kubernetes.default.svc
    namespace: default
  syncPolicy:
    automated:
      prune: true        # 删除 Git 中已移除的资源
      selfHeal: true     # 集群被手动改坏时自动修正

其中 automated.pruneselfHeal 是 GitOps 的两大护法:前者保证”Git 删了集群也删”,后者保证”有人手改集群会被自动拉回 Git 定义”。

六、声明式部署实战:从 Git Push 到集群生效

安装后,用 CLI 登录并触发首次同步:

# 获取初始 admin 密码
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d; echo
argocd login localhost:8080 --username admin --password <SECRET>
argocd app create guestbook \
  --repo https://github.com/example/manifests.git \
  --path guestbook --dest-server https://kubernetes.default.svc \
  --dest-namespace default
argocd app sync guestbook

此后你只需向 Git 的 guestbook 路径提交变更,ArgoCD 会在下一个轮询周期自动拉取并同步,无需再碰 kubectl。这正是”持续部署”的精髓:部署动作被 Git 事件驱动。

七、多环境管理:App of Apps 模式

当应用变多,逐个维护 Application 会很痛苦。推荐 App of Apps 模式:用一个”父 Application”指向存放其他 Application 清单的目录,实现批量托管。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: apps-all
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/example/gitops.git
    path: apps          # 该目录下每个子目录都是一个 Application
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated: { prune: true, selfHeal: true }
状态含义处理建议
Synced集群等于 Git正常,无需干预
OutOfSync存在差异自动或手动 sync
Healthy资源已就绪正常
Degraded资源异常查 kubectl describe 事件
Progressing同步进行中等待完成即可

八、健康状态与自愈:Drift 检测与回滚

因为开启了 selfHeal,当有人误执行 kubectl scale 改了副本数,控制器会立刻把集群拉回 Git 定义。若一次发布导致 Degraded,最稳的回滚方式是回到上一个 Git commit 并同步——Git 历史就是你的部署审计与时光机。这一能力在复杂网络环境下尤其有价值,类似 Cilium 实战:用 eBPF 数据面替代 kube-proxy 踩坑记 中强调的”声明式即可恢复”。

需要提醒的是,selfHeal 并非对所有工作负载都该无脑开启。对于有状态应用(如数据库主从、消息队列),集群内部的运行态往往包含 Git 里无法表达的临时状态,盲目自愈可能打断正在进行的副本同步。这类负载建议关闭 selfHeal,改为仅告警、由人工确认后再同步,把”自动修正”降级为”自动发现”。

九、安全与可观测:RBAC、Webhook 与监控接入

生产环境务必收紧权限。ArgoCD 通过 ConfigMap 定义 RBAC 策略,把团队映射到角色:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.csv: |
    p, role:developer, applications, get, */*, allow
    p, role:developer, applications, sync, */*, allow
    g, dev-team, role:developer

可观测性方面,把 ArgoCD 的 metrics 接入既有监控栈即可实时看到同步成功率:

# prometheus 抓取 ArgoCD metrics
- job_name: argocd
  metrics_path: /metrics
  static_configs:
    - targets: ['argocd-metrics.argocd.svc:8082']

这与 Prometheus + Grafana 监控面板实战 的采集体系天然契合,也可和 Istio 服务网格入门:流量治理与 mTLS 实战 组合成完整的云原生可观测闭环。

十、常见坑位与排查清单

落地 ArgoCD 时,下面几个坑出现频率最高,建议上线前逐一核对:

  • 仓库凭证失效:Private 仓库需配置 Repository Credentials 或 SSH key,否则控制器拉取超时,状态长期 OutOfSync。
  • targetRevision 写死某个 tag:镜像更新后 Git 没变,ArgoCD 不会重新同步;建议生产用固定 commit 或分支,由 CI 负责更新引用。
  • 有状态应用误开 selfHeal:参考第八节,避免自动修正打断副本同步。
  • RBAC 过宽:默认账号权限很大,务必按团队拆分 role,遵循最小权限原则。
  • 忽略 Sync Hook:数据库迁移等必须在同步前后执行的任务,应使用 Pre/Post Sync Hook 而非手动操作。

十一、行动清单:今天就能落地

  • 用 Helm 在测试集群装一套 ArgoCD,熟悉 UI 与 CLI。
  • 把一个现有 Deployment 改造成 Git 仓库里的清单,托管为第一个 Application。
  • 开启 automated.prune + selfHeal,故意手改一次集群验证自愈。
  • 接入 RBAC 与 Prometheus 抓取,让部署可审计、可观测。
上一篇 WebAssembly 实战:把 Rust 编译进浏览器,给前端加上原生级性能
下一篇 LLM-as-Judge 实战:用大模型自动评测输出质量