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 配置错误。
排查:
修复:手动 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)。