跳转至

GitOps 基础设施管理:ArgoCD/FluxCD 声明式部署实战与选型决策树

2023 年我们团队从 Jenkins pipeline 切换到 ArgoCD,过程不算痛苦,但有几个踩坑点值得记下来——尤其是要处理好"手动变更"和"GitOps 流程"之间的摩擦。

GitOps 核心概念:一句话讲清楚

GitOps = Git 作为单一事实源 + 自动同步机制。

Git 仓库(source of truth)
     ↓  开发者 push manifest
Controller(ArgoCD/FluxCD)
     ↓  持续 reconcile
Kubernetes 集群(desired state → actual state)

三个关键原则: 1. 所有变更走 Git——禁止直接 kubectl 操作生产集群 2. 自动同步——Controller 持续比对并修复 drift 3. 版本可追溯——每次变更都有 commit hash,可回滚到任意历史版本

ArgoCD vs FluxCD:选型决策树

维度 ArgoCD FluxCD
架构 Go 编写,单二进制 Go 编写,模块化
界面 Web UI(强项) CLI 为主,Web UI 较弱
同步模式 pull(controller 主动拉) pull(同 ArgoCD)
多集群 原生支持,Web UI 可视化 支持,需配置多个 source
与 GitHub 集成 通过 Webhook 原生支持 GitHub App
学习曲线 中(概念多但 UI 友好) 低(简单直接)
资源占用 较高(UI + 数据库) 较低(无状态)
适合团队 大团队、多环境、UI 偏好 小团队、CLI 偏好、GitHub 深度用户

选型建议: - 团队有专职运维 → ArgoCD(UI 降低运维负担) - 团队是纯开发导向、GitHub 重度用户 → FluxCD(CI/CD 集成更顺滑) - 同时管 K8s + Terraform → ArgoCD(支持跨平台资源) - 最小化运维成本 → FluxCD(轻量、少依赖)

ArgoCD 最小可用配置

# app-of-apps 模式:用一个 Application 管理所有子应用
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: platform-apps
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/platform-infra.git
    targetRevision: main
    path: apps
  destination:
    server: https://kubernetes.default.svc
    namespace: argocd
  syncPolicy:
    automated:
      prune: true           # 删除 Git 里不存在的资源
      selfHeal: true        # 自动修复 drift
    syncOptions:
      - CreateNamespace=true
# apps/monitoring.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
  name: monitoring
  namespace: argocd
spec:
  project: default
  source:
    repoURL: https://github.com/myorg/platform-infra.git
    targetRevision: main
    path: overlays/monitoring
  destination:
    server: https://kubernetes.default.svc
    namespace: monitoring
  syncPolicy:
    automated:
      prune: true
      selfHeal: true
    syncOptions:
      - CreateNamespace=true

关键配置解析: - prune: true:Git 里删了资源,集群上也会跟着删——危险但必要 - selfHeal: true:有人手动改了集群,Controller 会自动改回来——防止 drift 累积 - targetRevision: main:指向具体分支,建议不要指向 main,指向 release tag 或特定 branch

FluxCD 最小可用配置

# fluxctl install --namespace=flux-system | kubectl apply -f -
# 上面的命令会自动安装 FluxCD

# 定义 Git 源
apiVersion: source.toolkit.fluxcd.io/v1beta2
kind: GitRepository
metadata:
  name: platform-infra
  namespace: flux-system
spec:
  interval: 1m0s            # 每 1 分钟检查一次变化
  url: https://github.com/myorg/platform-infra.git
  ref:
    branch: main
  secretRef:
    name: github-token      # 需要 Git token

---
# 定义 K8s 目标
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: monitoring
  namespace: flux-system
spec:
  interval: 5m0s
  sourceRef:
    kind: GitRepository
    name: platform-infra
  path: ./overlays/monitoring
  prune: true
  wait: true
  healthCheck:
    - apiVersion: v1
      kind: Namespace
      name: monitoring

ArgoCD vs FluxCD 实际使用感受: - ArgoCD 的 UI 是真实生产力工具——可以直接在 Web 上看每个资源的 diff、手动 sync、看事件日志 - FluxCD 的 CLI 体验好但调试麻烦——出问题要看 kubectl get events -n flux-system 和 flux 的 reconcile log

多集群管理:一个 Git 管所有集群

# clusters/prod/kustomization.yaml
apiVersion: kustomize.toolkit.fluxcd.io/v1beta2
kind: Kustomization
metadata:
  name: prod-apps
  namespace: flux-system
spec:
  interval: 5m
  sourceRef:
    kind: GitRepository
    name: platform-infra
  path: ./clusters/prod
  prune: true
  wait: true
  targetNamespace: apps-prod

---
# clusters/staging/kustomization.yaml(同上结构,不同 path)

ArgoCD 的多集群方式:通过 argocd cluster add <cluster-name> 把多个集群注册到同一个 ArgoCD 实例,然后在 UI 里为每个集群创建独立的 Application。

踩坑:多集群时 namespace 隔离要显式配置——两个集群的同一个 namespace 会冲突。建议在 Git 里用 namespace: prod-apps vs namespace: staging-apps 做区分。

Rollback 策略:三种回滚方式

方式一:Git revert(推荐)

# 找到出问题的 commit
git log --oneline -10

# revert 那个 commit
git revert abc1234

# push 后 Controller 自动同步回滚
git push origin main

优点:可审计、可 review、有历史记录。这是生产环境的首选方式。

方式二:ArgoCD UI 回滚

在 ArgoCD UI 里选择 "Rollback" → 选历史版本 → "Sync"。

优点:快速、可视化。缺点:绕过了 Git,没有 commit 记录,不适合审计要求高的场景。

方式三:FluxCD image update rollback

# 查看当前镜像版本
flux get images -n flux-system

# 回滚到指定版本
flux create image update my-app \
  --image=myregistry/my-app \
  --target-value=1.2.3 \
  --export | kubectl apply -f -

适用场景:只在镜像更新场景下用,其他场景不适用。

常见问题排障

问题一:应用一直处于 OutOfSync 状态

原因:集群状态和 Git 定义不一致,但 selfHeal 没有启用或 sync policy 配置错误。

排查:

# ArgoCD
argocd app get <app-name> --refresh

# FluxCD
flux get kustomizations <name>

修复:手动 sync 一次,确认 Git 定义是正确的,再让 Controller 自动修复。

问题二:Prune 误删了生产资源

原因:prune: true + 开发者忘记从 Git 里删除旧资源。

修复:

# 立即恢复被删除的资源
kubectl apply -f <old-manifest>

# 然后配置保护性 prune
# 在 ArgoCD 的 Application 里加:
# spec:
#   ignoreDifferences:
#     - jsonPointers:
#       - /spec/replicas

教训:prune 是双刃剑,生产环境建议先用 --dry-run 确认删除列表,再正式执行。

问题三:ArgoCD 登录 401

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

# 如果是 K8s 内置认证问题,检查 argocd-cm ConfigMap
kubectl get configmap argocd-cm -n argocd -o yaml

FAQ

Q: GitOps 适合微服务架构吗?

适合,而且微服务越多越需要 GitOps。微服务的部署复杂度呈指数增长——20 个服务手动部署是噩梦,但用 GitOps 就是 20 个 YAML 文件的事。关键是要有分层管理:基础组件(monitoring、logging)一层,业务服务一层,配置和环境差异通过 overlay 管理。

Q: 和 Helm/Kustomize 是什么关系?

GitOps 是流程(怎么管变更),Helm/Kustomize 是工具(怎么渲染模板)。两者正交: - ArgoCD/FluxCD 可以用 Helm chart 作为 source - ArgoCD/FluxCD 可以用 Kustomize overlay 管理多环境 - 也可以直接用裸 YAML(不推荐,维护成本高)

我们的实践:基础组件用 Helm(成熟稳定),业务应用用 Kustomize overlay(轻量灵活),GitOps controller 负责同步。

Q: GitOps 能解决所有部署问题吗?

不能。GitOps 解决的是声明式部署和版本管理问题,但不解决: - 数据库迁移(需要顺序执行,不适合自动同步) - 灰度发布(需要逐步 rollout,要配合argo-rollouts 或 Flagger) - 紧急 hotfix(可以直接改集群,但之后必须补回到 Git)

建议:把 GitOps 当作基础设施管理的基础设施,而不是全部。复杂部署流程还是要配合专门的工具(如 argo-rollouts)。