_helpers.tpl 约定
在 Helm Chart 中,以 下划线开头的模板文件(如 _helpers.tpl)有特殊含义:
不会渲染为 K8s 资源
以 _ 开头的文件 Helm 不会将其渲染为 K8s 资源提交给 API Server。它们仅作为命名模板的容器。
全局可访问
templates/ 目录下所有模板文件中定义的命名模板({{- define "xxx" -}})对其他所有模板文件都可见。
约定命名
命名模板名称约定为 "chartname.funcname" 格式,如 "myapp.fullname"、"myapp.labels",避免与其他 Chart 的模板冲突。
define / include / template 的差别
| 关键字 | 来源 | 返回值 | 支持管道 | 推荐场景 |
|---|---|---|---|---|
define |
Go text/template | 定义模板,无返回值 | — | 定义命名模板 |
template |
Go text/template | 直接输出(void) | 否 | 不需要缩进控制时 |
include |
Helm 扩展 | 字符串(可管道) | 是 | 绝大多数情况(推荐) |
# ❌ template:无法控制缩进,输出可能错位
labels:
{{ template "myapp.labels" . }} # 无法添加 | nindent 4
# ✅ include:返回字符串,可通过管道控制缩进
labels:
{{- include "myapp.labels" . | nindent 4 }} # 正确缩进
标准 helpers:helm create 生成的 _helpers.tpl
{{/*
_helpers.tpl — helm create 生成的标准模板
*/}}
{{/*
myapp.name:Chart 名称,截断到 63 字符(K8s 资源名限制)
*/}}
{{- define "myapp.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
myapp.fullname:Release 名称 + Chart 名称的组合
避免同一集群多个 Release 的资源名冲突
*/}}
{{- define "myapp.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
myapp.chart:Chart 名称 + 版本,用于 helm.sh/chart label
*/}}
{{- define "myapp.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
myapp.labels:标准 K8s 推荐标签集
app.kubernetes.io/* 是官方推荐的标签前缀
*/}}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ include "myapp.chart" . }}
{{ include "myapp.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
myapp.selectorLabels:Selector 用标签(不含版本信息)
Selector 一旦创建不可修改,所以不包含经常变化的版本标签
*/}}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{/*
myapp.serviceAccountName:Service Account 名称
*/}}
{{- define "myapp.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }}
{{- default (include "myapp.fullname" .) .Values.serviceAccount.name }}
{{- else }}
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}
toYaml | nindent 的正确用法
toYaml 将 Go 结构体(map、slice)转为 YAML 字符串,配合 nindent 控制缩进层级。
# values.yaml 中定义复杂结构
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
tolerations:
- key: node-role.kubernetes.io/spot
operator: Equal
value: "true"
effect: NoSchedule
# 模板中使用 toYaml | nindent
spec:
containers:
- name: app
{{- with .Values.resources }} # 只有 resources 非空才输出
resources:
{{- toYaml . | nindent 6 }} # . 在 with 块内指向 .Values.resources
{{- end }}
{{- with .Values.tolerations }}
tolerations:
{{- toYaml . | nindent 4 }}
{{- end }}
自定义 Helper 函数
{{/*
myapp.imagePullPolicy:根据 tag 自动推断 pullPolicy
tag 为 latest 时用 Always,否则用 IfNotPresent
*/}}
{{- define "myapp.imagePullPolicy" -}}
{{- if eq .Values.image.tag "latest" }}
Always
{{- else }}
IfNotPresent
{{- end }}
{{- end }}
{{/*
myapp.env:合并全局环境变量和局部环境变量
*/}}
{{- define "myapp.env" -}}
{{- $env := merge (.Values.env | default dict) (.Values.global.env | default dict) }}
{{- range $key, $value := $env }}
- name: {{ $key | quote }}
value: {{ $value | quote }}
{{- end }}
{{- end }}
{{/*
myapp.configChecksum:配置 ConfigMap 变更时触发 Pod 滚动重启
在 Deployment 的 annotations 中加入 configmap 的 hash 值
*/}}
{{- define "myapp.configChecksum" -}}
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- end }}
实战:统一的资源标签模板
将所有资源的标签统一管理,确保 K8s 推荐标签(app.kubernetes.io/*)一致性。
# _helpers.tpl — 完整的标签模板体系
{{/* 完整标签(用于 metadata.labels,含版本信息)*/}}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ include "myapp.chart" . }}
{{- include "myapp.selectorLabels" . | nindent 0 }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- if .Values.global.env }}
environment: {{ .Values.global.env | quote }}
{{- end }}
{{- end }}
{{/* Selector 标签(不含版本,不可变)*/}}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/component: {{ .Values.component | default "web" | quote }}
{{- end }}
# deployment.yaml 中统一调用
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels: # 完整标签
{{- include "myapp.labels" . | nindent 4 }}
spec:
selector:
matchLabels: # Selector 标签(不含版本)
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels: # Pod 标签
{{- include "myapp.selectorLabels" . | nindent 8 }}
annotations: # 配置变更自动重启
{{- include "myapp.configChecksum" . | nindent 8 }}
Deployment 的 spec.selector 一旦创建就不可修改(K8s 限制)。如果 selectorLabels 包含版本号,每次升级版本号变化都会导致 Selector 变更,从而使 helm upgrade 失败。因此 selectorLabels 只包含稳定不变的标签(名称 + 实例名)。
_helpers.tpl 是 Chart 代码复用的核心。命名约定 "chartname.funcname" 避免冲突。始终使用 include 而非 template,因为 include 支持管道。标准 helpers 包括 fullname(资源名称)、labels(完整标签)、selectorLabels(选择器标签,不含版本)。toYaml | nindent N 是处理复杂 values 结构的标准写法。配置 checksum 注解是实现配置变更触发 Pod 滚动重启的优雅方案。