- 官方文档: 命名模板
命名模板
此时需要越过模板,开始学习其他内容了、该部分我们会看到如何在一个文件中定义命名模板,并在其他地方使用。
命名模板仅仅是是在文件内部定义的模板,并使用了一个名字。有时候被称作为一个部分,或者一个子模板。
在 流控制 部分,我们介绍了三种声明和管理模板的方法: define, template 和 block。在这里,我们将使用这三种操作并介绍一种特殊用途的 include 方法,类似于 template 方法。
创建 命名模板 时要记住一个重要细节:模板名称是全局的。如果您想声明两个相同名称的模板,哪个最后加载就使用哪个。 因为在子 chart 中的模板和顶层模板一起编译,命名时要注意 chart 特定名称。
一个常见的命名惯例是用 chart 的名称作为模板前缀,如: {{ define "mychart.labels" }}。使用特定 chart 名称作为前缀可以避免可能因为两个不同 chart 使用了相同名称的模板而引起的冲突。
局部的和 _ 文件
目前为止,我们已经使用了单个文件,且单个文件中包含了单个模板。但Helm的模板语言允许你创建命名的嵌入式模板,这样就可以在其他位置按名称访问。
在编写模板细节之前,文件的命名惯例需要注意:
- templates/目录中的大多数文件被视为 kubernetes 清单文件;
- NOTES.txt是个例外
- 命名以下划线 (_) 开始的文件则假定没有包含 kubernetes 清单内容。这些文件不会被渲染为 kubernetes 对象定义,但在其他 chart 模板中都可用。
这些文件用来存储局部和辅助对象,实际上当我们第一次创建 mychart 时,会看到一个名为 _helpers.tpl 的文件,这个文件是模板局部的默认位置。
使用 define 和 template 声明和使用模板
define 操作允许我们在模板文件中创建一个命名模板,语法如下:
| 1 | {{ define "MY.NAME" }} | 
比如我们可以定义一个模板封装 kubernetes 的标签
| 1 | {{- define "mychart.labels" }} | 
- 现在我们将模板嵌入到已有的 configmap.yaml 文件中,然后使用 template 包含进来: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16- {{- define "mychart.labels" }} 
 labels:
 generator: helm
 date: {{ now | htmlDate }}
 {{- end }}
 apiVersion: v1
 kind: ConfigMap
 metadata:
 name: {{ .Release.Name }}-configmap
 {{- template "mychart.labels" }}
 data:
 myvalue: "Hello World"
 {{- range $key, $val := .Values.favorite }}
 {{ $key }}: {{ $var | quote }}
 {{- end }}
- 当模板引擎读取该文件时,它会存储 - mychart1.labels的引用,直到 template “mychart1.labels” 被调用。然后会按行渲染模板,因此结果类似这样:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- # Source: mychart/templates/configmap.yaml 
 apiVersion: v1
 kind: ConfigMap
 metadata:
 name: mychart-configmap
 labels:
 generator: helm
 date: 2021-11-18
 data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"- 注意: - define不会有输出,除非像本例一样使用 template 调用它。
- 按照惯例,Helm chart 将这些模板放置在局部文件中,一般是 - _helpers.tpl。把这个方法移到那里。- 1 
 2
 3
 4
 5
 6- {{/* Generator basic labels */}} 
 {{- define "mychart.labels" }}
 labels:
 generator: helm
 date: {{ now | htmlDate }}
 {{- end }}
- 尽管这个定义是在 _helpers.tpl 文件中,但是仍然能访问 - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10- apiVersion: v1 
 kind: ConfigMap
 metadata:
 name: {{ .Release.Name }}-configmap
 {{- template "mychart.labels" }}
 data:
 myvalue: "Hello World"
 {{- range $key, $val := .Values.favorite }}
 {{ $key }}: {{ $val | quote }}
 {{- end }}
如上所述,模板名称是全局的。因此,如果两个模板使用相同名字声明,会使用最后出现的那个。由于 子chart 中的模板和顶层模板一起编译,最好用 chart 特定名称命名你的模板。常用的命名规则是用chart的名字作为模板的前缀: {{ define "mychart.labels" }}。
设置模板范围
在上面定义的模板中,我们没有使用任何对象,仅仅使用了方法。
- 修改定义好的模板让其包含 chart 名称和版本号: - 1 
 2
 3
 4
 5
 6
 7
 8- {{/* Generator basic labels */}} 
 {{- define "mychart.labels" }}
 labels:
 generator: helm
 date: {{ now | htmlDate }}
 chart: {{ .Chart.Name }}
 version: {{ .Chart.Version }}
 {{- end }}- 如果渲染这个模板,会得到以下错误 - 1 - Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: [unknown object type "nil" in ConfigMap.metadata.labels.chart, unknown object type "nil" in ConfigMap.metadata.labels.version] 
- 要查看渲染了什么,可以使用 - --disable-openapi-validation参数重新执行- helm install mychart --dry-run --disable-openapi-validation .结果并不是我们想要的- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- # Source: mychart/templates/configmap.yaml 
 apiVersion: v1
 kind: ConfigMap
 metadata:
 name: mychart-configmap
 labels:
 generator: helm
 date: 2021-11-18
 chart:
 version:
 data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"- 名字和版本号怎么了?没有出现在我们定义的模板中。当一个(使用define创建的)命名模板被渲染时,会接收被 template 调用传入的内容。在我们的示例中,包含模板如下: - 1 - {{- template "mychart.labels" }} - 没有内容传入,所以模板中无法用 . 访问任何内容。但这个很容易解决,只需要传递一个范围给模板: - 1 
 2
 3
 4
 5- apiVersion: v1 
 kind: ConfigMap
 metadata:
 name: {{ .Release.Name }}-configmap
 {{- template "mychart.labels" . }}- 注意这个在 template 调用末尾传入的 - .,我们可以简单传入- .Values或- .Values.favorite或其他需要的范围。但一定要是顶层范围。
- 现在我们可以用 - helm install --dry-run --debug mychart .执行模板,然后得到:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- # Source: mychart/templates/configmap.yaml 
 apiVersion: v1
 kind: ConfigMap
 metadata:
 name: mychart-configmap
 labels:
 generator: helm
 date: 2021-11-18
 chart: mychart
 version: 0.1.0
 data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"
现在 {{ .Chart.Name }} 解析为 mychart,{{ .Chart.Version }} 解析为 0.1.0。
使用 include 方法
- 假设定义了一个简单模板如下: - 1 
 2
 3
 4- {{- define "mychart.app" -}} 
 app_name: {{ .Chart.Name }}
 app_version: "{{ .Chart.Version }}"
 {{- end -}}
- 现在假设我想把这个插入到模板的 - labels:部分和- data:部分:- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- apiVersion: v1 
 kind: ConfigMap
 metadata:
 name: {{ .Release.Name }}-configmap
 labels:
 {{ template "mychart.app" . }}
 data:
 myvalue: "Hello World"
 {{- range $key, $val := .Values.favorite }}
 {{ $key }}: {{ $val | quote }}
 {{- end }}
 {{ template "mychart.app" . }}- 如果渲染这个,会得到以下错误 - 1 - Error: unable to build kubernetes objects from release manifest: error validating "": error validating data: [ValidationError(ConfigMap): unknown field "app_name" in io.k8s.api.core.v1.ConfigMap, ValidationError(ConfigMap): unknown field "app_version" in io.k8s.api.core.v1.ConfigMap] 
- 要查看渲染了什么,可以用 - --disable-openapi-validation参数重新执行- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- # Source: mychart/templates/configmap.yaml 
 apiVersion: v1
 kind: ConfigMap
 metadata:
 name: measly-whippet-configmap
 labels:
 app_name: mychart
 app_version: "0.1.0"
 data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"
 app_name: mychart
 app_version: "0.1.0"- 注意两处的 app_version 缩进都不对,为啥?因为被替换的模板中文本是左对齐的。由于 template 是一个行为,不是方法,无法将 template 调用的输出传给其他方法,数据只是简单地按行插入。为了处理这个问题,Helm 提供了一个 template 的可选项,可以将模板内容导入当前管道,然后传递给管道中的其他方法。 
- 下面这个示例,使用 indent 正确地缩进了 mychart.app 模板: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- apiVersion: v1 
 kind: ConfigMap
 metadata:
 name: {{ .Release.Name }}-configmap
 labels:
 {{ include "mychart.app" . | indent 4 }}
 data:
 myvalue: "Hello World"
 {{- range $key, $val := .Values.favorite }}
 {{ $key }}: {{ $val | quote }}
 {{- end }}
 {{ include "mychart.app" . | indent 2 }}- 注意: 使用 - include方法时。花括号必须从最左边开始写,否则渲染会报错,如下- 1 - Error: YAML parse error on mychart/templates/configmap.yaml: error converting YAML to JSON: yaml: line 11: did not find expected key - nindent则不需要,但是- nindent需要在左侧大括号处添加- -,否则会多一个空行。上面的代码改写如下- 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12- apiVersion: v1 
 kind: ConfigMap
 metadata:
 name: {{ .Release.Name }}-configmap
 labels:
 {{- include "mychart.app" . | nindent 4 }}
 data:
 myvalue: "Hello World"
 {{- range $key, $val := .Values.favorite }}
 {{ $key }}: {{ $val | quote }}
 {{- end }}
 {{- include "mychart.app" . | nindent 2 }}
- 现在生成的YAML每一部分都可以正确缩进了: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- # Source: mychart/templates/configmap.yaml 
 apiVersion: v1
 kind: ConfigMap
 metadata:
 name: mychart-configmap
 labels:
 app_name: mychart
 app_version: "0.1.0"
 data:
 myvalue: "Hello World"
 drink: "coffee"
 food: "pizza"
 app_name: mychart
 app_version: "0.1.0"- Helm 模板中使用 - include而不是- template被认为是更好的方式 只是为了更好地处理 YAML 文档的输出格式。
 
		