helm2-chart模板指南
1、创建一个模板
helm create mychart # 创建一个名为mychart的模板
rm -rf mychart/templates/* # 删除模板目录下的全部内容,方便接下来测试
创建一个没有渲染的模板
- 创建一个名为 mychart/templates/configmap.yaml的文件
apiVersion: v1
kind: ConfigMap
metadata:
name: mychart-configmap
data:
myvalue: "Hello World"
# 安装chart
helm install test-mychart1 ./mychart
# 查看实际加载的模板
helm get manifest test-mychart1
# 卸载chart
helm uninstall test-mychart1
创建一个使用渲染的模板
- 重新配置mychart/templates/configmap.yaml文件
- 使用{{ .Release.Name }}构建confimgmap的name
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
# 安装
helm install test-chart2 ./mychart
# 查看渲染后的模板
helm get manifest test-chart2
# 卸载
helm uninstall test-chart2
不安装chart,查看模板渲染效果
- 使用--dry-run --dubeg,chart将不会安装到kubenetes集群中,只会渲染模板内容到控制台(用于测试)
- --dry-run可以正常运行,并不能保证chart可以成功安装到Kubernetes
- 会与k8s集群交互,可以排查API版本不支持、命名空间不存在等问题,适合部署前最终校验。
helm install --debug --dry-run goodly-guppy ./mychart
- helm template适合快速渲染模板,可以在没有k8s的环境下运行
helm template test-chart ./mychart
- 只渲染一个文件
helm templage test-chart ./mychart -s path/to/file.yaml
2、模板内置对象
- 接着上边的例子。在mychart目录下创建test-files。其中放置测试的yaml文件
- Release、Values、Chart、Files、Capabilities是在模板中访问的顶层对象
- Values对应values.yaml文件中的数据结构
语法解释

示例
configmap.yaml被选然后的输出示例
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Release.Name }}-configmap"
data:
myvalue: "Hello World"
Release:
Release.Namespace: {{ .Release.Namespace }} # 当前应用的命名空间
Release.IsUpgrade: {{ .Release.IsUpgrade }} # 如果当前操作是升级或回滚,该值为true
Release.IsInstall: {{ .Release.IsInstall }} # 如果当前操作是安装,该值为true
Release.Revision: {{ .Release.Revision | quote }} # 此次修订的版本号。安装时是1,每次升级或回滚都会自增
Release.Service: {{ .Release.Service }}
Chart:
Chart.Name: {{ .Chart.Name }}
Chart.Version: {{ .Chart.Version }}
Files:
Files.Get: |- # 通过文件名获取文件内容
{{- $.Files.Get "test-files/config.yaml" | nindent 6}}
Files.lines: |- # 逐行读取文件内容的
{{- range $.Files.Lines "test-files/config.yaml" }}
{{- . | nindent 6}}
{{- end }}
Files.Glob: |-
{{$root := .}}
{{- range $path, $bytes := .Files.Glob "**.yaml" -}}
{{$path}}: |-
{{- $root.Files.Get $path | nindent 8 }}
{{end}}
# Capabilities提供关于Kubernetes集群支持功能的信息
Capabilities:
Capabilities.APIVersions: {{ .Capabilities.APIVersions | quote }} # 是K8S的版本列表
Capabilities.APIVersions.Has $version: {{ .Capabilities.APIVersions.Has "apps/v1" }} # 说明集群中的版本 (例如:batch/v1) 或是资源 (例如: apps/v1/Deployment) 是否可用或存在于上面的列表中,可用或存在为true
Capabilities.KubeVersion: {{ .Capabilities.KubeVersion.Version | quote }} # Kubernetes的版本号
Capabilities.KubeVersion.Version: {{ .Capabilities.KubeVersion.Version }} # Kubernetes的版本号
Capabilities.KubeVersion.Major: {{ .Capabilities.KubeVersion.Major }} # Kubernetes的主版本号
Capabilities.KubeVersion.Minor: {{ .Capabilities.KubeVersion.Minor }} # Kubernetes的次版本号
Capabilities.HelmVersion: {{ .Capabilities.HelmVersion.Version | quote }} # 当前Helm的版本号
Capabilities.HelmVersion.Version: {{ .Capabilities.HelmVersion.Version }} # 当前Helm的版本号
Capabilities.HelmVersion.GitCommit: {{ .Capabilities.HelmVersion.GitCommit | quote }} # Helm的git sha1值
Capabilities.HelmVersion.GitTreeState: {{ .Capabilities.HelmVersion.GitTreeState | quote }} # Helm git树的状态
Capabilities.HelmVersion.GoVersion: {{ .Capabilities.HelmVersion.GoVersion | quote }} # 使用的Go编译器版本
# Template包含当前被执行的模板信息
Template:
Template.Name: {{ .Template.Name | quote }} # 当前chart模板的文件路径
Template.BasePath: {{ .Template.BasePath | quote }} # 当前chart模板目录的路径
# 这条命令是在mychart目录下执行的
helm template test-chart .


3、values.yaml文件
values的赋值方式
- Helm模板提供的内置对象Values其内容来自于多个位置,优先级由低到高分别是
- chart中的values.yaml文件
- 如果是子chart,就是父chart中的values.yaml文件
- 使用-f参数(helm install -f myvalues.yaml ./mychart)传递到 helm install 或 helm upgrade的values文件
- 使用--set (比如helm install --set foo=bar ./mychart)传递的单个参数
values文件结构化
- values.yaml文件可以配置单行的内容,例如:hobby: game
- 也可以包含更多结构化的内容。比如我们可以在values.yaml文件中创建一个favorite项,然后添加一些key
hobby: game
favorite:
drink: coffee
food: pizza
- 模板中使用以下变量进行引用:
hobby: {{ .Values.hobby }}
drink: {{ .Values.favorite.drink }}
food: {{ .Values.favorite.food }}
删除默认的key
- 假设develop.yaml中有一个httpGet方式的livenessProbe
- 如果想替换掉httpGet用exec重写活动探针,可以使用--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt]
- Helm会把默认的key和重写的key合并在一起,从而生成以下YAML:
livenessProbe:
httpGet:
path: /user/login
port: http
exec:
command:
- cat
- docroot/CHANGELOG.txt
initialDelaySeconds: 120
- 因为Kubernetes中不能同时声明多个livenessProbe,从而会应用发布会失败。
- 为了解决这个问题,Helm可以指定通过设定null来删除livenessProbe.httpGet
helm install test-release \
--set image=my-registry/drupal:0.1.0 \
--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] \
--set livenessProbe.httpGet=null
4、模板函数
- Helm 有超过60个可用函数。少部分是Go语言本身的,大部分是Sprig 模板库中的。
- Srig不是Go的官方库,是K8s/Helm生态的标配扩展库,专门解决Go原生模板函数太少、能力太弱的问题
- Helm可用的函数在以下链接中查看
- Helm可用的Srig库中的函数 https://masterminds.github.io/sprig/
- Helm可用的Go语言函数 https://pkg.go.dev/text/template
更多函数和用法参见模板函数列表
https://helm.sh/zh/docs/chart_template_guide/function_list/
quote函数
- 将传入的字符串值用双引号包裹起来
upper函数
- 将传入的字符串大写表示
repeat函数
- 将传入的字符串重复特定的次数
示例
- Valuses.yaml
favorite:
drink: "coffee"
food: "pizza"
- configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{.Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{.Values.favorite.drink | repeat 5 | quote }}
food: {{.Values.favorite.food | upper | quote }}

default函数
- 在模板中指定一个默认值,当key没有指定值时,使用默认值
- Values.yaml
favorite:
drink:
- configmap.yaml
# 当.Values.favorite.drink 没有指定其值时,drink的值为"tea"
drink: {{.Values.favorite.drink | default "tea" | quote }}
lookup函数

- configmap.yaml
apiVersion: v1
kind: configmap
metadata:
name: "{{ .Release.Name }}-configmap"
data:
value: |-
{{- range $index, $pod := (lookup "v1" "Pod" "calico-system" "").items }}
{{ $index }}: {{ $pod.metadata.name }}
{{- end }}
使用with修改变量的作用域
- . 是对当前作用域的引用,可以使用with来重置。.表示的作用域,作用范围到{{ end }}为止
- Values.yaml
favorite:
drink:
food: "pizza"
- configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{.Release.Name }}-configmap"
data:
myvalue: |-
{{- with .Values.favorite }} # - 这行表示将作用域切换为.Values.favorite。默认的作用域是.
drink: {{.drink | default "tea" | quote }} # 因为作用域发生了变化,因此不用这样指定.Values.favorite.drink
food: {{.food | upper | quote }}
release: {{ $.Release.Name }} # 因为作用域发生了变化,需要使用$,表示使用默认的作用域。因为作用域发生了变化。这样写会报错release: {{ .Release.Name }}
{{- end }}
使用range操作循环
- Values.yaml
favorite:
drink: coffee
food: pizza
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
- configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Release.Name }}-configmap"
data: |-
{{ with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
toppings: |-
{{- range $.Values.pizzaToppings }} # 遍历pizzaToppings列表
- {{ . | title | quote }}
{{- end }}
{{- end }}

- 对于有key和value的数据结构,可以使用range获取key和value。Values.yaml和上个例子相同
- configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end }}

AsConfig 和 AsSecrets
- AsConfig 和 AsSecrets 是 Helm 3 引入的两个内置函数,用于将字符串或文件内容转换为 ConfigMap 和 Secret 对象的数据格式。简化 ConfigMap 和 Secret 数据的生成
- 创建测试文件
cd mychart
mkdir conf secrets
# 创建配置文件(用于 AsConfig)
echo -e "app: test\nport: 8080" > conf/app.conf
echo "log_level: info" > conf/log.yaml
# 创建敏感文件(用于 AsSecrets)
echo "db_password=123456" > secrets/db.txt
echo "token=abcdefg123" > secrets/token.key
- configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Release.Name }}-app-config"
labels:
app: test-app
data:
{{ (.Files.Glob "conf/*").AsConfig | indent 4 }}
- configmap.yaml渲染后的效果

- secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: {{ .Release.Name }}-app-secret
labels:
app: test-app
type: Opaque
data:
{{ (.Files.Glob "secrets/*").AsSecrets | indent 2 }}
- secret.yaml渲染后的效果

b64enc
- b64nc是Helm内置的Base64编码函数。作用是将字符串或文本内容转为 Base64 编码格式,使其符合 K8s Secret 对值的编码要求。常和 Files.Get 配合使用
- Base64 是编码不是加密,能通过 echo "ZGJfcGFzc3dvcmQ9MTIzNDU2Cg==" | base64 -d 解码
- secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: "{{ .Release.Name }}-app-secret"
type: Opaque
token: {{ .Files.Get "secrets/db.txt" | b64enc }}
- secret.yaml渲染后的效果

5、命名模板
使用define生声明模板
- 模板命名
- 使用define关键字命名模板
- 自定义的模板名称以 _ 开头,常用的命名规则是用chart的名字作为模板的前缀: {{ define "mychart.xxxx" }}
- 模板位置
- 模板名称是全局的。因此,如果两个模板使用相同名字声明,会使用最后出现的那个。
- 将模板放在_helpers.tpl文件中,使用helm create mychart命令时templates目录下有_helpers.tpl文件
- 示例,_helpers.tpl的内容如下
{{- define "mychart.labels" -}}
generator: helm
date: {{ now | htmlDate}}
chart: {{ .Chart.Name }}
version: {{ .Chart.Version }}
{{- end -}}
使用template或include引用模板
- 注意在template和include尾部的.,它的作用是将上下文传递给模板里的内容,而要传递的就是根上下文。
- 没有.模板中的.Chart.Name、.Chart.Version将无法被渲染出来
- 示例,使用template引用模板的configmap.yaml的内容如下
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Release.Name }}-configmap"
labels:
{{- include "mychart.labels" . | nindent 4 }}

- 示例,使用include引用模板的configmap.yaml的内容如下
apiVersion: v1
kind: ConfigMap
metadata:
name: "{{ .Release.Name }}-configmap"
labels:
{{ template "mychart.labels" .}} # 不能向上面的include一样使用 | nindent 4,会报错
6、全局chart值
在子chart中添加值
# 创建子chart
cd mychart/charts
helm create mysubchart
rm -rf mysubchart/templates/*
# 在子chart的values.yaml中添加值
echo "dessert: cake" >> mysubchart/values.yaml
- mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cfgmap2
data:
dessert: {{ .Values.dessert }}
helm template --generate-name mychart/charts/mysubchart
在父chart中添加值
- 父chart中的值会覆盖子chart中的值
- 父chart将dessert的值改为 ice cream
cat << EOF >> mychart/values.yaml
mysubchart:
dessert: ice cream
EOF
- 再次执行创建子chart的命令,发现dessert的值由cake改为 ice cream
helm template --generate-name mychart/charts/mysubchart
设置全局chart值
- 使用global关键字,在父chart的values.yaml文件中添加值。父或子chart均可使用
cat << EOF >> mychart/values.yaml
global:
dessert: cookie
EOF
# mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cfgmap2
data:
dessert: {{ .Values.global.dessert }}
# mychart/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-cfgmap2
data:
dessert: {{ .Values.global.dessert }}
- 执行创建父chart的命令,可以看到父和子chart的值都与global设置的值一致

- 单独执行创建子chart的命令会提示空指针

.helmignore文件
- 排除不想包含在chart中的文件
- 位于chart的顶级目录中
- .helmignore文件示例
# 匹配任意文件或目录名字叫.helmignore
.helmignore
# 匹配任意文件或目录名字叫.git
.git
# 匹配任意txt文件
*.txt
# 只匹配目录,名字叫mydir
mydir/
# 只匹配顶级目录中的txt文件
/*.txt
# 只匹配顶级目录中的foo.txt文件
/foo.txt
# 匹配任意文件叫 ab.txt, ac.txt, or ad.txt
a[b-d].txt
# 匹配子目录temp*下的任意文件
*/temp*
*/*/temp*
temp?
# 忽略名称为secret.yaml的文件
secret.yaml
7、调试模板
helm lint

- helm lint会检查mychart中的Chart.yaml。因为在mychart/charts目录下有子chart(mysubchart),在Chart.yaml文件中没有指定依赖,所以会报错
- 在Chart.yaml文件中添加依赖即可解决
cat << EOF >> Chart.yaml
dependencies:
- name: mysubchart
EOF

浙公网安备 33010602011771号