模板分隔符与基本语法
Helm 使用 Go 的 text/template 包。所有模板指令写在双大括号 {{ }} 内。
# 基础输出
name: {{ .Values.appName }}
# 管道(Pipeline):将左侧的值传给右侧的函数
name: {{ .Values.appName | upper }} # 转大写
name: {{ .Values.appName | quote }} # 加引号
name: {{ .Values.appName | trunc 63 | trimSuffix "-" }} # 截断+去尾横线
# 去除空白行:{{- 去左侧空白,-}} 去右侧空白
{{- if .Values.enabled }}
key: value
{{- end }}
{{- 的重要性
YAML 对缩进和空行极为敏感。{{- (注意空格)会消除该指令前的所有空白(包括换行)。 -}} 消除后面的空白。在条件判断和循环中正确使用 - 是避免生成无效 YAML 的关键。
内置对象
Helm 在渲染模板时注入了多个内置对象,通过 . 访问。
.Values
来自 values.yaml 和用户提供的 --set/--values 的所有配置值。例如
.Values.image.repository。.Release
Release 对象。包含 .Release.Name(Release 名称)、.Release.Namespace(命名空间)、.Release.IsInstall(首次安装)、.Release.IsUpgrade(升级)、.Release.Revision(版本号)。
.Chart
Chart.yaml 的内容。包含 .Chart.Name、.Chart.Version、.Chart.AppVersion、.Chart.Description 等。
.Files
访问 Chart 中的非模板文件(如配置文件)。常用方法:.Files.Get "config.ini"、.Files.AsConfig(转为 ConfigMap 格式)。
.Capabilities
集群能力信息。包含 .Capabilities.KubeVersion.GitVersion(K8s 版本)、.Capabilities.APIVersions.Has "apps/v1"(检查 API 是否可用)。
.Template
当前模板信息。包含 .Template.Name(模板文件路径)、.Template.BasePath(模板目录路径)。
# 常见内置对象用法
metadata:
name: {{ .Release.Name }}-myapp
namespace: {{ .Release.Namespace }}
labels:
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" }}
spec:
containers:
- image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
控制流:if / else
# 基本 if/else
{{- if .Values.ingress.enabled }}
# 渲染 Ingress...
{{- end }}
# if/else if/else
type:
{{- if eq .Values.service.type "NodePort" }}
NodePort
{{- else if eq .Values.service.type "LoadBalancer" }}
LoadBalancer
{{- else }}
ClusterIP
{{- end }}
# 逻辑运算符:and / or / not
{{- if and .Values.ingress.enabled .Values.ingress.tls }}
# 同时启用了 ingress 和 tls
{{- end }}
# 真值判断:以下值为 false(空字符串、0、nil、空 slice/map)
{{- if .Values.someValue }} # someValue 非空/非零/非 nil 则执行
循环:range
# 遍历 slice(列表)
env:
{{- range .Values.envVars }}
- name: {{ .name }} # . 指向当前元素
value: {{ .value | quote }}
{{- end }}
# 遍历 map(键值对),$key 和 $val 是变量绑定
annotations:
{{- range $key, $val := .Values.annotations }}
{{ $key }}: {{ $val | quote }}
{{- end }}
# 使用 $index 获取索引
{{- range $index, $host := .Values.ingress.hosts }}
# $index 从 0 开始
{{- end }}
with:作用域切换
# 不使用 with(繁琐)
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
pullPolicy: {{ .Values.image.pullPolicy }}
# 使用 with 切换作用域(. 变为 .Values.image)
{{- with .Values.image }}
image: {{ .repository }}:{{ .tag }}
pullPolicy: {{ .pullPolicy }}
{{- end }}
# with 块内需要访问父作用域,使用 $ 引用全局根对象
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 2 }}
releaseName: {{ $.Release.Name }} # $ 访问根对象
{{- end }}
define 与 include:模板复用
使用 define 定义命名模板,用 include 或 template 调用。
# 在 _helpers.tpl 中定义命名模板
{{- define "myapp.labels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
# 在其他模板文件中使用 include(支持管道,推荐)
metadata:
labels:
{{- include "myapp.labels" . | nindent 4 }}
# template 关键字(不支持管道,不推荐用于有缩进需求的场景)
{{ template "myapp.labels" . }}
include vs template
include 是 Helm 扩展的函数,返回字符串,可以接管道操作(如 | nindent 4)。template 是 Go 原生指令,直接输出内容,不支持管道。因此在需要控制缩进时必须使用 include。nindent vs indent
nindent N 在文本前添加换行后再缩进 N 个空格,indent N 只缩进不添加前置换行。在 YAML 中 nindent 更常用,确保标签块在正确的缩进层级。实战:构建完整 Deployment 模板
# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
namespace: {{ .Release.Namespace }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
protocol: TCP
{{- with .Values.resources }}
resources:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.envVars }}
env:
{{- range .Values.envVars }}
- name: {{ .name | quote }}
value: {{ .value | quote }}
{{- end }}
{{- end }}
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
常用模板函数速查
| 函数 | 用途 | 示例 |
|---|---|---|
default | 提供默认值 | {{ .Values.tag | default "latest" }} |
required | 必填参数,缺失时报错 | {{ required "image.repository is required" .Values.image.repository }} |
quote | 加双引号 | {{ .Values.version | quote }} |
toYaml | 结构体转 YAML 字符串 | {{ toYaml .Values.resources }} |
toJson | 结构体转 JSON 字符串 | {{ toJson .Values.config }} |
nindent | 添加换行+缩进 | {{ toYaml .Values.labels | nindent 4 }} |
trunc | 截断字符串 | {{ .Values.name | trunc 63 }} |
trimSuffix | 去尾字符 | {{ .Values.name | trimSuffix "-" }} |
upper / lower | 大小写转换 | {{ .Values.env | upper }} |
replace | 替换字符串 | {{ .Chart.Version | replace "+" "_" }} |
printf | 格式化字符串 | {{ printf "%s-%s" .Chart.Name .Chart.Version }} |
contains | 子字符串检测 | {{ contains "NodePort" .Values.service.type }} |
sha256sum | 计算 SHA256(常用于配置热重启) | {{ include "myapp.config" . | sha256sum }} |
b64enc | Base64 编码(Secret 用) | {{ .Values.password | b64enc }} |
lookup | 从集群查询现有资源 | {{ (lookup "v1" "Secret" .Release.Namespace "my-secret").data }} |
本章小结
Go 模板语法是 Helm 的核心。掌握 {{- -}} 空白控制、内置对象(.Values/.Release/.Chart)、if/range/with 控制流和 define/include 模板复用后,你就能编写任意复杂的 Chart 模板。记住:include 优于 template(支持管道),toYaml | nindent 是处理复杂结构(资源限制、节点选择器)的标准写法。