文章

ArgoCD GitOps 实战

ArgoCD GitOps 实战

概述

ArgoCD 是 CNCF 毕业项目,实现声明式 GitOps —— Git 仓库是唯一的期望状态来源,ArgoCD 持续将集群实际状态与 Git 中的声明对齐。它是 kagent Agent 落地交付管道的核心组件(Agent → ArgoCD → K8s)。

一句话:Git 里有什么,集群就是什么。不是 kubectl apply 驱动的运维,而是 Git commit 驱动的运维。

GitOps 四原则

原则ArgoCD 实现
声明式描述Application CRD 声明”哪个 Git 仓库 + 哪个路径 + 哪个集群”
版本化、不可变每次变更 = git commit,完整审计日志
自动拉取每 3 分钟(可配)自动检测 Git 变更并同步
持续调和selfHeal: true 时,手动改了集群也会被自动回滚

架构

Git Repo (Manifests/Helm/Kustomize)
      ↓ 1. ArgoCD 定期检测变更
[ArgoCD API Server]  ← Web UI / CLI / gRPC

[ArgoCD Repo Server] → 2. Clone + 渲染(helm template/kustomize build)

[ArgoCD Application Controller] → 3. Diff(期望 vs 实际)
      ↓ 4. Sync
Kubernetes API Server → Target Cluster
组件职责
API ServerREST/gRPC API + Web UI,对外暴露管理界面
Repo Server从 Git 拉取仓库,执行 Helm/Kustomize/Jsonnet 渲染,生成最终 YAML
Application Controller持续对比期望状态 vs 实际状态,触发 Sync;管理 Application 生命周期
Redis缓存 Git 仓库内容、Application 状态
ApplicationSet Controller根据模板 + Generator 自动生成多个 Application
Notifications ControllerSync 成功/失败/健康检查事件 → Slack/Webhook/邮件

核心 CRD

Application —— 最小可用单元

一个 Application = 一个 Git 仓库 + 一个目标路径 + 一个目标集群。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: health-ack
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/org/manifests.git
    targetRevision: main          # Git branch / tag / commit SHA
    path: overlays/prod/health-ack
    helm:
      valueFiles:
        - values-prod.yaml
      parameters:                 # 等价于 --set
        - name: image.tag
          value: "v2.3.1"
  destination:
    server: https://10.0.0.1:6443  # K8s API Server
    namespace: health
  syncPolicy:
    automated:
      prune: true                 # 自动删除 Git 中移除的资源
      selfHeal: true              # 集群中被手动改了 → 自动回滚
      allowEmpty: false           # 不允许 Git 目录为空
    syncOptions:
      - CreateNamespace=true      # 自动创建 namespace
      - PruneLast=true            # Sync 时先创建新资源再删旧资源
    retry:
      limit: 5
      backoff:
        duration: 5s
        maxDuration: 3m

AppProject —— 权限与边界

限制 Application 可以访问哪些 Git 仓库和目标集群:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: prod
  namespace: argocd
spec:
  description: Production applications
  sourceRepos:                     # 允许的 Git 仓库白名单
    - 'https://github.com/org/manifests.git'
  destinations:                    # 允许的目标集群 + namespace
    - server: https://10.0.0.1:6443
      namespace: 'health-*'        # 支持通配符
  clusterResourceWhitelist:        # 允许的集群级资源
    - group: '*'
      kind: Namespace
  namespaceResourceWhitelist:      # 允许的 namespaced 资源
    - group: '*'
      kind: '*'
  roles:                           # RBAC 角色(给 CI / 开发者用)
    - name: developer
      policies:
        - p, proj:prod:developer, applications, sync, prod/*, allow

ApplicationSet —— 批量管理

核心是 Generator(生成器),根据模板自动为多个集群/环境生成 Application:

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: health-services
  namespace: argocd
spec:
  generators:
    # Git 目录生成器:该仓库下每多一个子目录就多一个 Application
    - git:
        repoURL: https://github.com/org/manifests.git
        revision: main
        directories:
          - path: overlays/prod/*
  template:
    metadata:
      name: '{{path.basename}}'          # 目录名 → Application 名
    spec:
      project: prod
      source:
        repoURL: https://github.com/org/manifests.git
        targetRevision: main
        path: '{{path}}'
      destination:
        server: https://10.0.0.1:6443
        namespace: '{{path.basename}}'
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

Generator 类型速查

Generator用途适用场景
List静态列表少量固定环境
Git DirectoriesGit 仓库子目录按环境/应用分目录的仓库
Git Files解析 Git 中的 JSON/YAML从配置文件中读取环境列表
Cluster自动发现注册的 K8s 集群多集群 Fleet 管理
Pull Request为每个 PR 创建临时环境预览环境(Preview Env)
Matrix两个 Generator 的笛卡尔积集群 × 应用 矩阵
Merge多个 Generator 合并覆盖部分字段

App of Apps —— 应用树

“App of Apps” 模式:一个父 Application 管理多个子 Application。ArgoCD 自己管理自己。

# bootstrap-app.yaml — 父 Application
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: bootstrap
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/org/argocd-apps.git
    path: apps/           # 该目录下每个 YAML 定义一个 Application
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
bootstrap (Application)
  ├── apps/health-ack.yaml    → Application: health-ack
  ├── apps/api-tpa.yaml       → Application: api-tpa
  ├── apps/bigdata.yaml       → Application: bigdata
  └── apps/monitoring.yaml    → Application: monitoring

同步 (Sync) 机制

syncPolicy 决策矩阵

场景pruneselfHeal结果
Git 中删除 Deployment集群中的 Deployment 自动删除
手动 kubectl edit deployArgoCD 自动回滚到 Git 版本
Git 新增 ServiceArgoCD 自动创建 Service
Git 目录为空allowEmpty=false 时阻止 Sync

Sync 阶段与 Hook

Sync 分三个阶段,每个阶段可注入 Hook:

PreSync  → Sync  → PostSync
   ↓         ↓        ↓
 通知      应用 YAML   通知
 备份      等待健康    冒烟测试
# PreSync Hook:同步前备份数据库
apiVersion: batch/v1
kind: Job
metadata:
  name: db-backup
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: backup
          image: postgres:16
          command: ["pg_dump", "-h", "db.prod", ">", "/backup/dump.sql"]
      restartPolicy: Never

---
# PostSync Hook:冒烟测试
apiVersion: batch/v1
kind: Job
metadata:
  name: smoke-test
  annotations:
    argocd.argoproj.io/hook: PostSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
        - name: test
          image: curlimages/curl
          command: ["curl", "-f", "http://health-ack:8080/health"]
      restartPolicy: Never

多集群管理

Declarative Cluster Config

向 ArgoCD 注册外部集群:

# 获取目标集群的 kubeconfig context
argocd cluster add <target-context> --name=prod-shanghai

或通过 Secret 声明:

apiVersion: v1
kind: Secret
metadata:
  name: cluster-prod-shanghai
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster
type: Opaque
stringData:
  name: prod-shanghai
  server: https://10.0.2.1:6443
  config: |
    {
      "bearerToken": "<service-account-token>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<base64-ca-cert>"
      }
    }

Application 只需指定 destination.server,即可部署到对应集群。

Cluster Generator

自动为所有已注册集群生成 Application:

spec:
  generators:
    - clusters:
        selector:
          matchLabels:
            env: prod              # 只匹配打了 env=prod 标签的集群
  template:
    spec:
      destination:
        server: '{{server}}'       # 目标集群 API 地址
        namespace: health

多集群同步策略

策略配置行为
并行默认所有集群同时同步
蓝绿手动分两批 sync首批成功后再同步第二批
金丝雀ApplicationSet + maxUpdate每次同步 N 个集群,逐步推进
进度式rollingSync + maxUpdateApplicationSet 按步骤逐步更新

通知与告警

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  annotations:
    notifications.argoproj.io/subscribe.on-sync-succeeded.slack: '#argocd'
    notifications.argoproj.io/subscribe.on-sync-failed.slack: '#argocd-alert'
    notifications.argoproj.io/subscribe.on-deployed.slack: '#releases'
    notifications.argoproj.io/subscribe.on-health-degraded.slack: '#oncall'

触发器类型:on-sync-succeeded / on-sync-failed / on-sync-running / on-deployed / on-health-degraded

日常运维

CLI 速查

# 登录
argocd login argocd.example.com --sso

# 查看所有 Application
argocd app list

# 查看 Application 详情(含 diff)
argocd app get health-ack

# 手动同步
argocd app sync health-ack
argocd app sync health-ack --resource apps:Deployment:health-ack  # 只同步特定资源

# 回滚到上一个版本
argocd app rollback health-ack

# 查看历史
argocd app history health-ack

# 查看 diff(不操作)
argocd app diff health-ack

# 刷新(重新拉 Git)
argocd app get health-ack --refresh

常见故障处理

症状原因处理
OutOfSync 但 Git 没问题selfHeal=false 时手动变更不会被回滚手动 sync 或开启 selfHeal
Sync 卡住资源正在等待条件(如 PVC 绑定、Pod 调度)argocd app get <app> 查看卡在哪一步,解决 K8s 层面的问题
删除 Application 后资源还在prune=false 时只删 ArgoCD 元数据不删 K8s 资源删除时加 --cascade,或开启 prune
Helm Chart 渲染失败values.yaml 语法错误或依赖缺失helm dependency update 或检查 values 文件
repo 连接失败Git 仓库认证过期更新 repo 凭据 Secret

灾难恢复

ArgoCD 默认无状态(所有配置存 K8s),恢复只需重新部署 ArgoCD 并 kubectl apply 备份的 Application 清单:

# 备份所有 Application(定期执行)
argocd app list -o yaml > argocd-apps-backup-$(date +%Y%m%d).yaml

# 恢复
kubectl apply -f argocd-apps-backup-20260701.yaml

安全最佳实践

  1. 最小权限 AppProject:限制 sourceRepos、destinations、clusterResourceWhitelist
  2. Secret 管理:不要 put Secret YAML 到 Git。使用 External Secrets Operator 或 Sealed Secrets,ArgoCD 只引用 Secret 名称
  3. OCI Helm Chart:使用 ref: oci://registry.example.com/charts/myapp 替代 Git 中的 Chart,版本锁定
  4. SSO:集成 Dex + OIDC(Okta/Keycloak/AD),禁用本地账户
  5. Network Policy:限制 ArgoCD 组件只与目标集群 API Server 通信

关联知识

参考资源

学习时间

阶段时间备注
架构与实战2026-07-01完成:核心 CRD、同步机制、多集群、App of Apps、故障处理

状态: 🌱 学习中 下次复习日期: 2026-07-08