技术博客

ArgoCD App of Apps 模式:多集群 GitOps 统一管理实战

详解 ArgoCD App of Apps 设计模式的原理和落地方案,包括如何用一个根 Application 管理所有子 Application、多集群注册与部署、ApplicationSet 大规模集群扩展、以及 ArgoCD Projects 的 RBAC 权限隔离。

ArgoCDGitOps多集群App of AppsKubernetesDevOps

当企业 Kubernetes 规模增长到多个集群(不同区域、不同业务线、不同环境),ArgoCD 的多集群管理能力就至关重要。App of Apps 模式是 ArgoCD 处理大规模应用的标准架构:用 Git 管理所有 Application 对象本身,让 ArgoCD 既管理应用,也管理 ArgoCD 自身的配置。

App of Apps 核心思想

普通模式(Application → 应用资源):

ArgoCD Application "myapp-prod"
    ↓ sync
Kubernetes Deployment/Service/...


App of Apps 模式(Application → Application → 应用资源):

ArgoCD Application "root-apps"(根 Application)
    ↓ sync(从 Git 读取 Application YAML)
ArgoCD Application "infra-apps"     ArgoCD Application "team-a-apps"
    ↓ sync                               ↓ sync
Prometheus/Grafana/...              myapp-prod/api-prod/...

好处:

仓库结构

cluster-configs/                      ← 主仓库
├── clusters/
│   ├── cluster-cn-shanghai/          ← 上海生产集群
│   │   ├── root-app.yaml             ← 根 Application(手动 apply 一次)
│   │   └── apps/                     ← 子 Application 定义
│   │       ├── infra.yaml
│   │       ├── monitoring.yaml
│   │       └── team-a.yaml
│   ├── cluster-cn-beijing/           ← 北京生产集群
│   │   ├── root-app.yaml
│   │   └── apps/
│   │       └── ...
│   └── cluster-dev/                  ← 开发集群
│       ├── root-app.yaml
│       └── apps/
│           └── ...
├── apps/                             ← 各子 Application 的具体资源
│   ├── infra/
│   │   ├── cert-manager/
│   │   ├── ingress-nginx/
│   │   └── cilium/
│   ├── monitoring/
│   │   ├── prometheus/
│   │   └── grafana/
│   └── team-a/
│       ├── myapp/
│       └── api-gateway/
└── argocd-projects/                  ← ArgoCD Projects(RBAC 隔离)
    ├── infra-project.yaml
    └── team-a-project.yaml

注册多集群

在 ArgoCD 中注册目标集群:

# 在目标集群上,ArgoCD 需要有权限部署资源
# 方法1:使用 argocd CLI 注册(推荐)

# 1. 先登录 ArgoCD
argocd login argocd.company.com --username admin

# 2. 切换 kubectl context 到目标集群
kubectl config use-context k8s-cn-shanghai

# 3. 注册集群(ArgoCD 会在目标集群创建 ServiceAccount 和 RBAC)
argocd cluster add k8s-cn-shanghai \
  --name cluster-cn-shanghai \
  --in-cluster-namespace argocd   # 在目标集群的 argocd 命名空间创建 SA

# 4. 重复添加其他集群
kubectl config use-context k8s-cn-beijing
argocd cluster add k8s-cn-beijing --name cluster-cn-beijing

# 查看已注册集群
argocd cluster list
# SERVER                              NAME                STATUS
# https://k8s-cn-shanghai.internal    cluster-cn-shanghai  Successful
# https://k8s-cn-beijing.internal     cluster-cn-beijing   Successful
# https://kubernetes.default.svc      in-cluster           Successful
# 方法2:Secret 方式(适合自动化)
# argocd 命名空间下创建包含 kubeconfig 的 Secret

apiVersion: v1
kind: Secret
metadata:
  name: cluster-cn-shanghai
  namespace: argocd
  labels:
    argocd.argoproj.io/secret-type: cluster   # 关键标签,ArgoCD 识别为集群配置
type: Opaque
stringData:
  name: cluster-cn-shanghai
  server: https://k8s-cn-shanghai.internal:6443
  config: |
    {
      "bearerToken": "<SERVICE_ACCOUNT_TOKEN>",
      "tlsClientConfig": {
        "insecure": false,
        "caData": "<BASE64_CA_CERT>"
      }
    }

根 Application 配置

# clusters/cluster-cn-shanghai/root-app.yaml
# 这是需要手动 apply 一次的根 Application
# 之后所有 Application 的增删改都通过 Git 管理

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-apps-cn-shanghai
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: default
  source:
    repoURL: https://github.com/your-org/cluster-configs
    targetRevision: HEAD
    path: clusters/cluster-cn-shanghai/apps   # 指向子 Application 目录
  destination:
    server: https://kubernetes.default.svc    # ArgoCD 所在集群(管理面)
    namespace: argocd                          # 子 Application 创建在 argocd 命名空间
  syncPolicy:
    automated:
      prune: true      # 删除 Git 中不存在的 Application
      selfHeal: true
# 只需执行一次的启动命令
kubectl apply -f clusters/cluster-cn-shanghai/root-app.yaml

# 之后 ArgoCD 自动读取 apps/ 目录下的所有 Application YAML 并创建

子 Application 配置

# clusters/cluster-cn-shanghai/apps/infra.yaml
# 基础设施层 Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: infra-cn-shanghai
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io
spec:
  project: infra-project   # 只有 infra 团队有权限
  source:
    repoURL: https://github.com/your-org/cluster-configs
    targetRevision: HEAD
    path: apps/infra        # 基础设施资源目录
    # 如果用 Helm,加:
    # helm:
    #   valueFiles:
    #   - ../../envs/cn-shanghai/infra-values.yaml
  destination:
    server: https://k8s-cn-shanghai.internal:6443   # 部署到上海集群
    namespace: kube-system
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

---
# clusters/cluster-cn-shanghai/apps/monitoring.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: monitoring-cn-shanghai
  namespace: argocd
spec:
  project: infra-project
  source:
    repoURL: https://github.com/your-org/cluster-configs
    targetRevision: HEAD
    path: apps/monitoring
  destination:
    server: https://k8s-cn-shanghai.internal:6443
    namespace: monitoring
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
    - CreateNamespace=true

---
# clusters/cluster-cn-shanghai/apps/team-a.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: team-a-cn-shanghai
  namespace: argocd
spec:
  project: team-a-project   # team-a 只能管理自己的 Application
  source:
    repoURL: https://github.com/your-org/cluster-configs
    targetRevision: HEAD
    path: apps/team-a
  destination:
    server: https://k8s-cn-shanghai.internal:6443
    namespace: team-a-production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

RBAC 隔离:ArgoCD Projects

ArgoCD Project(AppProject)是 RBAC 隔离的核心机制,可以限制:哪些团队能管理哪些 Application、能部署到哪些集群/命名空间、能使用哪些 Git 仓库。

# argocd-projects/team-a-project.yaml
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-a-project
  namespace: argocd
spec:
  description: "Team A 的应用项目,只能部署到 team-a-* 命名空间"

  # 允许的源仓库(只能使用授权仓库)
  sourceRepos:
  - https://github.com/your-org/cluster-configs
  - https://github.com/your-org/team-a-configs

  # 允许部署的目标(集群 + 命名空间)
  destinations:
  - server: https://k8s-cn-shanghai.internal:6443
    namespace: team-a-*   # 通配符:只允许 team-a- 前缀的命名空间
  - server: https://k8s-dev.internal:6443
    namespace: "*"         # dev 集群无限制

  # 允许部署的 Kubernetes 资源类型(防止 team-a 创建 ClusterRole 等)
  clusterResourceWhitelist:
  - group: ""
    kind: Namespace
  namespaceResourceBlacklist:
  - group: ""
    kind: ResourceQuota   # 不允许修改 ResourceQuota

  # 孤儿资源检测(检测不在 ArgoCD 管理下的资源)
  orphanedResources:
    warn: true

  # RBAC 角色
  roles:
  - name: developer
    description: "Team A 开发人员:只读 + 手动同步"
    policies:
    - p, proj:team-a-project:developer, applications, get, team-a-project/*, allow
    - p, proj:team-a-project:developer, applications, sync, team-a-project/*, allow
    groups:
    - team-a-developers   # SSO 组
  - name: lead
    description: "Team A 负责人:完整权限"
    policies:
    - p, proj:team-a-project:lead, applications, *, team-a-project/*, allow
    groups:
    - team-a-leads
# argocd/argocd-cm-patch.yaml
# 配置 ArgoCD 的 RBAC(全局 + 项目级别)

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.default: role:readonly   # 默认所有人只读
  policy.csv: |
    # 超级管理员
    p, role:admin, *, *, *, allow

    # 基础设施团队
    p, role:infra-admin, applications, *, infra-project/*, allow
    p, role:infra-admin, clusters, *, *, allow

    # 将 SSO 组映射到角色
    g, infra-team, role:infra-admin
    g, admin-group, role:admin

ApplicationSet 大规模扩展

当需要将同一套应用部署到 10+ 个集群时,ApplicationSet 的 Cluster 生成器最合适:

# applicationset-all-clusters.yaml
# 自动为每个已注册集群生成 Application

apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: monitoring-all-clusters
  namespace: argocd
spec:
  generators:
  # Cluster 生成器:为每个已注册集群生成变量
  - clusters:
      selector:
        matchLabels:
          environment: production   # 只对生产集群
  template:
    metadata:
      name: "monitoring-{{name}}"   # {{name}} = 集群名
    spec:
      project: infra-project
      source:
        repoURL: https://github.com/your-org/cluster-configs
        targetRevision: HEAD
        path: apps/monitoring
        helm:
          parameters:
          - name: cluster.name
            value: "{{name}}"      # 传入集群名
          - name: cluster.server
            value: "{{server}}"    # 传入集群地址
      destination:
        server: "{{server}}"       # 部署到对应集群
        namespace: monitoring
      syncPolicy:
        automated:
          prune: true
          selfHeal: true
        syncOptions:
        - CreateNamespace=true
# 为集群添加标签
kubectl label secret cluster-cn-shanghai -n argocd \
  argocd.argoproj.io/secret-type=cluster \
  environment=production

# ApplicationSet 自动为所有带 environment=production 标签的集群创建 monitoring Application
kubectl get application -n argocd | grep monitoring
# monitoring-cluster-cn-shanghai   Synced  Healthy
# monitoring-cluster-cn-beijing    Synced  Healthy
# monitoring-cluster-cn-shenzhen   Synced  Healthy

新集群加入流程(标准化)

有了 App of Apps 模式,新集群加入流程极度简化:

# 1. 注册新集群
argocd cluster add k8s-cn-shenzhen \
  --name cluster-cn-shenzhen

# 2. 在 Git 仓库创建集群配置目录
mkdir -p clusters/cluster-cn-shenzhen/apps
cp clusters/cluster-cn-shanghai/root-app.yaml \
   clusters/cluster-cn-shenzhen/root-app.yaml
# 修改 root-app.yaml 中的 path 和集群地址

# 3. 复制或定制子 Application 配置
cp clusters/cluster-cn-shanghai/apps/* \
   clusters/cluster-cn-shenzhen/apps/
# 修改 destination.server 为新集群地址

# 4. 提交 PR,合并后 apply 根 Application
git add clusters/cluster-cn-shenzhen/
git commit -m "feat: add cn-shenzhen cluster"
git push && gh pr create --fill

# PR 合并后,执行一次性命令
kubectl apply -f clusters/cluster-cn-shenzhen/root-app.yaml
# ArgoCD 自动创建所有子 Application,全套基础设施自动部署完成

常用运维命令

# 查看所有集群的 Application 状态
argocd app list --all-namespaces

# 过滤特定集群的 Application
argocd app list \
  --dest-server https://k8s-cn-shanghai.internal:6443

# 批量同步某集群所有 Application
argocd app list \
  --dest-server https://k8s-cn-shanghai.internal:6443 \
  -o name | xargs -I{} argocd app sync {}

# 查看集群健康状态
argocd cluster stats

# ApplicationSet 调试(查看生成的 Application 预览)
kubectl get applicationset -n argocd monitoring-all-clusters -o yaml

小结

App of Apps 模式的本质是用 Git 管理 GitOps 本身:不仅应用资源在 Git 里,ArgoCD Application 对象本身也在 Git 里。一旦建立这套结构,新集群加入只需 apply 一个根 Application,所有基础设施、监控、业务应用全自动部署完成,实现真正的“集群即代码”。结合 ApplicationSet 的 Cluster 生成器,20 个集群的统一管理与 1 个集群无本质差别。