Kustomize 完整掌握 — 配置即代码的艺术
前言
上一篇文章 我们掌握了 Helm——它解决的是”如何打包和分发应用”。但生产环境中还有一个棘手的问题:同一套应用,在 dev / test / prod 环境里只有细微差异(副本数、镜像 tag、域名),能不能不复制粘贴整份 YAML?
Kustomize 就是答案。它从 Kubernetes 1.14 起内置在 kubectl 中,核心思想是 base + overlay:一份基础配置打底,每个环境只声明差异。
| 对比维度 | Helm | Kustomize |
|---|---|---|
| 核心理念 | 模板 + 值注入 | 基础配置 + 差异化补丁 |
| 工作方式 | {{ .Values.xxx }} 占位符 |
原地 patch 修改 YAML |
| 配置复用 | 多 values.yaml 覆盖 | base/overlay 分层 |
| 模板语法 | Go Template(需学习) | 纯 YAML(零学习语法) |
| 原生集成 | 第三方工具 | kubectl apply -k 内置 |
| 最佳场景 | 对外分发的通用包 | 内部多环境配置管理 |
简单粗暴的区分:对外分发的 Chart 用 Helm,内部多环境管理用 Kustomize。两者并不对立——后面会看到它们如何组合使用。
一、基础篇:hello world
1.1 确认版本
1 | kubectl version --client | grep Kustomize |
kubectl apply -k 直接用,无需额外安装。
1.2 第一个 Kustomize 项目
创建 base 目录:
1 | mkdir -p ~/kustomize-demo/base |
vim ~/kustomize-demo/base/deployment.yaml
1 | apiVersion: apps/v1 |
vim ~/kustomize-demo/base/service.yaml
1 | apiVersion: v1 |
vim ~/kustomize-demo/base/kustomization.yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
1.3 运行
1 | # 预览渲染结果(不部署) |
就这么简单。kustomization.yaml 是入口,resources 列出要管理的文件。目前它只是”打包”,还没有任何差异化能力。接下来才是重点。
二、多环境篇:base + overlay
Kustomize 的核心模式:base 写不变的部分,overlay 只写差异。
2.1 创建 overlay 目录
1 | mkdir -p ~/kustomize-demo/overlays/{dev,test,prod} |
vim ~/kustomize-demo/overlays/dev/kustomization.yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
replicas 是 Kustomize 内置的快捷字段,专门用来 原地修改 Deployment 的 replicas,不需要写 patch 文件。
vim ~/kustomize-demo/overlays/test/kustomization.yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
patches 语法:使用 JSON Patch(RFC 6902)。
op可以是replace/add/remove,path用/指到目标字段。上面这条语义是:”把 nginx Deployment 的容器镜像换成 alpine 版”。
vim ~/kustomize-demo/overlays/prod/kustomization.yaml
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
2.4 渲染对比
1 | # 分别查看三个环境的最终 YAML |
你会发现 base 中的 deployment.yaml + service.yaml 原样保留,overlay 只”覆盖”了差异部分。这是 Kustomize 和 Helm 最大的不同:没有模板语言,没有占位符。
三、核心资源生成器:ConfigMap / Secret / 镜像替换
Kustomize 不仅能 patch 已有资源,还能自动生成 ConfigMap、Secret,并优雅地处理镜像 tag 替换。
3.1 ConfigMap 生成器 — 从文件生成
创建环境专属的 nginx 配置:
创建 nginx 配置目录:
1 | mkdir -p ~/kustomize-demo/overlays/dev/nginx-conf |
vim ~/kustomize-demo/overlays/dev/nginx-conf/default.conf
1 | server { |
然后在 ~/kustomize-demo/overlays/dev/kustomization.yaml 末尾追加 configMapGenerator:
1 | # ... 原有内容 ... |
渲染出来看看:
1 | # 用 yq 精确提取 ConfigMap 部分(推荐) |
输出:
1 | apiVersion: v1 |
为什么要加 hash? 假设你不小心改了 nginx 配置中的某个参数,如果 ConfigMap 名字不变(始终叫 nginx-config),Deployment 不会知道内容变了,Pod 继续用旧配置运行。加 hash 之后:配置内容变了 → ConfigMap 名字变了 → Deployment 挂载的 volume 引用也自动更新为新名字 → Pod 必然重建 → 新配置自动生效。 这也是为什么 Deployment 里可以安全地写 name: nginx-config —— Kustomize 渲染时会自动替换。
3.2 让 Deployment 挂载生成的 ConfigMap
现在的问题是:ConfigMap 名称带了随机 hash,Deployment 怎么引用?答案是 namePrefix / nameSuffix 或直接用生成器的 name。
Kustomize 会自动把模板中的 nginx-config 替换为实际带 hash 的名称,只要在 Deployment 中引用同名即可。修改 base/deployment.yaml,加入 volume 挂载:
1 | # 在 containers 下增加 |
这里有一个关键问题:ConfigMap 名称已经变成 nginx-config-7k4m8d5g2f,Deployment 里挂载的还是 name: nginx-config,那不就不匹配了吗?
这就是 Kustomize 最精妙的地方:它会扫描所有资源,把引用了 nginx-config 的地方全部自动替换成带 hash 的名字。 渲染后的 Deployment 实际上变成了:
1 | # Deployment 渲染结果(关键字段) |
所以 Deployment 挂载的一定能对上 ConfigMap 的名字。写的时候用固定名,渲染后自动变成 hash 名,既保证了引用正确,又保证了内容变更即滚动更新。
3.3 Secret 生成器 — 从文字面值生成
1 | # 在 kustomization.yaml 中添加 |
渲染结果:
1 | apiVersion: v1 |
安全提醒:这里的值是明文写在 kustomization.yaml 中的,不要直接提交 Git。后面会介绍如何搭配 sops 加密。
3.4 images — 统一替换镜像 tag
假设 CI 构建的镜像 tag 每次不同(如 git commit hash),总不能去改 deployment.yaml 吧?Kustomize 的 images 字段就是干这个的:
1 | # 在 kustomization.yaml 中添加 |
images 会找到所有使用该镜像的 Deployment,把 tag 替换成 abc1234。这个是声明式的镜像替换,比 sed 靠谱一百倍。
prod overlay 完整示例:
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
四、进阶篇:Kustomize + Helm 混合使用
前面说过二者不互斥。企业里最典型的模式:用 Helm 拉取外部 Chart,用 Kustomize 做环境化定制。
4.1 helmChartInflator — 引入外部 Helm Chart
假设我们要引入 Bitnami 的 Redis Chart,用 Kustomize 定制。
注意:这个功能在 Kustomize 5+ 中通过
helmCharts字段原生支持。
overlays/prod/kustomization.yaml 中添加:
1 | # 引入外部 Helm Chart(Kustomize 会自动 helm pull + 渲染) |
国内用户注意:如果 Bitnami 仓库访问慢,可以先用
helm pull拉下来放到本地,改用chartHome指定本地路径。或者参考上篇 Helm 文章搭建本地仓库。
overlays/prod/redis-values.yaml
1 | # Helm values 覆盖 |
4.2 用 Kustomize patch 修改 Helm 原生资源
Helm Chart 渲染出的资源可能不完全满足需求,用 Kustomize 的 patches 做二次加工:
1 | # 继续在 kustomization.yaml 中 |
4.3 完整混合 overlay 示例
把 nginx(自己的 Chart)+ Redis(外部 Helm Chart)组合在一起,这是企业里最常见的模式:
1 | overlays/prod/ |
overlays/prod/kustomization.yaml 完整版:
1 | apiVersion: kustomize.config.k8s.io/v1beta1 |
渲染看看整个 prod 环境到底生成了哪些资源:
1 | kubectl kustomize overlays/prod/ --enable-helm |
--enable-helm是启用 helmCharts 处理的开关。若不加这个 flag,helmCharts 部分会被跳过。
五、实操篇:用 Kustomize 部署 dev/test/prod 到集群
5.1 创建命名空间
1 | kubectl create ns dev |
5.2 部署三个环境
1 | # Dev |
5.3 验证环境差异
1 | # Dev 环境:1 个副本,NodePort |
5.4 查看实际生效的配置
1 | # 对比 base 和某环境 overlay 的差异 |
六、安全篇:SOPS 加密 Secret
和 Helm 那篇一样,Secret 的明文不能提交 Git。Kustomize 原生支持 SOPS 加密。
6.1 安装 SOPS + Kustomize SOPS 插件
1 | # 安装 sops(参考 Helm 文章 6.1 节) |
6.2 创建并加密 Secrets 文件
1 | # 准备明文 secret(不提交 Git) |
加密后的 .env.enc 内容:
1 | DB_PASSWORD=ENC[AES256_GCM,data:xxxx,iv:xxxx,tag:xxxx,type:str] |
6.3 在 kustomization.yaml 中引用加密文件
1 | # 加在 overlays/prod/kustomization.yaml 中 |
Kustomize 会自动检测
.enc后缀,调用sops解密后再生成 Secret。CI 机器上需要安装sops并有对应的解密密钥。
6.4 .gitignore 规则
1 | # .gitignore |
七、交付篇:同时输出 Helm 包 + Kustomize 清单
企业级交付的终极形态:对外给 Helm Chart、对内给 Kustomize overlay。
1 | my-app/ |
Makefile 统一构建入口:
1 | # 打包 Helm Chart |
1 | make build |
两种产物各有用处:
.tgz扔到 Harbor 供其他团队helm install;*.yaml给 ArgoCD 做 GitOps 部署。
八、生产排障:常见问题速查
8.1 kubectl apply -k 报 accumulating resources: ... doesn't exist
1 | # resources 中引用的文件不存在 |
8.2 ConfigMap 名称对不上导致挂载失败
1 | # 渲染出来确认实际 ConfigMap 名称 |
8.3 patch 不生效 / YAML 格式报错
1 | # 常见原因:JSON Patch 的 path 写错了 |
8.4 images 替换不生效
1 | # images 字段中 name 必须和 Deployment 中 image 字段的前缀完全匹配 |
8.5 helmCharts 报 Error: no repositories found
1 | # helmCharts 引用外部仓库需要先 helm repo add |
8.6 kubectl kustomize 报 cyclic dependency detected
1 | # 原因:kustomization.yaml 引用了自己所在的目录 |
8.7 多 overlay 共享 base 时 base 改动影响所有环境
1 | # 改 base 前先看哪些 overlay 引用了它 |
8.8 secretGenerator 生成的值是明文的?
1 | # 是的。kustomization.yaml 中 secretGenerator.literals 的值是明文 |
九、面试高频 12 题
1. Kustomize 和 Helm 的区别?
Helm 是模板引擎({{ .Values.xxx }}),Kustomize 是配置叠加(base + patch)。Helm 适合分发通用包,Kustomize 适合多环境配置管理。kubectl apply -k 是 K8s 内置能力。
2. base 和 overlay 是什么? base 定义通用的基础配置;overlay 针对特定环境声明差异(如副本数、镜像 tag、namespace)。渲染时 base + overlay 合并成最终 YAML。
3. Kustomize 怎么改 Deployment 副本数?
replicas: 字段是内置快捷方式,直接声明 Deployment 名和副本数,不需要写 JSON Patch。
4. patches 只支持 JSON Patch 吗?
JSON Patch(RFC 6902)最常用,支持 replace/add/remove。新版 Kustomize 也支持 Strategic Merge Patch。
5. ConfigMap 名字后面为什么有 hash?
Kustomize 根据 ConfigMap 内容生成 hash 后缀。内容变了 hash 就变 → Deployment 自动滚动更新 → 新配置自动生效。不用手动 kubectl rollout restart。
6. hash 名称变了,Deployment 挂载会不会对不上?
不会。Kustomize 会扫描所有资源,把引用原名称(如 nginx-config)的地方全部替换为带 hash 的实际名称。
7. images 字段怎么用?
声明式镜像 tag 替换。images.name 匹配 Deployment 中的镜像名,newTag 指定新 tag。CI 中动态注入 git commit hash 最常见。
8. helmCharts 和 Kustomize 的关系?
Kustomize 5+ 可以通过 helmCharts 引入 Helm Chart 并渲染为 base 资源,再用 Kustomize 的 patch/replicas/images 做二次定制。相当于 Helm 负责拉包,Kustomize 负责调参。
9. commonLabels 和 labels 的区别?
commonLabels 会给所有资源(包括 Deployment 的 template labels)加标签;labels 只给顶层资源加,不会影响 Pod template。
10. namespace 配置会覆盖 base 中的 namespace 吗?
会。overlay 中的 namespace 会覆盖所有资源的 namespace 字段。
11. 多个 overlay 怎么管理?避免重复配置?
创建 overlays/common/ 存放公共 overlay,各环境 overlay 引用它。或者用 Kustomize 的 components 特性。
12. 生产和开发用同一套 Kustomize,怎么防止误改 base?
Git PR + review 流程。base 的改动会影响所有 overlay,所以 base 变更必须经过 Code Review。CI 中用 kubectl kustomize 渲染各 overlay 做 diff 检查。
十、总结:Helm vs Kustomize 选型指南
| 场景 | 推荐工具 |
|---|---|
| 开发一个要分发给社区/其他团队的通用应用 | Helm |
| 同一个应用部署到 3+ 环境,每个环境差异小 | Kustomize |
| 需要引入开源组件(如 Redis、PostgreSQL) | Helm(或 Kustomize + helmCharts) |
| GitOps 工作流(ArgoCD / Flux) | 两者皆可,Kustomize 更原生 |
| 团队不熟悉 Go Template | Kustomize(纯 YAML) |
| 需要模板化的复杂逻辑 | Helm |
最终推荐的企业架构:
1 | Helm Chart(制作通用包) |
把 Helm 当作”基础包”,Kustomize 做”环境适配层”,二者各司其职,互不替代。
回头看你的学习路径:
1 | Helm: install/upgrade → Chart 结构 → 手写 Chart → 多环境 → secrets → Harbor |
常用命令速查
| 场景 | 命令 |
|---|---|
| 渲染预览 | kubectl kustomize <dir> |
| 部署 | kubectl apply -k <dir> |
| 删除 | kubectl delete -k <dir> |
| 渲染含 Helm Chart | kubectl kustomize <dir> --enable-helm |
| 修改副本数 | replicas: 字段(kustomization.yaml 内) |
| 替换镜像 tag | images: 字段 |
| JSON Patch | patches: + op: replace/add/remove |
| 生成 ConfigMap | configMapGenerator: + files: / literals: |
| 生成 Secret | secretGenerator: + literals: / envs: |
| 加密 Secret | sops --encrypt → .env.enc → secretGenerator.envs |
| 引入 Helm Chart | helmCharts: + repo: + valuesFile: |
希望这篇教程帮你彻底搞懂 Kustomize,并能和 Helm 搭配使用。两篇一起,覆盖了 Kubernetes 应用配置管理的核心能力。