Chapter 10

CI/CD 完整流水线

将前九章内容融会贯通,构建从代码提交到生产部署的完整 GitOps 流水线。掌握仓库分离最佳实践、GitHub Actions CI 自动化、Argo Rollouts 渐进式交付,以及企业级落地关键经验。

GitOps 仓库分离最佳实践

成熟的 GitOps 实践要求将应用代码仓库配置仓库(Config Repo)分离。将两者混在一起会导致 CI/CD 耦合、权限难以控制、历史记录混乱等问题。

双仓库 GitOps 架构

┌──────────────────────────────────────────────────────────────────────────┐
                     应用代码仓库 (my-org/my-app)                          
  src/          tests/         Dockerfile         .github/workflows/      
  应用源代码      单元测试        构建镜像             CI Pipeline             
└──────────────────────────────────┬───────────────────────────────────────┘
                                    │ CI: 构建镜像,推送 GHCR
                                    │ CI: 更新配置仓库的 image tag
┌──────────────────────────────────▼───────────────────────────────────────┐
                    配置仓库 (my-org/my-app-config)                        
  apps/                                                                    
  └── my-app/                                                              
      ├── base/                   (通用 K8s 资源)                          
      └── overlays/               (环境差异化配置)                         
          ├── dev/ → image:v1.6   (dev 环境最新)                           
          ├── staging/ → image:v1.5 (staging 稳定版)                       
          └── prod/ → image:v1.4  (prod 慢更新)                            
└──────────────────────────────────┬───────────────────────────────────────┘
                                    │ ArgoCD Poll(每3分钟)
┌──────────────────────────────────▼───────────────────────────────────────┐
                  K8s 集群(ArgoCD 自动同步)                              
└──────────────────────────────────────────────────────────────────────────┘

应用代码仓库职责

  • 存放应用源代码
  • CI Pipeline(构建/测试/扫描)
  • Dockerfile
  • 单元测试/集成测试
  • 包含 K8s YAML

配置仓库职责

  • 所有环境的 K8s YAML
  • Kustomize overlays / Helm values
  • ArgoCD Application CRD
  • 更严格的访问控制(prod 需审批)
  • 包含应用源代码

GitHub Actions CI 完整流程

以下是一个生产级的 GitHub Actions CI 工作流,完成从代码提交到更新配置仓库的全流程:

# .github/workflows/ci.yaml(应用代码仓库)
name: CI Pipeline
on:
  push:
    branches: [main]
  pull_request:
    branches: [main]

env:
  REGISTRY: ghcr.io
  IMAGE_NAME: ${{ github.repository }}

jobs:
  test:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4
    - name: Run Tests
      run: make test

  build-push:
    needs: test
    runs-on: ubuntu-latest
    if: github.ref == 'refs/heads/main'   # 只有 main 分支才构建推送
    permissions:
      contents: read
      packages: write
    outputs:
      image_tag: ${{ steps.meta.outputs.version }}
    steps:
    - uses: actions/checkout@v4

    - name: Set up Docker Buildx
      uses: docker/setup-buildx-action@v3

    - name: Login to GHCR
      uses: docker/login-action@v3
      with:
        registry: ${{ env.REGISTRY }}
        username: ${{ github.actor }}
        password: ${{ secrets.GITHUB_TOKEN }}

    - name: Extract metadata
      id: meta
      uses: docker/metadata-action@v5
      with:
        images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
        tags: |
          type=sha,prefix=,format=short
          type=raw,value=latest

    - name: Build and push
      uses: docker/build-push-action@v5
      with:
        context: .
        push: true
        tags: ${{ steps.meta.outputs.tags }}
        labels: ${{ steps.meta.outputs.labels }}
        cache-from: type=gha
        cache-to: type=gha,mode=max

  update-config:
    needs: build-push
    runs-on: ubuntu-latest
    steps:
    - name: Checkout config repo
      uses: actions/checkout@v4
      with:
        repository: my-org/my-app-config
        token: ${{ secrets.CONFIG_REPO_PAT }}   # PAT 需要配置仓库写权限

    - name: Install kustomize
      uses: imranismail/setup-kustomize@v2

    - name: Update image tag in dev overlay
      run: |
        cd apps/my-app/overlays/dev
        kustomize edit set image \
          ghcr.io/my-org/my-app=ghcr.io/my-org/my-app:${{ needs.build-push.outputs.image_tag }}
        git config user.name "github-actions[bot]"
        git config user.email "github-actions[bot]@users.noreply.github.com"
        git add .
        git commit -m "chore: update my-app to ${{ needs.build-push.outputs.image_tag }}"
        git push

Argo Rollouts:渐进式交付

Argo Rollouts 是 Argo 生态的渐进式交付控制器,提供比原生 Kubernetes Deployment 更强大的发布策略,与 ArgoCD 深度集成。

金丝雀发布 (Canary)
逐步将流量切换到新版本:先 5% 流量 → 分析指标 → 25% → 50% → 100%。任意阶段发现问题可自动回滚,将影响范围降到最低。
蓝绿发布 (Blue-Green)
同时运行新旧两个版本(Blue=旧,Green=新),测试通过后瞬间切换流量,回滚只需切回旧版本,停机时间接近于零。
Analysis Run
自动化的指标分析任务,在每个金丝雀阶段检查 Prometheus 指标(如错误率、P99 延迟),如果指标超过阈值则自动中止并回滚。
# Argo Rollouts 金丝雀发布示例
apiVersion: argoproj.io/v1alpha1
kind: Rollout
metadata:
  name: my-app
spec:
  replicas: 10
  strategy:
    canary:
      steps:
      - setWeight: 5            # 5% 流量切到新版本
      - pause:
          duration: 5m         # 等待 5 分钟观察
      - analysis:              # 自动指标分析
          templates:
          - templateName: error-rate
      - setWeight: 25
      - pause:
          duration: 10m
      - setWeight: 50
      - pause:
          duration: 10m
      - setWeight: 100         # 全量切换
  selector:
    matchLabels:
      app: my-app
  template:
    spec:
      containers:
      - name: my-app
        image: ghcr.io/my-org/my-app:v2.0.0

Argo Workflows vs ArgoCD

对比维度 Argo Workflows ArgoCD
核心职责 流水线执行引擎(CI、批处理) 持续交付(CD)、GitOps
触发方式 主动触发(事件/定时) 监听 Git 变更(Pull 模式)
执行模型 DAG 工作流,步骤间有数据流 声明式同步,无步骤概念
状态管理 有执行历史和 Artifact 管理 K8s 资源持续状态
适用场景 构建镜像、运行测试、ML 训练 部署应用、管理配置
组合使用 Argo Workflows(CI)→ 更新配置仓库 → ArgoCD(CD)→ 集群

企业级落地经验

从小规模开始,逐步推广

不要一次性将所有应用迁移到 ArgoCD。选择 1-2 个非核心服务作为试点,跑通 GitOps 流程后再逐步推广。让团队有足够时间适应"不再直接 kubectl"的工作方式。

配置仓库需要更严格的审批流程

生产环境的配置仓库需要强制 Code Review(至少 2 人审批),并通过 Branch Protection 防止直接 push main。建议为 dev/staging/prod 三个环境设置不同的 PR 审批要求。

ArgoCD 本身也要 GitOps 管理

ArgoCD 的 Application、AppProject、RBAC 配置等,都应该存储在 Git 中,通过"App of Apps"或 ApplicationSet 管理。避免直接在 UI 上创建资源,否则 ArgoCD 本身就不符合 GitOps 原则。

合理设置同步间隔和 Webhook

默认的 3 分钟轮询对大多数场景够用。对延迟敏感的场景,配置 Git Webhook,ArgoCD 收到 push 事件后立即触发同步,延迟降到秒级。注意 Webhook 需要 ArgoCD API Server 对外可达。

selfHeal 和 prune 需要充分测试

在生产环境开启 selfHeal 前,必须在 staging 环境充分验证。selfHeal 会覆盖运维人员在紧急情况下的手动操作,需要确保 Git 配置始终是正确的"参考状态"。prune 开启前要确认所有应用资源都在 Git 中有记录。

建立清晰的镜像 tag 策略

生产环境禁止使用 latest tag,必须使用 Semver(v1.2.3)或 Commit SHA(sha-abc123f)。这确保每次部署的版本完全确定可重现,是 GitOps 可审计性的基础。

完整架构总结

企业级 GitOps 完整架构

┌────────────────────────────────────────────────────────────────────────┐
                         开发人员推送代码                                 
└──────────────────────────────────┬─────────────────────────────────────┘
                                    
┌──────────────────────────────────▼─────────────────────────────────────┐
                     GitHub Actions CI                                  
  ① 运行单元测试 → ② 构建 Docker 镜像 → ③ 推送到 GHCR → ④ 更新配置仓库   
└──────────────────────────────────┬─────────────────────────────────────┘
                                    ↓ PR 自动合并 or 人工审批
┌──────────────────────────────────▼─────────────────────────────────────┐
                     配置仓库 (my-app-config)                           
  Kustomize overlays  |  Helm values  |  Application CRDs               
└──────────────────────────────────┬─────────────────────────────────────┘
                                    ↓ ArgoCD Poll / Webhook
┌──────────────────────────────────▼─────────────────────────────────────┐
                     ArgoCD (Hub 集群)                                  
  Application CRD  |  AppProject RBAC  |  Notifications  |  Prometheus   
└──────┬──────────────────────┬──────────────────────┬────────────────────┘
       ↓ auto-sync           ↓ auto-sync            ↓ auto-sync
┌──────▼──────────┐  ┌───────▼─────────┐  ┌──────▼──────────────┐
   Dev 集群          Staging 集群      Prod 集群           
 Argo Rollouts      Argo Rollouts     Argo Rollouts Canary 
└─────────────────┘  └─────────────────┘  └─────────────────────┘
课程总结

恭喜完成整个 ArgoCD 与 GitOps 实战教程!核心要点:GitOps 以 Git 为事实来源,通过声明式配置和持续协调实现可审计的自动化交付。ArgoCD 是 GitOps 的最佳实践工具,配合 Helm/Kustomize 的多环境管理、ApplicationSet 的批量操作、RBAC 的安全控制,以及 Argo Rollouts 的渐进式发布,构成了一套完整的企业级 GitOps 技术栈。将 CI(构建)与 CD(部署)在仓库层面解耦,是 GitOps 落地的关键架构决策。