Argo CD GitOps 入门实战:从 Git 仓库到集群自动同步

手动 kubectl apply 上线有三个老问题:集群现状没人说得清、改动没有评审记录、回滚靠翻聊天记录找当时的 YAML。GitOps 的答案是把 Git 仓库作为唯一事实源:期望状态全部声明在 Git 里,由集群内的控制器持续比对并自动对齐。本文用 Argo CD 把这套模式跑起来,覆盖安装、Application 定义、同步策略和多环境组织,读完即可在一套测试集群上完成第一次自动同步。

适用环境:Kubernetes 1.24 及以上,有一个可用的 Git 仓库(GitHub、GitLab、自建 Gitea 均可),示例清单用普通 YAML + Kustomize 组织。

先理解模型:声明式与持续对账

GitOps 和「流水线里跑 kubectl apply」的本质区别在对账模型:

  • 声明式:Git 里存的是期望状态(Deployment 应该是 3 副本、镜像是哪个版本),不是操作步骤;
  • 持续对账:Argo CD 周期性地拿 Git 里的期望状态与集群里的实际状态比对,不一致就标记 OutOfSync,并按策略自动或手动拉齐;
  • 方向反转:是集群内的控制器主动拉取 Git,而不是外部流水线把变更推进集群——集群凭据不出集群,Git 仓库只需读权限;
  • 自愈的基础:有人绕过 Git 直接改了集群,控制器能发现并改回去,这是「配置漂移」治理的落点。

前置条件

  • kubectl 可连接目标集群,且有创建 Namespace 与 CRD 的集群级权限(仅安装阶段需要);
  • 准备一个 Git 仓库存放应用清单,文中以 https://git.example.com/platform/apps.git 占位;
  • 集群出口能访问该 Git 仓库(私有仓库需准备只读凭据)。

第一步:安装 Argo CD 并登录

官方清单安装最省事,适合入门和中小规模;大规模或需要高可用时再考虑官方 Helm Chart 调副本与资源。

kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 等核心组件就绪
kubectl wait --for=condition=Available deployment/argocd-server -n argocd --timeout=180s

# 取初始 admin 密码(首次登录后应立即修改,并考虑接入 SSO)
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d; echo

# 本地调试时用端口转发访问界面;正式使用应通过 Ingress 暴露并配 TLS
kubectl port-forward svc/argocd-server -n argocd 8080:443

第二步:定义 Application——界面点选与 YAML 声明

Application 是 Argo CD 的核心资源:它把一个「Git 仓库 + 路径」与一个「目标集群 + 命名空间」绑定起来。界面上可以点选创建,适合第一次体验;但正式使用强烈建议用 YAML 定义并把 Application 本身也放进 Git 管理(不然管应用的东西又变成手工点了)。一份最小可用的定义:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: demo-app-prod
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://git.example.com/platform/apps.git
    targetRevision: main            # 也可固定 tag 或 commit,避免分支漂移
    path: apps/demo-app/overlays/prod
  destination:
    server: https://kubernetes.default.svc   # 同集群部署用内置地址
    namespace: prod
  syncPolicy:
    automated:
      prune: false                  # 先关:自动删除很危险,理解后再开
      selfHeal: false               # 先观察一轮手工同步,确认无误再开自愈
    syncOptions:
      - CreateNamespace=true        # 目标命名空间不存在时自动创建
kubectl apply -f application-demo-prod.yaml
argocd app get demo-app-prod        # 或在界面查看同步状态与健康状态

注意 Argo CD 区分两个状态:Sync 状态(和 Git 是否一致)与 Health 状态(资源是否健康)。OutOfSync 不一定有故障,可能只是还没同步;Synced 但 Degraded 则是应用自身不健康,要去查工作负载而不是 GitOps。

第三步:同步策略——自动同步、自愈与修剪的边界

三个开关决定控制器的「胆子」大小,建议按阶段逐步打开:

  • 自动同步(automated):发现 Git 有新提交就自动同步。适合测试环境无条件开启;生产环境开启前,务必保证 Git 的合并评审就是发布评审,因为合并即上线;
  • 自愈(selfHeal):集群里被手工改动后自动改回 Git 状态。它是对抗配置漂移的利器,但也会把故障时的人工止损操作「纠正」回去——应急时先关自愈再动手,并把这条写进值班手册;
  • 修剪(prune):Git 里删掉的资源,同步时在集群里也删掉。不开它,删文件只是不再管理,资源会残留;开了它,重命名路径、移仓库这类操作可能被误判为「全部删除」。开启 prune 的前提:仓库路径变更要当重大变更评审,且重要资源加注解 argocd.argoproj.io/sync-options: Prune=false 做个体豁免。

另外一个容易忽略的字段是同步波次:同一 Application 内资源默认按类型顺序同步,个别有依赖关系的资源可用注解 argocd.argoproj.io/sync-wave: "-1" 控制先后(数值小先同步),比如先建 CRD、命名空间,再发工作负载。

第四步:多环境仓库组织——Kustomize overlay 衔接

一个应用多个环境,推荐「一份 base + 每环境一个 overlay」的 Kustomize 结构,与 Argo CD 一环境一个 Application 正好对应:

apps/demo-app/
├── base/                  # 公共清单:Deployment、Service 等,只写一遍
│   ├── deployment.yaml
│   ├── service.yaml
│   └── kustomization.yaml
└── overlays/
    ├── dev/               # 差异:副本数、镜像 tag、资源配额、域名
    │   └── kustomization.yaml
    ├── test/
    └── prod/
# overlays/prod/kustomization.yaml
resources:
  - ../../base
images:
  - name: harbor.example.com/apps/demo-app
    newTag: "1.4.2"
replicas:
  - name: demo-app
    count: 3
patches:
  - patch: |-
      - op: replace
        path: /spec/template/spec/containers/0/resources/limits/memory
        value: 512Mi
    target:
      kind: Deployment
      name: demo-app

镜像 tag 的更新动作(流水线构建出新镜像后改 overlay 里的 newTag 并提交)就是 GitOps 的标准发布动作:留痕在 Git、回滚就是 revert 那次提交。仓库组织上有两种流派:清单和应用代码同仓(小团队方便),或单独的配置仓库(权限与评审独立,大多数团队的最终选择)。无论哪种,一个 Application 只对应一个 path,不要用一个 Application 管多个应用。

关于密钥:一句交代

Git 里不能存明文密钥。Argo CD 本身不解决这个问题,主流做法是 Sealed Secrets(公钥加密后可安全入库、集群内控制器解密)或 External Secrets 对接外部密钥系统;入门阶段先用 Sealed Secrets 即可,不要为了图省事把 base64 当加密——那只是编码。

验证

# 应用列表与状态总览
argocd app list
# 在 Git 里改一个副本数并提交,观察是否被自动发现并同步
argocd app get demo-app-prod --refresh
# 验证自愈:手工改集群,再看控制器是否将其拉回(selfHeal 开启时)
kubectl scale deploy/demo-app -n prod --replicas=1
kubectl get deploy/demo-app -n prod -w

常见问题

1. 长期 OutOfSync,但点开看不出差异。最常见来源是集群侧控制器给资源打的默认值与 Git 声明不一致:比如 HPA 在改副本数、准入 Webhook 注入的字段、Service 自动分配的 clusterIP 被回写等。处理分三类:该纳入 Git 的补进清单;属于平台默认值的,在 Application 里配 ignoreDifferences 精确忽略到字段级;HPA 与副本数冲突的,让 Git 里干脆不写 replicas。不要为图省事配全局通配忽略,那等于关掉对账。

2. 同步卡住或部分资源 Applying 不动。多半是资源间有先后依赖:先看同步波次与资源健康排序,再看失败资源的事件。典型例子是 CRD 还没建立就同步 CR 实例、或新版本的配置校验失败。Argo CD 界面里点进失败资源看 Events 和日志,比在命令行猜要快得多。

3. 开了 prune 后资源被误删。多发生在改仓库路径、切换分支、批量移动目录时,控制器把「新路径下没有的资源」理解为应删除。对策:路径类变更先关 prune 做一轮同步确认,再打开;对数据库、PVC 等有状态资源个体加 Prune=false 注解兜底。prune 不是不能开,而是要知道它删东西时不会再问第二遍。

4. 私有仓库拉不到、报认证失败。仓库凭据在 Argo CD 里以 Secret 形式单独登记,与 Application 定义分离。检查凭据是否过期、仓库地址协议是否一致(SSH 与 HTTPS 的凭据不能混用)、以及集群出口网络是否放通。对内网 Git 服务还要确认 TLS 证书是否被 repo-server 信任,自签证书需要在 Argo CD 配置里显式登记 CA 或(仅测试环境)跳过校验。

小结

GitOps 落地的关键不是装上 Argo CD,而是三件事跟上:清单仓库的评审流程等同于发布流程;自动同步、自愈、修剪三个开关按环境分阶段放开;密钥用 Sealed Secrets 之类的方案单独解决。做到这三点,集群变更就从「操作」变成了「可审计、可回滚的提交」,这正是 GitOps 相比流水线直推的核心收益。

发表回复

后才能评论