ArgoCD 架构深度解析

凌晨三点,某团队的发布负责人被手机震醒:生产环境的 Deployment 更新失败了。不是因为代码有问题,而是因为 Kubernetes 集群临时不可用,导致 CI/CD 流水线超时。整个发布窗口被延误了两个小时。

这是一个典型的「命令式发布」困境:发布过程依赖外部系统的可用性。

GitOps 给出了一种不同的思路:不再由 CI/CD 流水线「推送」配置到集群,而是让集群「拉取」配置到集群。 ArgoCD 就是这种理念的践行者。

GitOps 理念回顾

在深入 ArgoCD 之前,先回顾 GitOps 的核心理念:

flowchart LR
    subgraph Git["Git 仓库(声明式配置)"]
        G1["App 配置"]
        G2["环境配置"]
        G3["Helm Charts"]
    end

    subgraph ArgoCD["ArgoCD(GitOps 控制器)"]
        AC["ArgoCD Server"]
        AC1["Sync Controller"]
        AC2["Application Controller"]
    end

    subgraph K8s["Kubernetes 集群"]
        K1["Pod"]
        K2["Service"]
        K3["Deployment"]
    end

    Git -->|"持续监控"| ArgoCD
    ArgoCD -->|"对比状态"| K8s
    K8s -->|"实际状态"| ArgoCD
    ArgoCD -->|"Sync 时同步"| K8s

GitOps 的核心原则

  1. 声明式优于命令式:所有配置以代码形式声明
  2. Git 是唯一真相源:环境状态由 Git 决定
  3. 自动化同步:集群状态自动向 Git 声明的状态收敛

ArgoCD 架构

核心组件

组件作用关键技术
API Server提供 API 和 UIgRPC/REST
Application Controller核心协调器Kubernetes Controller
Repository Server访问 Git 仓库Git/Direct
DexGitHub/GitLab 认证OAuth2/OIDC
flowchart TB
    subgraph ArgoCD["ArgoCD 控制平面"]
        UI["ArgoCD UI\n(Web)"]
        API["API Server\n(gRPC/REST)"]
        DEX["Dex\n(OAuth2)"]
        RC["Repository Server"]
        AC["Application\nController"]
    end

    subgraph External["外部资源"]
        Git["Git 仓库"]
        Helm["Helm Repo"]
        K8s["Target Clusters"]
    end

    UI --> API
    DEX --> API
    API --> RC
    RC --> Git
    RC --> Helm
    AC --> API
    AC --> K8s

Application 资源

Application 是 ArgoCD 的核心概念,定义了一个应用如何部署:

基础
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend-app
  namespace: argocd
spec:
  # 源:Git 仓库
  source:
    repoURL: https://github.com/example/app.git
    targetRevision: main
    path: deploy/overlays/production
    # Helm 参数
    helm:
      valueFiles:
        - values-prod.yaml
      parameters:
        - name: image.tag
          value: v2.0.0

  # 目标:Kubernetes 集群
  destination:
    server: https://kubernetes.default.svc
    namespace: production

  # 同步策略
  syncPolicy:
    automated:
      prune: true          # 自动删除不在 Git 中的资源
      selfHeal: true       # 自动恢复被手动修改的资源

多集群支持

多集群
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: backend-app
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/example/backend.git
    path: k8s
    helm:
      values: |
        replicaCount: 3
        image:
          repository: registry.example.com/backend
          tag: latest

  # 部署到多个集群
  destination:
    server: https://eks.us-west-2.amazonaws.com
    namespace: backend

ApplicationSet:批量管理

ApplicationSet 解决了管理大量 Application 的问题:

ApplicationSet
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: backend-clusters
  namespace: argocd
spec:
  generators:
    # 从集群列表生成
    - clusters:
        selector:
          matchLabels:
            environment: production

  # 每次生成的应用模板
  template:
    metadata:
      name: 'backend-{{name}}'
    spec:
      source:
        repoURL: https://github.com/example/backend.git
        path: deploy/{{name}}
        targetRevision: main
      destination:
        server: '{{server}}'
        namespace: backend
      syncPolicy:
        automated:
          prune: true
          selfHeal: true

生成器类型

生成器用途
List静态列表
Clusters从 ArgoCD 管理的集群
Git从 Git 目录/文件
Matrix组合多个生成器
Merge合并多个生成器
Matrix
apiVersion: argoproj.io/v1alpha1
kind: ApplicationSet
metadata:
  name: microservices
  namespace: argocd
spec:
  generators:
    - matrix:
        generators:
          # 服务列表
          - git:
              repoURL: https://github.com/example/config.git
              directories:
                - path: services/*
          # 集群列表
          - clusters:
              selector:
                matchLabels:
                  env: prod

  template:
    metadata:
      name: '{{path.basename}}-{{name}}'
    spec:
      source:
        repoURL: https://github.com/example/config.git
        path: '{{path}}/k8s'
      destination:
        server: '{{server}}'
        namespace: '{{path.basename}}'

Sync 策略与健康检查

Sync 阶段

Sync
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: critical-app
spec:
  syncPolicy:
    # 自动同步
    automated:
      prune: true
      selfHeal: true
      allowEmpty: false

    # 同步选项
    syncOptions:
      - CreateNamespace=true
      - PrunePropagationPolicy=foreground
      - PruneLast=true

    # 重试配置
    retry:
      limit: 5
      backoff:
        duration: 5s
        factor: 2
        maxDuration: 3m

健康检查

自定义健康检查.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: redis-app
spec:
  # 自定义健康检查脚本
  ignoreDifferences:
    - group: apps
      kind: Deployment
      jsonPointers:
        - /spec/replicas

  # 或者通过 ConfigMap 定义健康检查
  # ...
健康检查
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  resource.customizations: |
    apps/Deployment:
      health.lua: |
        local hs = {}
        hs.status = "Progressing"
        hs.message = ""
        if obj.status ~= nil then
          if obj.status.observedGeneration ~= nil
             and obj.metadata.generation == obj.status.observedGeneration then
            if obj.status.condition ~= nil then
              for i, condition in ipairs(obj.status.condition) do
                if condition.type == "Available" and condition.status == "True" then
                  hs.status = "Healthy"
                  hs.message = condition.message
                  return hs
                end
              end
            end
          end
        end
        return hs

Argo Rollouts:高级部署

Rollout 资源

Argo
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: backend-rollout
spec:
  replicas: 3
  strategy:
    canary:
      steps:
        - setWeight: 5
        - pause: {}           # 等待手动或自动继续
        - setWeight: 20
        - pause: {duration: 10}
        - setWeight: 50
        - pause: {duration: 10}
        - setWeight: 100

      # 金丝雀服务
      canaryService: backend-canary
      stableService: backend-stable

      # 流量管理
      trafficRouting:
        istio:
          virtualService:
            name: backend-vs
          routes:
            - primary

      # 分析
      analysis:
        templates:
          - templateName: success-rate
        startingStep: 1
        args:
          - name: service-name
            value: backend-canary

  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: backend
          image: backend:v2

分析模板

分析模板.yaml
apiVersion: argoproj.io/v1alpha1
kind: AnalysisTemplate
metadata:
  name: success-rate
spec:
  args:
    - name: service-name

  metrics:
    - name: success-rate
      interval: 1m
      successCondition: result[0] >= 0.95
      failureLimit: 3
      provider:
        prometheus:
          address: http://prometheus:9090
          query: |
            sum(rate(istio_requests_total{
              destination="{{args.service-name}}",
              response_code!="500"
            }[5m]))
            /
            sum(rate(istio_requests_total{
              destination="{{args.service-name}}"
            }[5m]))

RBAC 与安全

RBAC 配置

RBAC
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-rbac-cm
  namespace: argocd
data:
  policy.csv: |
    # 角色定义
    p, role:developer, applications, *, */*, allow
    p, role:developer, clusters, get, *, allow
    p, role:developer, repositories, get, *, allow

    # 团队管理员
    p, role:team-admin, applications, *, */production, allow
    g, team-admins, role:team-admin

    # 拒绝规则
    p, role:developer, applications, delete, */*, deny

权衡矩阵

维度ArgoCD传统 CI/CD (Jenkins/GitLab CI)
部署方式拉取(Pull)推送(Push)
配置位置GitCI/CD 系统
故障恢复自动需手动
权限模型声明式 RBAC命令式权限
多集群支持原生需要额外配置
与 K8s 集成原生需要 agent

常见问题与反模式

问题一:Sync 循环

错误:Application 不断处于 Syncing 状态。

正确做法:检查是否有资源配置冲突,或者 selfHeal 与手动修改冲突。

问题二:Repository 认证失效

错误:Git 仓库访问失败。

正确做法:确保 Secret 中的凭证是最新的,使用 Git Deploy Key 而非用户账号。

问题三:多集群权限混乱

错误:不同集群使用相同的 ServiceAccount。

正确做法:为每个集群创建独立的 Secret 和 Application。

延伸思考

ArgoCD 的本质是将部署的确定性交给 Git。当 Git 中的配置是正确的,集群状态就会是正确的。这种范式特别适合:

  • 多集群管理:一个 ArgoCD 可以管理多个集群的部署
  • 不可变基础设施:所有变更都必须通过 Git
  • 合规要求:审计日志就是 Git 提交记录

但 ArgoCD 不是万能的。对于需要复杂逻辑的构建流程(如多阶段编译、二进制打包),仍然需要 CI 系统配合。 ArgoCD 和 CI 系统各司其职:CI 负责构建,ArgoCD 负责部署。