K8s 运维系列 | 第 27 天:GitOps 实践——Argo CD 声明式部署

引言

在上一篇我们讨论了 Jenkins 与 GitLab CI 如何把镜像构建、部署到集群,本质上是「Push 模式」——CI 主动把资源推到 K8s。但当集群规模扩大、环境变多、审批链路变长之后,Push 模式会逐渐暴露出三个痛点:集群状态与实际想达的状态不一致(drift)、无法从单一源头追溯谁在什么时候改了什么、以及回滚困难。GitOps 就是为了解决这三个痛点而生的一种运维哲学:把 Git 仓库作为集群期望状态的唯一事实源,由常驻集群的控制器持续比对 Git 与实际集群,自动收敛到期望状态。

Argo CD 是 CNCF 官方毕业项目,也是目前最主流的 GitOps 工具之一。它以 Kubernetes 原生方式运行在集群内,通过 Repository、Application、Sync、Sync Policy 四个核心概念,把「Git 提交一次、集群自动持续同步」的体验带给运维和开发。本篇将完整搭建 Argo CD,实现从 Git 到 K8s 的声明式部署,覆盖应用管理、同步策略、自动回滚、App of Apps 与多集群同步等进阶用法。

K8s 运维 第27天

GitOps 理念与 Argo CD 架构

从 Push 到 Pull 的范式转变

传统 CI/CD 是流水线 Push 资源到集群,命令执行完就结束了,之后集群状态如何演进流水线无法感知。GitOps 反过来:常驻控制器 Pull Git 最新状态,持续 diff,发现偏差就发起 sync。这带来三个直接好处:可追溯(每次变更都是 Git commit)、可回滚(git revert 即可)、可自愈(Pod 被删除、镜像被改写,控制器都能恢复)。

Argo CD 的核心组件

Argo CD 由三个组件构成,全部运行在集群内:

  1. argocd-server:提供 Web UI、REST API 与 CLI 后端,是运维交互入口。
  2. argocd-repo-server:负责拉取 Git 仓库、渲染模板(支持 Kustomize、Helm、Jsonnet、Ksonnet)。
  3. argocd-application-controller:核心控制器,定期比对 Git 期望状态与集群实际状态,触发 sync。

四大核心概念

  • Repository:Git 仓库连接信息,支持 HTTPS、SSH、GitHub App、OIDC 等多种认证方式。
  • Application:Argo CD 的顶层对象,描述「部署什么、从哪部署、部署到哪」。
  • Sync:把 Git 状态应用到集群的操作,可手动或自动触发。
  • Sync Policy:同步策略,包含自动同步(automated)与钩子(preSync/sync/postSync webhook)。

核心概念详解

Application 资源剖析

Application 是 Argo CD 的心。它把「Git 路径 + K8s 目标」连起来,一个 Application 可以部署单个或多个 K8s 资源。

apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/stellardata/k8s-manifests.git
    targetRevision: main
    path: apps/myapp/production
    helm:
      valueFiles:
        - values-prod.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - ServerSideApply=true

关键字段说明:source.repoURL 指向 Git 仓库,source.path 指定子目录,source.targetRevision 支持分支、Tag 或 Commit SHA,destination.serverdestination.namespace 指定目标集群与命名空间,syncPolicy.automated.prune 让 Git 删除的资源在集群中同步删除,selfHeal 让集群被漂移后自动修复。

Sync Policy 三种模式

模式 触发方式 适用场景
手动 Sync 运维在 UI 或 CLI 点击 sync 生产环境、需要审批的变更
自动 Sync(automated) Git 提交后自动同步 开发、测试环境
条件 Sync(webhook) 仅 Git 仓库变更时触发 兼顾安全与自动化的生产

自动 Sync 结合 prune: trueselfHeal: true 是最强力的 GitOps 形态:Git 是权威,集群一切偏离都会被收敛回来。

与 Kustomize、Helm 的协作

GitOps 不等于只用裸 YAML。Kustomize 适合「多环境同一份 base」,Helm 适合「参数化模板」。Argo CD 原生支持三种渲染方式,通过 source.path 下是否存在 kustomization.yamlChart.yaml 自动识别,也可以在 Application 里显式声明:

spec:
  source:
    path: apps/myapp
    kustomize:
      images:
        - myapp:harbor.stellardata.top/app/myapp:v1.2.3

实战步骤

步骤一:使用 Helm 部署 Argo CD

Argo CD 官方推荐使用 Helm 部署,稳定、可配置、便于升级。

# 添加官方仓库
helm repo add argo https://argoproj.github.io/argo-helm
helm repo update

# 创建专用命名空间
kubectl create namespace argocd

# 安装 Argo CD
helm install argocd argo/argo-cd 
  -n argocd 
  --set server.service.type=ClusterIP 
  --set controller.replicas=2 
  --set controller.resources.requests.cpu=200m 
  --set controller.resources.requests.memory=256Mi 
  --wait --timeout 15m

安装完成后,通过 Port-Forward 访问 UI:

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

# 端口转发到本地 8080
kubectl -n argocd port-forward svc/argocd-server 8080:443

步骤二:使用 Argo CD CLI 与配置集群

Argo CD CLI 支持直接对接集群,无需额外 kubeconfig:

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

# 登录 UI 对应的 API
argocd login localhost:8080 --username admin --password '<初始密码>'

# 查看集群连接状态
argocd cluster list

# 添加第二个集群
argocd cluster add k8s-prod-2 
  --name prod-cluster-2 
  --server https://10.0.1.100:6443 
  --secret-name prod-cluster-2

在集群内创建的 ServiceAccount 与绑定权限,Argo CD 会自动注册为可用于同步的目标集群。

步骤三:创建 Repository 与应用

将生产 Git 仓库连接到 Argo CD,然后创建 Application 完成首次同步:

# 添加 Git 仓库
argocd repo add https://github.com/stellardata/k8s-manifests.git 
  --username bot --password "$GH_TOKEN"

# 创建 Application
cat > app-myapp.yaml <<'EOF'
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: myapp
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/stellardata/k8s-manifests.git
    targetRevision: main
    path: apps/myapp
    helm:
      releaseName: myapp
      valueFiles:
        - values-prod.yaml
  destination:
    server: https://kubernetes.default.svc
    namespace: production
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
EOF
argocd app create -f app-myapp.yaml

# 查看同步状态
argocd app get myapp

步骤四:配置 Git Webhook 与自动同步

自动同步是 GitOps 的灵魂。默认情况下 Argo CD 每 3 分钟轮询一次 Git,如果希望通过推送立即触发,可以配置 Webhook:

# 查看 Webhook 服务地址
kubectl -n argocd get svc argocd-server -o wide

# 在 GitHub 仓库设置中添加 Webhook
# URL: https://argocd-server.stellardata.top/api/webhook
# Content type: application/json
# Events: Push only

如果 Argo CD 部署在内网、无法直接被 GitHub 访问,可以借助中间层:

# 使用 nginx Ingress 代理 GitHub Webhook
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: argocd-webhook
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /api/webhook
spec:
  rules:
  - host: argocd.stellardata.top
    http:
      paths:
      - path: /api/webhook
        pathType: Prefix
        backend:
          service:
            name: argocd-server
            port:
              number: 443

步骤五:使用 App of Apps 管理多应用

当应用数量超过 20 个时,逐个 argocd app create 会失控。Argo CD 支持「Application 里再放 Application」的 App of Apps 模式,用一个 Git 目录管理所有应用:

k8s-manifests/
├── apps-of-apps/
│   └── app-of-apps.yaml       # 元应用,指向 applications 目录
└── applications/
    ├── myapp.yaml             # 单个 Argo CD Application
    ├── payment.yaml
    └── order.yaml
# apps-of-apps/app-of-apps.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: apps-of-apps
  namespace: argocd
spec:
  source:
    repoURL: https://github.com/stellardata/k8s-manifests.git
    path: applications
    targetRevision: main
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true
      selfHeal: true

步骤六:同步钩子与 Git 自动化回滚

Argo CD 支持在同步前后运行任意命令(通过 preSync/sync/postSync hooks),例如清理数据库表结构迁移:

apiVersion: batch/v1
kind: Job
metadata:
  name: migrate-schema
  annotations:
    argocd.argoproj.io/hook: PreSync
    argocd.argoproj.io/hook-delete-policy: HookSucceeded
spec:
  template:
    spec:
      containers:
      - name: migrate
        image: harbor.stellardata.top/app/myapp-migrate:v1
        args: ["/app/migrate.sh"]
      restartPolicy: Never

如果自动同步失败,可以配置回滚策略到上一次成功版本:

spec:
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    retry:
      limit: 3
      backoff:
        duration: 10s
        factor: 2
        maxDuration: 5m

常见问题 FAQ

Q1:Application 显示 OutOfSync,如何快速定位差异?

argocd app diff myapp 会输出 Git 与集群的字段级差异,包括资源新增、删除、修改。UI 中的 Changes 标签页也展示同类信息。如果差异是集群侧被人为改动,argocd app sync myapp --self-heal 会自动恢复;如果是 Git 尚未包含的期望变更,则需先合入 Git 再同步。

Q2:如何保证生产环境必须审批才能同步?

关闭 syncPolicy.automated,改用手动 sync 或 --auto-prune=false 的 GitOps Policy。更彻底的方案是 Argo CD 的 AppProject + RBAC:为运维角色配置只允许 getlist,生产同步权限授予少数 SRE,并在企业侧接入 SSO 与 MFA。

# appproject.yaml 示例
apiVersion: argoproj.io/v1alpha1
kind: AppProject
metadata:
  name: production
spec:
  sourceRepos:
    - 'https://github.com/stellardata/k8s-manifests.git'
  destinations:
    - server: https://kubernetes.default.svc
      namespace: production
  rbacRules:
    - roles: ['admin']
      actions: ['*', 'sync']

Q3:Git 权限怎么最小化?

GitOps 场景下,只需要一个只读 Token 或 SSH Key,Argo CD 只用它 pull 仓库内容,不需要 push 权限。企业级做法是使用 GitHub App 或 OIDC 短期 Token,避免长期 Token 泄露风险。

Q4:Argo CD 与 Jenkins/GitLab CI 是什么关系?

两者职责不同:CI 负责构建镜像、生成制品;GitOps 负责把制品(或 K8s 清单)声明到 Git,并由 Argo CD 应用到集群。推荐组合是 CI 产出镜像 + 更新 Git 里的 imageTag 字段,Argo CD 通过自动 Sync 部署。CI 不再直接 kubectl apply,实现「CI 只写 Git、集群只读 Git」的清晰边界。

Q5:同步延迟一般多久?如何调优?

默认轮询周期为 3 分钟,可在 Helm values 中调整 application.instance.refresh.interval。生产推荐用 Webhook 触发(毫秒级),配合合理轮询作为兜底。对于大规模集群(>500 Applications),建议开启 Application Controller 的分片机制,把同步负载分摊到多个 controller 副本。

总结

GitOps 把「Git 是集群状态唯一事实源」这句话变成工程实践:CI 只负责写 Git、Argo CD 只负责读 Git 并同步集群、运维与开发只在 Git 上操作。本篇从 Argo CD 架构、Application 资源、Sync Policy、Kustomize/Helm 集成,到 App of Apps、Webhook、AppProject 与 RBAC,给出了完整落地路径。

实践要点:自动同步 + prune + selfHeal 是 GitOps 的三大开关;App of Apps 让集群管理扩展到 100+ 应用;Git Webhook 让同步延迟从分钟级降到秒级;AppProject + RBAC 让权限与审批清晰可查。把这些能力组合起来,你就拥有了一个「Git 提交一次、集群持续收敛、错误自动回滚」的云原生运维体系。

下期预告

K8s 运维系列 | 第 28 天:灰度发布——金丝雀、蓝绿与滚动发布实践

微信二维码
© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容