使用 Kustomize Overlay 按环境组织仓库结构
为 dev 和 production 组织一个仓库,并避开 ConfigMap 滚动发布的陷阱。
真实的应用会运行在多个环境中,这些环境之间只有细微差别:副本数、主机名、配置值。Flux 应用纯 YAML 或 Kustomize overlay,并能检测文件夹使用的是哪一种。本指南展示如何用 Kustomize 为多个环境组织仓库,如何告诉 Flux 每个环境的位置,并介绍一个在修改配置时容易踩到的坑。本指南基于前面指南中的 webapp 示例。
选择布局:用文件夹,而不是分支
你可以把环境建模为长期存在的分支(dev、staging、main),但这会让升级变成一次次合并,也会让各环境逐渐漂移。单一分支加每个环境一个文件夹的方式更容易理解:所有环境并排可见,对其中一个的修改就是一次普通的 diff。
Flux 的文档介绍了三种常见的仓库策略:
- Monorepo。 所有集群、应用和基础设施都在一个仓库中。最容易上手,也是这里所使用的。
- 每个环境一个仓库。 例如,staging 和 production 各一个,具有各自独立的访问规则。
- 每个团队或每个应用一个仓库。 隔离性强,由一个平台仓库来注册每个团队的仓库。
一个典型的 monorepo 如下所示:
fleet-infra/
├── clusters/
│ ├── dev/ # Flux Kustomizations for the dev cluster
│ └── production/ # Flux Kustomizations for the production cluster
├── infrastructure/ # ingress controller, cert-manager, monitoring
└── apps/
├── base/webapp/ # shared manifests
├── dev/ # overlay for dev
└── production/ # overlay for production
构建 Kustomize base 与 overlay
apps/base/webapp/kustomization.yaml 列出共享资源:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- deployment.yaml
- service.yaml
在 apps/base/webapp/deployment.yaml 中,让容器从一个 ConfigMap 读取设置,该 ConfigMap 将由各个 overlay 生成(base 中不要写 namespace 字段,因为由 overlay 来设置):
envFrom:
- configMapRef:
name: webapp-config
apps/dev/kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
namespace: webapp-dev
resources:
- namespace.yaml
- ../base/webapp
replicas:
- name: webapp
count: 2
configMapGenerator:
- name: webapp-config
literals:
- HEADER=Hello from dev
并配有一个创建 webapp-dev 的 namespace.yaml。apps/production/kustomization.yaml 与之类似,只是 namespace: webapp-prod、count: 4、有它自己的命名空间清单和它自己的 HEADER 值。你可以在提交之前检查某个 overlay 会渲染出什么:
kustomize build apps/dev
# or, without installing kustomize separately:
kubectl kustomize apps/dev
让 Flux Kustomization 指向每个 overlay
Flux 会检测路径中的 kustomization.yaml 并为你构建。在每个集群的文件夹中,为每个环境添加一个 Flux Kustomization。clusters/dev/apps.yaml:
apiVersion: kustomize.toolkit.fluxcd.io/v1
kind: Kustomization
metadata:
name: apps
namespace: flux-system
spec:
interval: 10m
sourceRef:
kind: GitRepository
name: flux-system
path: ./apps/dev
prune: true
wait: true
timeout: 3m
对于 production 集群,clusters/production/apps.yaml 使用 path: ./apps/production。由于每个集群在 bootstrap 时都使用了自己的 --path,每个集群只能看到它自己的文件夹。
让生产环境保持审慎
与带有手动同步按钮的工具不同,Flux 是自动应用的,所以你要通过 Git 为生产环境把关。一种有力的模式是让 dev 跟随一个分支,而让 production 跟随发布的标签。在 production 集群的 source 中:
apiVersion: source.toolkit.fluxcd.io/v1
kind: GitRepository
metadata:
name: fleet-releases
namespace: flux-system
spec:
interval: 5m
url: https://github.com/your-org/fleet-infra
ref:
semver: ">=1.0.0"
这样,production 只有在你打标签发布版本时才会变化。对主分支的拉取请求审批是另一种常见的把关方式。
有意识地处理配置变更
修改某个环境中的 HEADER 值,看看会发生什么。Kustomize 会在生成的 ConfigMap 名称后附加内容哈希。新的值会产生新的 ConfigMap(webapp-config-<hash>),并更新 Deployment 的引用,从而触发 Pod 滚动发布。旧的 ConfigMap 现在成为孤儿,而在 prune: true 下 Flux 会为你删除它。这种行为正是你想要的:配置变更会让 Pod 滚动。
手写的普通 ConfigMap 则不同。如果你编辑了一个被 Deployment 通过 envFrom 读取的 ConfigMap,Deployment 的 spec 并没有变化,所以运行中的 Pod 会保留旧值。对于任何在变化时应当重启工作负载的内容,请使用 configMapGenerator。Helm chart 有等价的技术,Helm 指南会介绍。
按集群替换值
有时某个值因集群而异,但你又不想为它建立一整个 overlay,比如域名。Flux Kustomization 可以在构建之后替换变量:
spec:
postBuild:
substitute:
cluster_domain: dev.example.com
substituteFrom:
- kind: ConfigMap
name: cluster-vars
清单中任何 ${cluster_domain} 都会在应用时被替换。请谨慎使用,因为 overlay 更易于审查。
在各环境之间升级变更
采用这种布局,升级就是一连串普通的提交。先修改 dev overlay(例如,在 apps/dev 中运行 kustomize edit set image nginx=nginx:1.26 来升级镜像),让 Flux 应用它,然后验证。接着对 apps/production 做同样的修改,通过一个需要审批的拉取请求。CI 流水线可以自动完成 dev 的提交,而审阅者则把关 production 的提交。Flux 的镜像自动化也可以为你完成 dev 这一步,镜像自动化指南会介绍。
热门指南
-
推送与拉取:Flux 如何向 Kubernetes 交付 为什么基于拉取、由 Git 驱动的交付会改变你部署、保障安全和恢复集群的方式。 -
使用 GitRepository 与 Kustomization 部署你的第一个应用 通过 Kustomization 资源将 Flux 指向 Git 中的清单,并观察同步。 -
控制同步行为:间隔、Prune、漂移修正与回滚 决定 Flux 何时应用变更、删除什么、如何暂停它,以及如何撤销一次有问题的部署。 -
使用 Flux 镜像自动化实现镜像更新自动化 让 Flux 检测新的容器镜像标签,并将其提交回 Git。 -
使用 Flux 配置多集群 从一个仓库管理多个集群,包含共享基础设施和每个集群各自的差异。 -
Flux CD 与 Argo CD:如何选择 GitOps 工具 比较架构、UI、Helm、密钥、租户和镜像自动化,以选出合适的工具。