2. Helm Chart 基础回顾:Chart.yaml、values.yaml、templates 目录结构及渲染机制
在深入 values.schema.json 准入策略之前,必须牢固掌握 Helm Chart 的核心构成与渲染流水线。Helm 将 Kubernetes 资源打包为 Chart,通过模板引擎将静态 YAML 转化为参数化、可复用的交付制品。本节聚焦三个核心文件与模板渲染的完整链路。
2.1 Chart 目录结构总览
一个标准的 Helm Chart 目录遵循以下约定(以 my-app 为例):
my-app/
├── Chart.yaml # Chart 元数据(名称、版本、依赖等)
├── values.yaml # 默认配置值(用户可覆盖)
├── values.schema.json # (可选)JSON Schema 校验 values 结构
├── charts/ # (可选)子 Chart 或依赖包
├── templates/ # Go 模板文件,渲染后生成 Kubernetes 资源
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── _helpers.tpl # 模板辅助函数(不直接生成资源)
│ └── NOTES.txt # 安装后的使用说明
└── .helmignore # (可选)打包时忽略的文件模式
关键点:只有
templates/ 目录下的文件会经过模板引擎渲染并提交给 Kubernetes API;_helpers.tpl 以 _ 开头,不会被当作独立资源文件处理。
2.2 Chart.yaml:Chart 的身份证明
Chart.yaml 是每个 Chart 的入口文件,定义了 Chart 的元数据、版本约束和依赖关系。以下是一个生产级示例:
apiVersion: v2
name: my-app
description: A production-grade microservice deployment
type: application
version: 1.2.3
appVersion: "2.5.0"
kubeVersion: ">=1.21.0-0"
keywords:
- microservice
- web
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: postgresql
version: "12.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
| 字段 | 说明 | 示例值 |
|---|---|---|
apiVersion |
Chart API 版本,v2 为 Helm 3+ 标准 | v2 |
version |
Chart 自身的语义化版本,用于发布管理 | 1.2.3 |
appVersion |
所部署应用的版本,与 Chart 版本解耦 | "2.5.0" |
kubeVersion |
对 Kubernetes 集群版本的约束 | >=1.21.0-0 |
dependencies |
子 Chart 依赖列表,支持条件启用 | postgresql |
常见陷阱:
version 与 appVersion 混淆会导致升级策略混乱。Chart 版本变化触发 Helm Release 升级,而 appVersion 仅作为标签信息,不参与版本比较。
2.3 values.yaml:配置的默认值锚点
values.yaml 是用户与 Chart 交互的主要界面。它定义了所有可配置参数的默认值,模板文件通过 .Values 对象引用这些值。良好的 values 设计应具备层次化结构和清晰注释。
# values.yaml
replicaCount: 3
image:
repository: nginx
tag: "1.25.3"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
host: ""
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 250m
memory: 256Mi
postgresql:
enabled: true
auth:
database: myapp
username: myapp
用户可通过 --set 或自定义 values-*.yaml 文件覆盖任意层级的值。覆盖优先级为:--set > 用户 values 文件 > values.yaml 默认值。
2.4 templates 目录与渲染机制
templates/ 目录下的文件使用 Go 模板语法({{ }}),结合 Sprig 函数库进行动态渲染。渲染流程分为三个阶段:
- 值合并:Helm 将
values.yaml、用户提供的 values 文件、--set参数合并为一个统一的.Values对象。 - 模板解析:遍历
templates/目录(排除_开头的文件),对每个文件执行 Go 模板引擎,生成纯 YAML/JSON 字符串。 - 资源验证:Helm 对渲染结果进行基本的 YAML 语法检查和 Kubernetes 资源校验(若启用
--validate)。
渲染核心公式:Chart 模板 + Values 数据 → 有效的 Kubernetes 资源清单。任何模板语法错误或值引用缺失都会导致渲染失败,阻止 Release 安装或升级。
以下是一个典型的 Deployment 模板片段:
{{- /* templates/deployment.yaml */ -}}
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "my-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-app.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
ports:
- containerPort: {{ .Values.service.port }}
2.5 渲染流程可视化
下图展示了从 Chart 源文件到最终 Kubernetes 资源的完整渲染链路:
2.6 模板函数与管道操作
Helm 模板支持丰富的内置函数和 Sprig 库,常用操作包括:
| 函数/操作 | 用途 | 示例 |
|---|---|---|
include |
调用 _helpers.tpl 中定义的命名模板 |
{{ include "my-app.labels" . }} |
nindent |
换行并缩进指定空格数 | {{ include "my-app.labels" . | nindent 4 }} |
default |
为缺失值提供默认值 | {{ .Values.replicaCount | default 1 }} |
quote |
将值用双引号包裹 | {{ .Values.image.tag | quote }} |
required |
强制要求某个值必须存在,否则报错 | {{ required "ingress.host is required" .Values.ingress.host }} |
toYaml |
将结构体转为 YAML 字符串 | {{ .Values.resources | toYaml | nindent 8 }} |
最佳实践:使用
required 函数对安全敏感参数(如数据库密码、TLS 证书)进行强制校验,避免因遗漏配置导致集群安全风险。这是 values.schema.json 准入策略的补充手段。
2.7 子 Chart 与全局值
当 Chart 包含依赖(子 Chart)时,值传递遵循以下规则:
- 父 Chart 的 values.yaml 中与子 Chart 同名的键会被自动传递给子 Chart。
- 全局值(
.Values.global) 可被所有子 Chart 共享,适用于跨 Chart 的公共配置(如全局域名、镜像仓库地址)。 - 子 Chart 作用域隔离:子 Chart 无法直接访问父 Chart 的非全局值,必须通过显式传递或全局值。
# 父 Chart values.yaml
global:
registry: docker.io
domain: example.com
postgresql:
auth:
database: myapp
username: myapp
# 子 Chart 自动接收 postgresql 下的值
理解这些基础机制后,我们才能进一步探讨如何通过 values.schema.json 在渲染前对 values 进行结构化校验,从而拦截高风险变更——这正是本课程的核心主题。