引言
在上一篇我们讨论了 Jenkins 与 GitLab CI 如何把镜像构建、部署到集群,本质上是「Push 模式」——CI 主动把资源推到 K8s。但当集群规模扩大、环境变多、审批链路变长之后,Push 模式会逐渐暴露出三个痛点:集群状态与实际想达的状态不一致(drift)、无法从单一源头追溯谁在什么时候改了什么、以及回滚困难。GitOps 就是为了解决这三个痛点而生的一种运维哲学:把 Git 仓库作为集群期望状态的唯一事实源,由常驻集群的控制器持续比对 Git 与实际集群,自动收敛到期望状态。
Argo CD 是 CNCF 官方毕业项目,也是目前最主流的 GitOps 工具之一。它以 Kubernetes 原生方式运行在集群内,通过 Repository、Application、Sync、Sync Policy 四个核心概念,把「Git 提交一次、集群自动持续同步」的体验带给运维和开发。本篇将完整搭建 Argo CD,实现从 Git 到 K8s 的声明式部署,覆盖应用管理、同步策略、自动回滚、App of Apps 与多集群同步等进阶用法。

GitOps 理念与 Argo CD 架构
从 Push 到 Pull 的范式转变
传统 CI/CD 是流水线 Push 资源到集群,命令执行完就结束了,之后集群状态如何演进流水线无法感知。GitOps 反过来:常驻控制器 Pull Git 最新状态,持续 diff,发现偏差就发起 sync。这带来三个直接好处:可追溯(每次变更都是 Git commit)、可回滚(git revert 即可)、可自愈(Pod 被删除、镜像被改写,控制器都能恢复)。
Argo CD 的核心组件
Argo CD 由三个组件构成,全部运行在集群内:
- argocd-server:提供 Web UI、REST API 与 CLI 后端,是运维交互入口。
- argocd-repo-server:负责拉取 Git 仓库、渲染模板(支持 Kustomize、Helm、Jsonnet、Ksonnet)。
- argocd-application-controller:核心控制器,定期比对 Git 期望状态与集群实际状态,触发 sync。
四大核心概念
- Repository:Git 仓库连接信息,支持 HTTPS、SSH、GitHub App、OIDC 等多种认证方式。
- Application:Argo CD 的顶层对象,描述「部署什么、从哪部署、部署到哪」。
- Sync:把 Git 状态应用到集群的操作,可手动或自动触发。
- Sync Policy:同步策略,包含自动同步(automated)与钩子(preSync/sync/postSync webhook)。
核心概念详解
Application 资源剖析
Application 是 Argo CD 的心。它把「Git 路径 + K8s 目标」连起来,一个 Application 可以部署单个或多个 K8s 资源。
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/stellardata/k8s-manifests.git
targetRevision: main
path: apps/myapp/production
helm:
valueFiles:
- values-prod.yaml
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- ServerSideApply=true
关键字段说明:source.repoURL 指向 Git 仓库,source.path 指定子目录,source.targetRevision 支持分支、Tag 或 Commit SHA,destination.server 与 destination.namespace 指定目标集群与命名空间,syncPolicy.automated.prune 让 Git 删除的资源在集群中同步删除,selfHeal 让集群被漂移后自动修复。
Sync Policy 三种模式
| 模式 | 触发方式 | 适用场景 |
|---|---|---|
| 手动 Sync | 运维在 UI 或 CLI 点击 sync | 生产环境、需要审批的变更 |
| 自动 Sync(automated) | Git 提交后自动同步 | 开发、测试环境 |
| 条件 Sync(webhook) | 仅 Git 仓库变更时触发 | 兼顾安全与自动化的生产 |
自动 Sync 结合 prune: true 与 selfHeal: true 是最强力的 GitOps 形态:Git 是权威,集群一切偏离都会被收敛回来。
与 Kustomize、Helm 的协作
GitOps 不等于只用裸 YAML。Kustomize 适合「多环境同一份 base」,Helm 适合「参数化模板」。Argo CD 原生支持三种渲染方式,通过 source.path 下是否存在 kustomization.yaml 或 Chart.yaml 自动识别,也可以在 Application 里显式声明:
spec:
source:
path: apps/myapp
kustomize:
images:
- myapp:harbor.stellardata.top/app/myapp:v1.2.3
实战步骤
步骤一:使用 Helm 部署 Argo CD
Argo CD 官方推荐使用 Helm 部署,稳定、可配置、便于升级。
# 添加官方仓库
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update
# 创建专用命名空间
kubectl create namespace argocd
# 安装 Argo CD
helm install argocd argo/argo-cd
-n argocd
--set server.service.type=ClusterIP
--set controller.replicas=2
--set controller.resources.requests.cpu=200m
--set controller.resources.requests.memory=256Mi
--wait --timeout 15m
安装完成后,通过 Port-Forward 访问 UI:
# 获取初始管理员密码
kubectl -n argocd get secret argocd-initial-admin-secret
-o jsonpath="{.data.password}" | base64 -d
# 端口转发到本地 8080
kubectl -n argocd port-forward svc/argocd-server 8080:443
步骤二:使用 Argo CD CLI 与配置集群
Argo CD CLI 支持直接对接集群,无需额外 kubeconfig:
# 安装 CLI
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/download/v2.11.0/argocd-linux-amd64
chmod +x argocd && sudo mv argocd /usr/local/bin/
# 登录 UI 对应的 API
argocd login localhost:8080 --username admin --password '<初始密码>'
# 查看集群连接状态
argocd cluster list
# 添加第二个集群
argocd cluster add k8s-prod-2
--name prod-cluster-2
--server https://10.0.1.100:6443
--secret-name prod-cluster-2
在集群内创建的 ServiceAccount 与绑定权限,Argo CD 会自动注册为可用于同步的目标集群。
步骤三:创建 Repository 与应用
将生产 Git 仓库连接到 Argo CD,然后创建 Application 完成首次同步:
# 添加 Git 仓库
argocd repo add https://github.com/stellardata/k8s-manifests.git
--username bot --password "$GH_TOKEN"
# 创建 Application
cat > app-myapp.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: myapp
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/stellardata/k8s-manifests.git
targetRevision: main
path: apps/myapp
helm:
releaseName: myapp
valueFiles:
- values-prod.yaml
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true
EOF
argocd app create -f app-myapp.yaml
# 查看同步状态
argocd app get myapp
步骤四:配置 Git Webhook 与自动同步
自动同步是 GitOps 的灵魂。默认情况下 Argo CD 每 3 分钟轮询一次 Git,如果希望通过推送立即触发,可以配置 Webhook:
# 查看 Webhook 服务地址
kubectl -n argocd get svc argocd-server -o wide
# 在 GitHub 仓库设置中添加 Webhook
# URL: https://argocd-server.stellardata.top/api/webhook
# Content type: application/json
# Events: Push only
如果 Argo CD 部署在内网、无法直接被 GitHub 访问,可以借助中间层:
# 使用 nginx Ingress 代理 GitHub Webhook
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: argocd-webhook
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /api/webhook
spec:
rules:
- host: argocd.stellardata.top
http:
paths:
- path: /api/webhook
pathType: Prefix
backend:
service:
name: argocd-server
port:
number: 443
步骤五:使用 App of Apps 管理多应用
当应用数量超过 20 个时,逐个 argocd app create 会失控。Argo CD 支持「Application 里再放 Application」的 App of Apps 模式,用一个 Git 目录管理所有应用:
k8s-manifests/
├── apps-of-apps/
│ └── app-of-apps.yaml # 元应用,指向 applications 目录
└── applications/
├── myapp.yaml # 单个 Argo CD Application
├── payment.yaml
└── order.yaml
# apps-of-apps/app-of-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: apps-of-apps
namespace: argocd
spec:
source:
repoURL: https://github.com/stellardata/k8s-manifests.git
path: applications
targetRevision: main
destination:
server: https://kubernetes.default.svc
namespace: argocd
syncPolicy:
automated:
prune: true
selfHeal: true
步骤六:同步钩子与 Git 自动化回滚
Argo CD 支持在同步前后运行任意命令(通过 preSync/sync/postSync hooks),例如清理数据库表结构迁移:
apiVersion: batch/v1
kind: Job
metadata:
name: migrate-schema
annotations:
argocd.argoproj.io/hook: PreSync
argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
template:
spec:
containers:
- name: migrate
image: harbor.stellardata.top/app/myapp-migrate:v1
args: ["/app/migrate.sh"]
restartPolicy: Never
如果自动同步失败,可以配置回滚策略到上一次成功版本:
spec:
syncPolicy:
automated:
prune: true
selfHeal: true
retry:
limit: 3
backoff:
duration: 10s
factor: 2
maxDuration: 5m
常见问题 FAQ
Q1:Application 显示 OutOfSync,如何快速定位差异?
argocd app diff myapp 会输出 Git 与集群的字段级差异,包括资源新增、删除、修改。UI 中的 Changes 标签页也展示同类信息。如果差异是集群侧被人为改动,argocd app sync myapp --self-heal 会自动恢复;如果是 Git 尚未包含的期望变更,则需先合入 Git 再同步。
Q2:如何保证生产环境必须审批才能同步?
关闭 syncPolicy.automated,改用手动 sync 或 --auto-prune=false 的 GitOps Policy。更彻底的方案是 Argo CD 的 AppProject + RBAC:为运维角色配置只允许 get 与 list,生产同步权限授予少数 SRE,并在企业侧接入 SSO 与 MFA。
# appproject.yaml 示例
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
name: production
spec:
sourceRepos:
- 'https://github.com/stellardata/k8s-manifests.git'
destinations:
- server: https://kubernetes.default.svc
namespace: production
rbacRules:
- roles: ['admin']
actions: ['*', 'sync']
Q3:Git 权限怎么最小化?
GitOps 场景下,只需要一个只读 Token 或 SSH Key,Argo CD 只用它 pull 仓库内容,不需要 push 权限。企业级做法是使用 GitHub App 或 OIDC 短期 Token,避免长期 Token 泄露风险。
Q4:Argo CD 与 Jenkins/GitLab CI 是什么关系?
两者职责不同:CI 负责构建镜像、生成制品;GitOps 负责把制品(或 K8s 清单)声明到 Git,并由 Argo CD 应用到集群。推荐组合是 CI 产出镜像 + 更新 Git 里的 imageTag 字段,Argo CD 通过自动 Sync 部署。CI 不再直接 kubectl apply,实现「CI 只写 Git、集群只读 Git」的清晰边界。
Q5:同步延迟一般多久?如何调优?
默认轮询周期为 3 分钟,可在 Helm values 中调整 application.instance.refresh.interval。生产推荐用 Webhook 触发(毫秒级),配合合理轮询作为兜底。对于大规模集群(>500 Applications),建议开启 Application Controller 的分片机制,把同步负载分摊到多个 controller 副本。
总结
GitOps 把「Git 是集群状态唯一事实源」这句话变成工程实践:CI 只负责写 Git、Argo CD 只负责读 Git 并同步集群、运维与开发只在 Git 上操作。本篇从 Argo CD 架构、Application 资源、Sync Policy、Kustomize/Helm 集成,到 App of Apps、Webhook、AppProject 与 RBAC,给出了完整落地路径。
实践要点:自动同步 + prune + selfHeal 是 GitOps 的三大开关;App of Apps 让集群管理扩展到 100+ 应用;Git Webhook 让同步延迟从分钟级降到秒级;AppProject + RBAC 让权限与审批清晰可查。把这些能力组合起来,你就拥有了一个「Git 提交一次、集群持续收敛、错误自动回滚」的云原生运维体系。
下期预告
K8s 运维系列 | 第 28 天:灰度发布——金丝雀、蓝绿与滚动发布实践


















暂无评论内容