Flux CD 实战:GitOps 实现 K8s 持续部署

当 Kubernetes 集群里的应用从几个涨到几十个,靠 kubectl apply 手工发布迟早会翻车。Flux CD 是一套基于 GitOps 理念的持续部署工具:把 Git 仓库当成集群状态的「唯一真相源」,每一个 Deployment、每一个 ConfigMap 都由控制器自动从 Git 拉取并调和(reconcile)。本文用一套可复制的最小实践,带你从零把 Flux CD 在生产集群跑起来。

一、为什么需要 GitOps

传统 CI/CD 的末端往往是「构建完镜像 → 推到集群」,发布动作由人触发,集群状态与代码仓库很容易发生漂移。GitOps 的反转在于:Git 是唯一可信源,集群只是 Git 状态的镜像。任何变更都必须先提交到 Git,Flux CD 持续比对实际状态与期望状态,发现偏差就自动纠正。

同样走声明式交付,ArgoCD GitOps 实战 与 Flux CD 是最常被拿来比较的两套方案,核心差异如下:

维度Flux CDArgoCD
架构形态多 Controller 组合,无中心 UI单体应用 + 强大 Web UI
配置方式纯 YAML,Git 即配置YAML + 可选 UI 操作
镜像自动更新内置 Image Automation需配合 Image Updater
学习曲线偏 CLI,概念分散UI 直观,上手快
适用团队偏好「全 Git 驱动、自动 PR」需要可视化审计与人工审批

二、Flux CD 核心架构

Flux CD 由一组独立运行的 Controller 组成,各管一摊,彼此通过 CRD 协作:

  • Source Controller:对接 Git 仓库、Helm 仓库、OCI 制品,产出可被调和的「源」。
  • Kustomize Controller:消费 Kustomize 目录,把资源配置应用到集群。
  • Helm Controller:通过 HelmRelease 管理 Helm Chart 的部署与升级。
  • Image Automation Controller:监听镜像仓库,自动更新 Git 里的镜像 tag。
  • Notification Controller:把调和结果、健康状态推送到 Slack / Webhook。

三、环境准备

你需要一个可用的 K8s 集群(本地可用 k3s 实战 快速起一个)、一个 GitHub 账号,以及本地安装好 kubectl 与 flux CLI。Flux CD 要求集群版本 ≥ 1.28。

# 校验环境是否满足 Flux 安装前置条件
flux check --pre

# 安装 flux CLI(macOS 示例)
brew install fluxcd/tap/flux

四、用 bootstrap 把集群交给 Git

flux bootstrap 是一步到位的初始化:它会在集群里创建 flux-system 命名空间与所有 Controller,同时把一份最小配置提交到你指定的 Git 仓库,之后这份仓库就成为集群的真相源。

export GITHUB_TOKEN=xxxx
flux bootstrap github \
  --owner=your-org \
  --repository=cluster-gitops \
  --branch=main \
  --path=./clusters/production

执行后,Git 仓库会多出 clusters/production/flux-system 目录;以后你在 path 下新增任何 Kustomize 或 Helm 配置,Flux 都会自动调和。推荐用如下目录结构组织:

clusters/production/
├── flux-system/          # bootstrap 自动生成
├── apps/
│   ├── web.yaml          # Kustomization 指向 web 应用
│   └── redis.yaml
└── infrastructure/
    └── ingress.yaml      # Traefik 等基础组件

五、第一个应用:用 Kustomization 部署

先在 Git 里定义「源」与「调和对象」。下面两段 YAML 放在 apps/web.yaml:

# 1) 声明 Git 源
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
  name: web-app
  namespace: flux-system
spec:
  interval: 1m
  url: https://github.com/your-org/web-app
  ref:
    branch: main
---
# 2) 声明 Kustomization,把仓库内容应用到集群
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
  name: web-app
  namespace: flux-system
spec:
  interval: 5m
  path: "./deploy/overlays/production"
  sourceRef:
    kind: GitRepository
    name: web-app
  prune: true            # 删除 Git 中已移除的资源
  wait: true             # 等待健康后再标记成功

prune: true 保证 Git 里删掉的配置,集群也会跟着删;wait: true 让 Flux 等待 Pod 进入 Ready 再判定成功。镜像构建应交给 GitHub Actions 流水线:CI 负责构建并推送镜像,Flux CD 负责把新镜像部署到集群,二者职责清晰、互不越界。

六、用 HelmRelease 管理 Helm 应用

对已有 Helm Chart 的组件,不必手写 Kustomize,直接用 HelmRelease:

# 声明 Helm 仓库源
apiVersion: source.toolkit.fluxcd.io/v1
kind: HelmRepository
metadata:
  name: bitnami
  namespace: flux-system
spec:
  interval: 1h
  url: https://charts.bitnami.com/bitnami
---
apiVersion: helm.toolkit.fluxcd.io/v2
kind: HelmRelease
metadata:
  name: redis
  namespace: redis
spec:
  interval: 30m
  chart:
    spec:
      chart: redis
      version: "18.x"
      sourceRef:
        kind: HelmRepository
        name: bitnami
      interval: 1h
  values:
    auth:
      enabled: false
    master:
      persistence:
        size: 8Gi

Helm Controller 会按 interval 定时比对 Chart 版本与 values,发现新版或配置变更就自动升级,同时保留 Helm 的回滚能力,无需人工介入。

七、镜像自动更新:提交 PR 而不是改集群

GitOps 的精髓是「只改 Git」。配合 Image Automation Controller,新镜像推送到仓库后,Flux 会自动向 Git 提交一个把镜像 tag 改掉的提交,再由调和环节部署,全程不碰 kubectl。

apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImagePolicy
metadata:
  name: web-app
  namespace: flux-system
spec:
  imageRepositoryRef:
    name: web-app
  policy:
    semver:
      range: "1.x"     # 只允许 1.x 的递增
---
apiVersion: image.toolkit.fluxcd.io/v1beta2
kind: ImageUpdateAutomation
metadata:
  name: web-app
  namespace: flux-system
spec:
  interval: 5m
  git:
    checkout:
      ref:
        branch: main
  update:
    path: ./clusters/production
    strategy: Setters

八、密钥、多环境与可观测性

Git 里不该放明文 Secret。可以用 External Secrets Operator 把云厂商密钥同步进集群,Flux 只负责引用 Secret 名,敏感值始终留在密钥管理系统里。

多环境用目录隔离即可:clusters/staging 与 clusters/production 各 bootstrap 一次,分别对应两套集群或同集群不同命名空间。基础网络层可交给 Cilium 做 Zero-Trust,入口流量用 Traefik 暴露;节点弹性不足时,Karpenter 能按需扩缩节点。

调和状态要看得见。把 Flux 的告警接到 Prometheus + Grafana,一旦某个 Kustomization 长时间未 Ready,立刻在仪表盘与 IM 里亮红灯。

九、生产落地检查清单

检查项建议做法
仓库权限bootstrap 用的部署密钥仅授予目标仓库,遵循最小权限
目录隔离staging / production 分目录或分仓库,互不影响
prune & wait均开启,保证 Git 删除即集群删除、部署可等待健康
镜像策略ImagePolicy 锁定 semver 范围,避免误升大版本
密钥管理用 External Secrets Operator,禁止明文入库
告警接 Prometheus/Grafana + IM 通知,调和失败可感知
备份定期备份 Git 仓库与 etcd,灾难可重建

十、常见误区与排障

现象可能原因处理
资源一直 Unknown/NotReady仓库地址或 token 错、网络不通flux get sources git 看 Message
改了 Git 集群没变interval 未到 / 调和被暂停flux reconcile kustomization <name> --with-source
HelmRelease 卡住Chart 版本不存在或 values 不合法看 flux get hr <name> 的 Conditions
自动更新不提交ImagePolicy 范围无匹配 / 无写库权限检查 policy.range 与部署密钥写权限
误删生产资源prune 误伤先 staging 验证,配合 Git 历史回滚

十一、进阶方向:多集群与渐进式交付

当集群不止一个,可以用 Flux 的 Kustomization 通过 kubeConfigRef 指向其他集群的 kubeconfig(建议由 External Secrets Operator 注入),实现「一个 Git 仓库编排多套环境」。更进一步的渐进式交付,可以叠加 Flagger:它监听 Flux 部署的新版本,自动做金丝雀分析(基于 Prometheus 指标),指标达标才全量,不达标自动回滚——把发布风险交给自动化判断,而不是赌运维手速。

另一个常见组合是「CI 不动、CD 交给 Flux」。CI 阶段只负责编译、测试、推送带唯一 tag 的镜像;Flux 侧的 ImagePolicy 监听到新 tag 后,自动把 Git 里的镜像引用改成新版本并提交。这样开发者的提交记录里看不到部署噪音,而集群状态始终能在 Git 里一键审计、随时回滚到任意历史提交。

十二、哪些场景暂时不适合 GitOps

GitOps 不是银弹。对需要秒级弹性伸缩的临时批处理作业、或强依赖外部工单审批的金融核心链路,纯 Git 驱动的自动调和反而会增加摩擦与等待。这类场景更稳妥的做法是保留人工触发入口,或用 ArgoCD 的 Web UI 做「同步前人工确认」。先想清楚变更频率与审计要求,再决定是否把控制权完全交给 Git。

小结

Flux CD 把「发布」这个动作从一次人工操作,变成了一条由 Git 驱动、自动调和、可回溯的流水线。它和 ArgoCD 的思路一致,但更偏向「控制器组合 + Git 提交自动化」的轻量哲学。当你管理的不再是三五个工作负载,而是跨多环境、多集群的一整片基础设施时,GitOps 会从「可选项」变成「必选项」。

上一篇 PostgreSQL 分区表实战:性能优化与自动维护
下一篇 direnv 实战:用 .envrc 实现项目级环境隔离
最新评论
Docker 网络模式详解:bridge/host 生产选型 - FSData
Docker 网络模式详解:bridge/host 生产选型 - FSData
8月20日
[…] 注意最后那条:把端口绑定到 127.0.0.1,再由宿主机上的 Nginx 反代进来,比直接 -p 80:80 暴露安全得多,也方便统一做
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
Vue3 + TypeScript 工程化:类型安全的前端架构 - FSData
8月20日
[…] Pinia 的工程化用法,可以参考我们之前的实战文章 《Vue3 组合式 API + Pinia:状态管理从入门到实战》,那里覆盖了 Sto
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
2026 年最值得装的 10 个 VS Code 插件(AI/前端/后端/效率全覆盖) - FSData
8月19日
[…] 状态,点一下就能起停容器,配合我们讲过的 Docker Compose 编排 […]
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
Redis 缓存设计:穿透、击穿、雪崩与最佳实践 - FSData
8月19日
[…] 缓存三大坑的本质都是”缓存失效导致请求穿透到数据库”。记住口诀:穿透用布隆、击穿用锁、雪崩用错峰。配合合理的过期策略
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
GitHub Actions 实战:从零搭建 CI/CD 流水线 - FSData
8月19日
[…] Docker 镜像部署。结合我们之前写的 Docker Compose 一键编排实战,可以在 CI […]