Chapter 10

CI/CD 与 GitOps:ArgoCD 实战

掌握 GitOps 工作流与 ArgoCD 的核心概念,将 Git 仓库作为集群状态的唯一真相来源,实现自动化、可审计的持续部署。

GitOps 原则

GitOps 是一种以 Git 为核心的运维模式,由 Weaveworks 于 2017 年提出。其四大原则:

  1. 声明式(Declarative):系统的期望状态用声明式配置(YAML)描述,存储在 Git 中
  2. 版本化且不可变(Versioned and Immutable):状态存储在 Git 中,可追溯变更历史,任何修改必须通过 PR/commit
  3. 自动拉取(Pulled Automatically):软件 agent(ArgoCD)自动从 Git 拉取变更并应用到集群
  4. 持续调和(Continuously Reconciled):agent 持续对比 Git 状态与集群实际状态,发现 drift 时自动修复
GitOps vs 传统 CI/CD

传统 Push 模式
  开发者 ─► PR ─► CI Build ─► CI 直接 kubectl apply ─► K8s
                               (CI 需要集群访问凭证,危险!)

GitOps Pull 模式
  开发者 ─► PR ─► CI Build ─► 更新 Git 仓库镜像 Tag ─► Git
                                                          
  K8s 集群                   ArgoCD ─── 持续监听 ──────┘
                              
     └──────────── 自动 apply ──┘
  (ArgoCD 在集群内,无需暴露集群 API,安全!)

ArgoCD 安装

# 方式一:官方 YAML 安装
kubectl create namespace argocd
kubectl apply -n argocd \
  -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

# 方式二:Helm 安装(推荐,方便定制)
helm repo add argo https://argoproj.github.io/argo-helm
helm install argocd argo/argo-cd \
  --namespace argocd \
  --create-namespace

# 等待所有组件就绪
kubectl wait --for=condition=available deployment \
  --all -n argocd --timeout=120s

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

# 访问 Web UI
kubectl port-forward -n argocd svc/argocd-server 8080:443
# 浏览器访问 https://localhost:8080,用户名 admin

ArgoCD 核心概念

ArgoCD 架构

┌────────────────────────────────────────────────────────┐
               ArgoCD 组件                            
                                                       
  ┌──────────────┐  ┌──────────────┐  ┌────────────┐  
   argocd-server   repo-server     application  
   Web UI / API    渲染 YAML       controller   
  └──────────────┘  └──────┬───────┘  └─────┬──────┘  
└───────────────────────────┼──────────────────┼──────────┘
                             │ 拉取 YAML        │ apply/sync
         ┌───────────────────▼──┐      ┌────────▼──────────┐
             Git Repository              K8s Cluster     
           kubernetes/                 Deployments     
           apps/                       Services ...    
         └──────────────────────┘      └───────────────────┘
Application
ArgoCD 的核心资源。定义了"Git 仓库的哪个路径"同步到"哪个集群的哪个 namespace",以及同步策略(手动/自动)。
AppProject
Application 的逻辑分组,用于权限控制。可以限制 Application 能使用哪些 Git 仓库、部署到哪些集群/namespace、操作哪些资源类型。
Sync(同步)
将 Git 中的期望状态应用到 K8s 集群的操作。可以手动触发,也可以设置为自动同步(Auto-Sync)。
Drift(漂移)
集群实际状态与 Git 期望状态不一致的情况。可能由手动 kubectl apply 或集群内部变更引起。ArgoCD 可以检测并自动修复 drift(Self-Heal)。
Sync Status
Synced(一致)/ OutOfSync(不一致,Git 有新变更未应用或有 Drift)/ Unknown。
Health Status
Healthy(全部 Pod 就绪)/ Degraded(有 Pod 不健康)/ Progressing(更新中)/ Missing(资源不存在)。

Application 资源配置

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: my-app-production
  namespace: argocd           # Application 必须创建在 argocd namespace
  finalizers:
  - resources-finalizer.argocd.argoproj.io  # 删除 App 时级联删除 K8s 资源
spec:
  project: default            # 所属 AppProject

  source:                     # 来源:Git 仓库信息
    repoURL: https://github.com/myorg/my-app-config
    targetRevision: HEAD     # 分支/Tag/Commit SHA
    path: kubernetes/production  # 仓库中的目录路径

    # 如果使用 Helm Chart(可选)
    # helm:
    #   valueFiles:
    #   - values-prod.yaml
    #   parameters:
    #   - name: image.tag
    #     value: "abc1234"

  destination:               # 目标:部署到哪个集群/namespace
    server: https://kubernetes.default.svc  # 当前集群
    namespace: production

  syncPolicy:                # 同步策略
    automated:               # 开启自动同步
      prune: true             # 自动删除 Git 中已移除的资源
      selfHeal: true          # 自动修复 Drift(防止手动修改)
      allowEmpty: false       # 防止意外清空所有资源
    syncOptions:
    - CreateNamespace=true    # 自动创建不存在的 namespace
    - PrunePropagationPolicy=foreground  # 按依赖顺序删除
    retry:
      limit: 5                # 失败后重试 5 次
      backoff:
        duration: 5s
        factor: 2              # 指数退避
        maxDuration: 3m

  ignoreDifferences:         # 忽略某些字段的 drift(如 HPA 会改 replicas)
  - group: apps
    kind: Deployment
    jsonPointers:
    - /spec/replicas           # HPA 管理 replicas,ArgoCD 不追踪此字段

AppProject:权限隔离

apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: team-backend
  namespace: argocd
spec:
  description: 后端团队项目
  sourceRepos:              # 允许使用的 Git 仓库
  - https://github.com/myorg/backend-*
  destinations:            # 允许部署到哪些集群/namespace
  - server: https://kubernetes.default.svc
    namespace: backend-*   # 通配符匹配
  clusterResourceWhitelist: # 允许操作的集群级资源
  - group: ''
    kind: Namespace
  namespaceResourceBlacklist:  # 禁止操作的命名空间资源
  - group: ''
    kind: ResourceQuota      # 不允许应用自己修改配额
  roles:
  - name: developer
    description: 开发者可同步,不能删除
    policies:
    - p, proj:team-backend:developer, applications, sync, team-backend/*, allow

与 GitHub Actions 集成

推荐的 GitOps 工作流:CI 负责构建镜像,通过 PR 更新 Config 仓库的镜像 Tag,ArgoCD 监听 Config 仓库自动部署。

GitOps CI/CD 工作流

  App 仓库                   Config 仓库          K8s 集群
  my-app                    my-app-config
      
  开发者 push ──► GitHub Actions
                      
                  1. docker build
                  2. docker push registry/my-app:abc123
                  3. PR to Config Repo ──────────────► PR Review
                                                             Merge
                                              更新 image.tag=abc123
                                                            
                                         ArgoCD 检测到变更
                                                            
                                              自动 Sync ────► 更新 Deployment
# .github/workflows/deploy.yml
name: Build and Update Config

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/checkout@v4

    - name: Build Docker image
      run: |
        IMAGE_TAG=${{ github.sha }}
        docker build -t ghcr.io/myorg/my-app:${IMAGE_TAG} .
        docker push ghcr.io/myorg/my-app:${IMAGE_TAG}

    - name: Update Config Repo
      run: |
        # 克隆 config 仓库
        git clone https://x-access-token:${{ secrets.CONFIG_REPO_TOKEN }}@github.com/myorg/my-app-config
        cd my-app-config

        # 更新镜像 Tag(使用 yq 工具)
        yq -i '.image.tag = "${{ github.sha }}"' kubernetes/production/values.yaml

        # 提交并推送
        git config user.email "ci@github.com"
        git config user.name "GitHub Actions"
        git commit -am "chore: update image tag to ${{ github.sha }}"
        git push
App of Apps 模式

当需要管理大量 ArgoCD Application 时,推荐使用 App of Apps 模式——创建一个根 Application,它的 Git 路径下存放其他 Application 的 YAML 文件。ArgoCD 递归创建所有子 Application。这样可以用一个 Git 仓库管理整个集群的所有应用。

Multi-Cluster 管理

# 将外部集群添加到 ArgoCD 管理
argocd cluster add prod-cluster-context \
  --name production

# 查看已注册集群
argocd cluster list

# 查看所有 Application 状态
argocd app list

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

# 查看应用详情(资源树、健康状态)
argocd app get my-app-production

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

# 回滚到指定版本
argocd app rollback my-app-production 3
ArgoCD Image Updater

安装 ArgoCD Image Updater 后,可以自动监听镜像仓库的新 Tag,按语义化版本或 latest 策略自动更新 Application 的镜像版本,并将变更写回 Git(write-back 模式)。这样连 CI 更新 Config 仓库这一步也可以省略。

生产环境 GitOps 最佳实践

1. 分离 App 仓库和 Config 仓库:代码变更不等于部署变更,便于审计和权限控制
2. 生产环境关闭 Auto-Sync:生产部署应通过 PR 审批,手动或经过 Review 后同步
3. 开启 Sync Windows:限制只在维护窗口期(如工作日 10:00-17:00)自动同步生产
4. 配置通知:同步成功/失败、健康状态变化时通知到 Slack/钉钉
5. 加密 Secrets:Config 仓库中的 Secret 必须加密(Sealed Secrets 或 SOPS)

课程总结

恭喜你完成了 Kubernetes 云原生教程全部 10 章!回顾一下学习旅程:

第 1-2 章:基础认知

理解了 K8s 为什么存在,声明式 API 和控制循环这两个核心设计哲学,以及集群的整体架构。

第 3-4 章:工作负载

掌握了 Pod 的生命周期、探针配置、资源限制,以及 Deployment/StatefulSet/DaemonSet 的适用场景。

第 5 章:网络

理解了 K8s 扁平网络模型,四种 Service 类型,以及 Ingress 的 L7 路由配置。

第 6-7 章:配置与存储

学会了用 ConfigMap/Secret 管理配置,用 PV/PVC/StorageClass 实现持久化存储。

第 8 章:包管理

掌握了 Helm Chart 的结构、模板语法、多环境部署和版本管理。

第 9-10 章:工程化

构建了基于 Prometheus+Grafana 的可观测性体系,并通过 ArgoCD 实现了 GitOps 自动化部署。

下一步学习建议

安全加固:RBAC 细粒度权限、PodSecurityAdmission、NetworkPolicy、OPA/Gatekeeper
服务网格:Istio 或 Linkerd,实现流量管理、mTLS、熔断限流
Operator 开发:使用 Kubebuilder 开发自定义 Controller,将运维知识代码化
成本优化:Karpenter 节点自动伸缩、VPA 垂直自动伸缩、资源配额管理
CKA 认证:Kubernetes 官方管理员认证,提升职业竞争力