GitOps 核心原则

GitOps 是一种现代化的持续交付方法论,由 Weaveworks 在 2017 年提出。它将 Git 作为基础设施和应用配置的唯一可信源(Single Source of Truth),通过声明式方式实现持续部署。

根据 ArgoCD 官方文档,GitOps 遵循四大核心原则:

1. 声明式系统

基础设施和应用配置以声明式描述(YAML/Helm/Kustomize)存储在 Git 中:

# Git 仓库结构示例
infra-repo/
├── apps/
│   ├── frontend/
│   │   ├── deployment.yaml
│   │   ├── service.yaml
│   │   └── configmap.yaml
│   └── backend/
│       ├── deployment.yaml
│       └── service.yaml
├── helm/
│   └── values-production.yaml
└── kustomize/
    ├── base/
    └── overlays/
        ├── staging/
        └── production/

声明式描述的核心价值:配置即文档,Git 历史即审计日志。任何环境变更都可追溯、可回滚。

2. 版本控制

所有变更通过 Git 提交记录,天然具备:

  • 变更审计:谁在何时修改了什么,为什么修改
  • 版本回滚git revert 即可回滚到任意历史版本
  • 变更评审:通过 Pull Request 实现配置变更的 Code Review

3. 自动同步

代码合并到目标分支后,自动触发部署到目标环境,无需人工执行部署命令

开发者提交 PR → Code Review → 合并到 main → ArgoCD 检测变更 → 自动同步到集群

4. 持续协调

控制平面持续监控集群实际状态与 Git 期望状态的差异,发现漂移自动纠正:

Git (期望状态)  ←→  ArgoCD (协调器)  ←→  Cluster (实际状态)
                      持续对比 ↑↓
                  发现差异 → 自动同步

这与传统 CI/CD 的根本区别在于:传统 CI/CD 是 Push 模型(CI 推送到集群),GitOps 是 Pull 模型(集群内的 Agent 拉取 Git)。Pull 模型不需要在 CI 系统中存储集群凭据,安全性更高。

ArgoCD 架构

ArgoCD 是 CNCF 毕业项目,是 GitOps 领域最成熟的工具。它以 Kubernetes Controller 形式运行在集群内,持续协调 Git 仓库与集群状态。

核心组件

┌─────────────────────────────────────────────────────────┐
│                      ArgoCD 架构                         │
│                                                         │
│  ┌─────────────┐   ┌──────────────┐   ┌──────────────┐ │
│  │  API Server  │   │  Repo Server │   │ Application  │ │
│  │  (gRPC/REST) │   │ (Git 渲染)    │   │  Controller  │ │
│  └──────┬──────┘   └──────┬───────┘   └──────┬───────┘ │
│         │                 │                   │         │
│         │         ┌───────▼────────┐          │         │
│         │         │  Git Repository │          │         │
│         │         │  (Helm/Kustomize)│         │         │
│         │         └────────────────┘          │         │
│         │                                     │         │
│  ┌──────▼─────────────────────────────────────▼──────┐ │
│  │              Redis (缓存 + 状态)                    │ │
│  └───────────────────────────────────────────────────┘ │
│                                                         │
│  ┌───────────────────────────────────────────────────┐ │
│  │              K8s API Server                         │ │
│  └───────────────────────────────────────────────────┘ │
└─────────────────────────────────────────────────────────┘
组件职责关键点
API Server暴露 gRPC/REST API,管理 Application CRD认证授权、Web UI、CLI 交互
Repo Server克隆 Git 仓库,渲染 Helm/Kustomize无状态服务,可水平扩展
Application Controller协调循环:对比 Git 与集群状态核心控制器,触发同步操作
Redis缓存 Git 仓库和渲染结果降低 Repo Server 负载
ApplicationSet Controller批量生成 Application多集群/多环境场景

安装部署

# 安装 ArgoCD
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 获取初始密码
kubectl -n argocd get secret argocd-initial-admin-secret \
  -o jsonpath="{.data.password}" | base64 -d

# 端口转发访问 UI
kubectl port-forward svc/argocd-server -n argocd 8080:443

# 安装 ArgoCD CLI
curl -sSL -o argocd https://github.com/argoproj/argo-cd/releases/latest/download/argocd-linux-amd64
chmod +x argocd && mv argocd /usr/local/bin/

# 登录
argocd login localhost:8080 --username admin --password <password>

Application CRD 配置

Application 是 ArgoCD 的核心 CRD,定义了"把哪个 Git 仓库的什么内容同步到哪个集群":

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend-prod
  namespace: argocd
  finalizers:
  - resources-finalizer.argocd.argoproj.io  # 删除 App 时级联清理资源
spec:
  project: production                        # 关联的 ArgoCD Project
  source:
    repoURL: https://github.com/xubaojin/k8s-manifests.git
    targetRevision: main                     # 跟踪的分支/tag
    path: apps/frontend/overlays/production  # Kustomize 路径
  destination:
    server: https://kubernetes.default.svc   # 目标集群
    namespace: production
  syncPolicy:
    automated:
      prune: true        # 自动删除 Git 中已移除的资源
      selfHeal: true     # 自动恢复手动修改(漂移纠正)
    syncOptions:
    - CreateNamespace=true  # 自动创建命名空间
    - PrunePropagationPolicy=foreground
    - ApplyOutOfSyncOnly=true
  revisionHistoryLimit: 10  # 保留 10 个历史版本用于回滚

同步策略详解

Auto Sync(自动同步)

syncPolicy:
  automated:
    prune: true       # Git 中删除的资源在集群中也删除
    selfHeal: true    # 有人手动 kubectl 改了集群资源,自动恢复

selfHeal 是 GitOps 的核心——它确保集群状态始终与 Git 一致。如果有人手动 kubectl edit 修改了 Deployment 的副本数,ArgoCD 会自动将其恢复为 Git 中声明的值。

Manual Sync(手动同步)

syncPolicy:
  # 不配置 automated,需要手动触发同步
  syncOptions:
  - CreateNamespace=true

适用于生产环境,变更需要人工确认后点击同步。

Helm Chart 同步

spec:
  source:
    repoURL: https://github.com/xubaojin/helm-charts.git
    targetRevision: main
    path: charts/frontend
    helm:
      valueFiles:
      - values-production.yaml
      parameters:
      - name: image.tag
        value: v1.2.3
      - name: replicaCount
        value: "3"
      skipCrds: false

Kustomize 同步

spec:
  source:
    repoURL: https://github.com/xubaojin/k8s-manifests.git
    targetRevision: main
    path: apps/frontend/overlays/production
    kustomize:
      images:
      - ghcr.io/xubaojin/frontend:v1.2.3  # 覆盖镜像版本
      commonAnnotations:
        managed-by: argocd

多环境管理:App of Apps 模式

当管理多个微服务 × 多个环境时,Application 数量爆炸式增长。App of Apps 模式通过一个父 Application 管理多个子 Application:

root-app (Application)
├── staging-apps (Application)
│   ├── frontend-staging (Application)
│   ├── backend-staging (Application)
│   └── database-staging (Application)
└── production-apps (Application)
    ├── frontend-production (Application)
    ├── backend-production (Application)
    └── database-production (Application)

根 Application

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: root-app
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/xubaojin/k8s-manifests.git
    targetRevision: main
    path: argocd/apps  # 此目录下存放子 Application 定义
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

子 Application 目录结构

argocd/
├── apps/
│   ├── staging/
│   │   ├── frontend.yaml      # Application CRD
│   │   ├── backend.yaml
│   │   └── database.yaml
│   ├── production/
│   │   ├── frontend.yaml
│   │   ├── backend.yaml
│   │   └── database.yaml
│   └── kustomization.yaml     # 聚合所有子 Application
└── projects/
    ├── staging.yaml            # ArgoCD Project
    └── production.yaml

kustomization.yaml 聚合所有子 Application:

apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- staging/
- production/

ArgoCD Project 隔离

Project 提供多租户隔离,限制 Application 可操作的集群和命名空间:

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
  namespace: argocd
spec:
  description: 生产环境项目
  sourceRepos:
  - https://github.com/xubaojin/k8s-manifests.git
  destinations:
  - server: https://kubernetes.default.svc
    namespace: production
  - server: https://kubernetes.default.svc
    namespace: production-*
  clusterResourceWhitelist:
  - group: ''
    kind: Namespace
  namespaceResourceWhitelist:
  - group: '*'
    kind: '*'
  namespaceResourceBlacklist:
  - group: ''
    kind: ResourceQuota     # 禁止修改 ResourceQuota
  roles:
  - name: developer
    policies:
    - p, proj:production:developer, applications, sync, production/*, allow
    groups:
    - github:dev-team

ArgoCD CD 工作流实战

完整的 GitOps CD 工作流从代码提交到生产部署的全链路:

开发者 Push → Git 触发 CI → 构建镜像 → 更新 Manifest 仓库 → ArgoCD 检测 → 同步集群

完整流程

┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐    ┌──────────┐
│  Git Push │───►│ CI 构建   │───►│ 推送镜像  │───►│ 更新     │───►│ ArgoCD   │
│  (应用代码)│    │ (测试/构建)│    │ (Registry)│    │ Manifest │    │ 自动同步 │
└──────────┘    └──────────┘    └──────────┘    └──────────┘    └──────────┘

CI Pipeline(GitHub Actions 示例)

# .github/workflows/ci.yml
name: CI Build and Deploy

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    permissions:
      contents: write
      packages: write

    steps:
    - name: Checkout 应用代码
      uses: actions/checkout@v4

    - name: Go 测试
      run: |
        go test ./... -v -coverprofile=coverage.out        

    - name: 构建并推送镜像
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: |
          ghcr.io/${{ github.repository }}:${{ github.sha }}
          ghcr.io/${{ github.repository }}:latest          

    - name: 更新 Manifest 仓库
      env:
        GH_TOKEN: ${{ secrets.MANIFEST_REPO_TOKEN }}
      run: |
        # 克隆 manifest 仓库
        git clone https://x-access-token:${GH_TOKEN}@github.com/xubaojin/k8s-manifests.git
        cd k8s-manifests

        # 更新镜像版本(使用 yq)
        yq -i ".spec.template.spec.containers[0].image = \"ghcr.io/${{ github.repository }}:${{ github.sha }}\"" \
          apps/frontend/overlays/production/deployment-patch.yaml

        # 提交并推送
        git config user.name "CI Bot"
        git config user.email "ci-bot@sre.wang"
        git add .
        git commit -m "chore: update frontend image to ${{ github.sha }}"
        git push origin main        

ArgoCD 检测与同步

CI 推送 manifest 更新后,ArgoCD 在默认 3 分钟内检测到变更并触发同步。可通过 argocd-cm ConfigMap 调整轮询间隔:

apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  # 设置 Git 轮询间隔(秒)
  timeout.reconciliation: "180"
  # 使用 Webhook 替代轮询(推荐)
  # 配置 Git Webhook 后可实时触发

更推荐的方式是配置 Git Webhook,变更推送后立即触发同步,无需等待轮询:

# 在 Git 仓库配置 Webhook 指向 ArgoCD
# Payload URL: https://argocd.sre.wang/api/webhook
# Content type: application/json

# ArgoCD Webhook 配置
apiVersion: v1
kind: ConfigMap
metadata:
  name: argocd-cm
  namespace: argocd
data:
  webhook.github.secret: "your-webhook-secret"

同步状态监控

# 查看所有 Application 同步状态
argocd app list

# 查看特定 Application 详情
argocd app get frontend-production

# 手动触发同步
argocd app sync frontend-production

# 查看同步历史
argocd app history frontend-production

# 回滚到历史版本
argocd app rollback frontend-production <revision-id>

漂移检测告警

当有人手动修改集群资源导致漂移时,应配置告警通知:

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: frontend-production
  namespace: argocd
  annotations:
    notifications.argoproj.io/subscribe.on-deployed.slack: ops-alerts
    notifications.argoproj.io/subscribe.on-health-degraded.slack: ops-alerts
    notifications.argoproj.io/subscribe.on-sync-failed.slack: ops-alerts
spec:
  # ... 其他配置

ArgoCD Notifications 支持 Slack、Teams、邮件等多种通知渠道,关键事件包括:

事件说明建议告警级别
on-sync-succeeded同步成功Info(可选)
on-sync-failed同步失败Critical
on-health-degraded应用健康状态降级Critical
on-deployed部署完成Info
on-createdApplication 创建Warning

总结

GitOps 不仅仅是工具选择,更是一种运维范式转变。它的核心价值在于:

  • 安全性:集群凭据不在 CI 系统中暴露,Git 权限即部署权限
  • 可审计:所有变更通过 Git 提交记录,天然合规
  • 可回滚git revert 即可回滚,无需额外的回滚工具
  • 漂移纠正:selfHeal 机制确保集群状态始终与期望一致

ArgoCD 作为 GitOps 的核心组件,通过 Application CRD 声明式管理应用生命周期,App of Apps 模式实现多环境规模化,与 CI Pipeline 无缝衔接形成完整 CD 链路。

生产环境实施建议:staging 环境使用 Auto Sync + selfHeal 快速验证,production 环境使用 Manual Sync 人工确认 + Webhook 实时通知。渐进式推进,从非核心应用开始试点,积累经验后逐步扩大覆盖范围。

参考资料与致谢

本文在撰写过程中参考了以下资料,感谢原作者的贡献:

  1. ArgoCD 官方文档 — Argo CD 项目,参考了ArgoCD 官方文档相关内容