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 相比流水线直推的核心收益。






