从原生 K8s 到 Helm:彻底搞懂templates/、values与Chart.yaml
刚学完
k8s/文件夹里那一堆原生 YAML,以为自己"懂"了 Kubernetes 部署。打开helm/目录后却懵了:templates/里全是{{ .Values.xxx }},values.yaml、values-dev.yaml、values-prod.yaml长得还不一样,还有个Chart.yaml不知道是干嘛的。这篇文章把这几个核心问题一次性讲透。
一、为什么需要 Helm?从"手写简历"到"简历模板"
如果你把k8s/里的文件比作手写简历——内容固定,改一个字就得重抄一份——那helm/templates/就是简历模板。
你写一次模板,填入不同的信息,就能生成无数份针对不同岗位的简历。Helm 干的就是这件事:把静态 YAML 变成动态模板,让同一套配置能适配开发、测试、生产等多种环境。
二、templates/:你的"智能 YAML 工厂"
templates/是 Helm Chart 的核心引擎室。它存放的是"带变量的 YAML 草稿",Helm 根据values.yaml里的配置,自动"生产"出适合不同环境的 Kubernetes 资源清单。
2.1 每个文件的作用
Table
| 文件 | 作用 |
|---|---|
_helpers.tpl | 模板"工具箱",定义可复用的代码片段(如统一标签生成),不会直接产出 K8s 资源 |
deployment.yaml | 定义 Pod 怎么跑(镜像、副本数、环境变量、资源限制) |
service.yaml | 定义集群内如何访问 Pod |
ingress.yaml | 定义外部流量怎么进来(域名、路径、TLS) |
configmap.yaml/secret.yaml | 配置和敏感数据注入容器 |
pvc.yaml | 持久化存储 |
hpa.yaml | 自动扩缩容 |
resourcequota.yaml | 命名空间资源配额 |
networkpolicy.yaml | Pod 间网络安全隔离 |
serviceaccount.yaml | RBAC 权限身份 |
monitoring.yaml | 监控配置 |
notes.txt | 安装完成后给用户的提示信息 |
2.2 核心语法:占位符与渲染
templates/deployment.yaml里可能是这样写的:
yaml
spec: replicas: {{ .Values.replicaCount.backend }} template: spec: containers: - name: backend image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" resources: requests: memory: "{{ .Values.backend.resources.requests.memory }}"Helm 渲染后,就变成你熟悉的原生 K8s YAML:
yaml
spec: replicas: 3 template: spec: containers: - name: backend image: "ghcr.io/xxx/camp-backend:v1.0.0" resources: requests: memory: "512Mi"三、values.yaml与values-*.yaml:基准值 vs 覆盖值
这是最容易让人困惑的地方。为什么有三个values文件?它们怎么协作?
3.1 角色定位
Table
| 文件 | 角色 | 类比 |
|---|---|---|
values.yaml | 默认值文件(基准配置) | 菜单上的默认套餐 |
values-dev.yaml | 开发环境覆盖文件 | "不要辣、少盐"——只改需要改的地方 |
values-prod.yaml | 生产环境覆盖文件 | "加量、加辣、加芝士"——强化配置 |
Helm 的合并逻辑非常简单:
plain
最终配置 = values.yaml(完整默认值) + values-xxx.yaml(只覆盖差异部分)3.2 为什么覆盖文件那么短?
因为它们只写和默认值不一样的地方。
假设values.yaml里有完整的默认配置:
yaml
replicaCount: backend: 3 web: 2 auth: 2 image: repository: ghcr.io/xxx/camp-backend tag: "v1.0.0" backend: resources: requests: memory: "1Gi" cpu: "500m" limits: memory: "2Gi" cpu: "1000m" ingress: enabled: true host: camp.example.comvalues-dev.yaml只需要覆盖差异部分:
yaml
replicaCount: backend: 1 # 开发环境只要1个副本,省资源 web: 1 auth: 1 backend: resources: requests: memory: "256Mi" # 低配就行 cpu: "100m" limits: memory: "512Mi" cpu: "200m" ingress: host: camp-dev.local # 本地域名注意:image.repository、ingress.enabled等字段在values-dev.yaml里没有出现——因为它们和默认值一样,不需要改。
执行命令时:
bash
helm install camp ./camp --values values-dev.yamlHelm 会自动合并,最终生效的就是"默认值 + 开发环境补丁"。
3.3values-prod.yaml:与 dev 完全相反的方向
它和values-dev.yaml本质一样——都是覆盖文件。但方向完全相反:
Table
| 维度 | values-dev.yaml(降级) | values-prod.yaml(升级) |
|---|---|---|
| 副本数 | 1 个,省资源 | 3~5+ 个,高可用 |
| 资源限制 | CPU/内存给最低配 | requests 和 limits 都大幅提高 |
| HPA 自动扩容 | 关闭 | 开启,CPU > 70% 自动扩容 |
| 安全策略 | 宽松 | NetworkPolicy 收紧、RBAC 细化 |
| 监控告警 | 基础或关闭 | Prometheus/Grafana 全开 |
| 域名 | 本地/内网 | 正式公网域名 + TLS 证书 |
| 日志级别 | DEBUG(方便排错) | INFO/WARNING(减少噪音) |
values-prod.yaml可能长这样:
yaml
replicaCount: backend: 5 web: 3 backend: resources: requests: memory: "2Gi" cpu: "1000m" limits: memory: "4Gi" cpu: "2000m" hpa: enabled: true minReplicas: 3 maxReplicas: 10 targetCPUUtilizationPercentage: 70 ingress: host: camp.company.com tls: enabled: true secretName: camp-tls执行:
bash
helm install camp ./camp --values values-prod.yaml最终生成的是能扛住真实流量的生产级配置。
3.4 这样设计的好处
Table
| 好处 | 说明 |
|---|---|
| DRY(不重复自己) | 通用配置只写一次在values.yaml,不用复制 N 份 |
| 维护简单 | 升级镜像版本?改values.yaml一处即可,所有环境自动生效 |
| 差异一目了然 | 打开values-prod.yaml,一眼看出生产环境和默认配置到底哪里不同 |
| 减少人为错误 | 不会因为漏复制某个字段,导致 dev 和 prod 行为不一致 |
| 灵活组合 | 你可以随时创建values-staging.yaml、values-test.yaml,零成本扩展新环境 |
四、Chart.yaml:Helm Chart 的"身份证"
Chart.yaml不是 Kubernetes 资源(不会交给kubectl执行),而是专门给 Helm 工具自己看的元数据文件。Helm 靠它来识别、管理、分发这个 Chart。
4.1 典型内容
yaml
apiVersion: v2 # Helm 3 固定写 v2 name: camp # Chart 的名字 description: Cloud Asset Management Platform Helm Chart type: application # 这是应用 Chart(不是库 Chart) version: 1.0.0 # Chart 自身的版本号 appVersion: "1.0.0" # 里面部署的应用版本号 # 如果有依赖其他 Chart,写在这里 dependencies: - name: postgresql version: "12.x.x" repository: "https://charts.bitnami.com/bitnami" condition: postgresql.enabled4.2 关键字段解析
Table
| 字段 | 作用 |
|---|---|
apiVersion: v2 | 声明这是 Helm 3 格式的 Chart |
name | Chart 的名字,安装时默认的 release 名前缀 |
type | application(可部署的应用)或library(仅供其他 Chart 引用的模板库) |
version | Chart 包版本。每次改模板、改默认值,这个版本要升级 |
appVersion | 应用代码版本。比如后端镜像 tag 是v2.3.1,这里就写2.3.1 |
dependencies | 依赖的其他 Chart。比如你的应用需要 PostgreSQL,不用自己写,直接引用官方 Chart |
4.3 为什么需要它?
版本管理:打包时生成camp-1.0.0.tgz,版本号来自这里。
仓库索引:推送到 Helm 仓库后,别人能搜索到:
bash
helm search repo camp # 显示:camp 1.0.0 Cloud Asset Management Platform Helm Chart依赖解析:自动下载 PostgreSQL、Redis 等依赖 Chart。
区分"Chart 更新"和"应用更新":
改了
templates/deployment.yaml的 HPA 逻辑 → 升级version(Chart 变了)后端代码从
v1.0.0升级到v2.0.0→ 升级appVersion(应用变了)
五、完整使用示例
bash
# 1. 预览开发环境渲染结果 helm template camp ./camp --values ./values-dev.yaml # 2. 安装到开发环境 helm install camp-dev ./camp \ --namespace camp-dev \ --create-namespace \ --values ./values-dev.yaml # 3. 安装到生产环境 helm install camp-prod ./camp \ --namespace camp-prod \ --create-namespace \ --values ./values-prod.yaml # 4. 查看部署状态 helm list --all-namespaces helm status camp-prod -n camp-prod # 5. 升级(修改配置后) helm upgrade camp-prod ./camp \ --namespace camp-prod \ --values ./values-prod.yaml # 6. 回滚到上一个版本 helm history camp-prod -n camp-prod helm rollback camp-prod 2 -n camp-prod # 7. 打包分享 helm package ./camp # 生成 camp-1.0.0.tgz六、总结
从k8s/到helm/,本质是从静态配置走向动态管理。
记住这个公式:
Chart.yaml(我是谁)+templates/(模板骨架)+values.yaml(默认值)+values-*.yaml(环境补丁)= 生产级 Kubernetes 部署
templates/让你"写一次,到处用"values.yaml给你"统一的基准"values-dev.yaml和values-prod.yaml让你"只改差异,环境隔离"Chart.yaml让 Helm 知道"这个包叫什么、什么版本、依赖谁"
掌握这套机制,你就从"会写 Kubernetes YAML"进阶到了"会用 Helm 管理生产级多环境部署"。下一步,就是去挑战多集群部署和 GitOps 了。