Helm Chart 入门实战:把一坨 K8s YAML 收敛成可传参的可复用模板 Helm Chart 入门实战:把一坨 K8s YAML 收敛成可传参的可复用模板在 K8s 上部署过几个服务后,你大概率遇到过这个场景:测试环境和生产环境的 Deployment 几乎一模一样,只有镜像 tag、副本数、域名不同。于是你复制了一份 YAML,改几个字段,结果两份文件慢慢就漂移了——生产上加了个环境变量忘了同步到测试,某次故障排查半天才发现两边配置根本对不上。Helm 就是来治这个病的:把 K8s manifest 变成带变量的模板,不同环境只维护一份「差异值」文件。这篇从一个裸 YAML 出发,一步步把它 Helm 化,讲清 Chart 的目录结构、模板语法和最容易踩的坑。从一份重复的 YAML 说起假设我们有个 web 服务,原始 Deployment 长这样:# deployment.yaml —— 每个环境复制一份,改镜像、副本、域名apiVersion:apps/v1kind:Deploymentmetadata:name:webspec:replicas:2selector:matchLabels:{app:web}template:metadata:labels:{app:web}spec:containers:-name:webimage:myrepo/web:1.4.0ports:-containerPort:8080生产要 4 个副本、镜像是1.4.0,测试要 1 个副本、镜像是1.5.0-rc1。用复制大法就会有两份几乎相同的文件。Helm 的思路是:结构只写一遍,变的部分抽成变量。第一步:建一个 Chart 骨架helm create mychart生成的目录里,核心就三样(其余可以先删掉):mychart/ ├── Chart.yaml # Chart 的元信息:名字、版本 ├── values.yaml # 默认值(变量的默认取值) └── templates/ # 带变量的 K8s manifest 模板 └── deployment.yamlChart.yaml是这个包的身份证。values.yaml存所有可配置项的默认值。templates/里是模板,用{{ }}引用 values。Chart.yaml最小内容:apiVersion:v2name:mychartversion:0.1.0# Chart 自身的版本appVersion:1.4.0# 应用默认版本,仅作展示用途第二步:把变量抽进 values.yaml# values.yaml —— 默认值,可被 -f 或 --set 覆盖replicaCount:2image:repository:myrepo/webtag:1.4.0service:port:8080然后把templates/deployment.yaml里会变的字段换成模板引用:apiVersion:apps/v1kind:Deploymentmetadata:name:{{.Release.Name}}-web# .Release.Name 是安装时指定的实例名spec:replicas:{{.Values.replicaCount}}selector:matchLabels:{app:{{.Release.Name}}-web}template:metadata:labels:{app:{{.Release.Name}}-web}spec:containers:-name:webimage:{{ .Values.image.repository }}:{{ .Values.image.tag }}ports:-containerPort:{{.Values.service.port}}几个内置对象要认识:.Values.xxx:读 values.yaml(或命令行覆盖)里的值。.Release.Name:helm install name时的实例名,用它拼资源名,同一个 Chart 就能装多份而不撞名。.Chart.Name:Chart 名字本身。第三步:先渲染再安装,别盲发Helm 最实用的习惯是装之前先看渲染结果。helm template把模板 values 算出最终 YAML 打到屏幕,不碰集群:helm template myapp ./mychart你会看到{{ .Release.Name }}被替换成myapp,replicas变成2。确认没问题再真正安装:helminstallmyapp ./mychart想模拟安装但不真的提交给集群,用--dry-run:helminstallmyapp ./mychart --dry-run--debug第四步:多环境靠「差异值」文件,而不是复制 Chart这才是 Helm 的价值所在。生产和测试共用同一个 Chart,各自只维护一个覆盖文件:# values-prod.yaml —— 只写和默认值不同的部分replicaCount:4image:tag:1.4.0# values-test.yamlreplicaCount:1image:tag:1.5.0-rc1安装时用-f叠加,后面的覆盖前面的:# 生产helminstallweb-prod ./mychart-fvalues-prod.yaml# 测试helminstallweb-test ./mychart-fvalues-test.yaml临时改一两个值不想建文件,用--set:helm upgrade web-prod ./mychart-fvalues-prod.yaml--setimage.tag1.4.1覆盖优先级从低到高是:values.yaml默认值 -f文件 --set。到这一步,「两份 YAML 漂移」的问题就根治了:结构只有一份,差异一目了然。升级与回滚:Helm 记得每一版改完值用upgrade而不是重新install:helm upgrade web-prod ./mychart-fvalues-prod.yamlHelm 会把每次 upgrade 记成一个 revision。发现新版本有问题,一条命令滚回上一版:helmhistoryweb-prod# 看历史版本helm rollback web-prod1# 回到第 1 版这比手动kubectl apply旧文件靠谱得多——你不用自己保管「上一版长啥样」,Helm 替你存了。两个新手高频坑坑一:缩进用了 Tab。Helm 模板本质是 YAML,YAML 不认 Tab。模板里{{ }}前后的缩进必须是空格,否则helm template直接报error converting YAML。坑二:字符串数字没加引号。像镜像 tag1.40这种,如果 values 里写成tag: 1.40,YAML 会解析成浮点数1.4,渲染出来镜像就变成web:1.4,拉取失败。凡是可能被误判成数字/布尔的值,一律加引号:tag: 1.40。模板里也建议image: {{ .Values.image.repository }}:{{ .Values.image.tag }}整体套引号。小结Helm 治的是「YAML 复制漂移」:结构写一遍进templates/,变的部分抽进values.yaml,多环境只维护差异文件。三个核心目录:Chart.yaml(身份)、values.yaml(默认值)、templates/(带{{ }}的模板)。装前先渲染:helm template/--dry-run --debug看最终 YAML,别盲发。覆盖优先级:默认值 -f 文件--set;多环境用多个 values 文件叠加。升级用 upgrade,出事 rollback:Helm 记录每个 revision,回滚不用自己存旧文件。两个必踩坑:模板缩进只能空格不能 Tab;像 tag 这种值一律加引号防被解析成数字。一句话记忆:Helm K8s YAML 的模板引擎,结构一份、差异分环境,装前先渲染、出事能回滚。