一个 Helm .tpl 文件可以包含多个 YAML 文档,用 --- 文档开头分隔符分隔。此外,您可以使用所有标准 Go text/template 功能,包括其循环结构。
这意味着您可以编写这样的模板:
{{- $top := . -}}
{{- range .Values.names -}}
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ . }}
spec:
...
template:
spec:
containers:
- env:
- name: {{ $top.Values.env1 }}
value: "yes"
---
apiVersion: v1
kind: Service
metadata:
name: {{ . }}
spec: { ... }
{{ end -}}
这首先是保存当前上下文;由于range 将当前模板默认上下文. 重置为迭代器值,我们需要记住它的当前值是什么。然后我们遍历值文件中列表中的每个值。 (Spriglist 函数可以在模板中创建列表。)对于每个项目,我们创建一个部署和一个服务,每个项目都以 --- 开头。当我们需要当前名称时,它是.;当我们需要 Helm 值中的某些内容时,我们需要在 $top.Values 中明确查找。
另一种可能的方法是为部署和服务编写单独的模板,然后让文件调用它们中的每一个。从技术上讲,模板只接受一个参数,但您可以使用list 和index 将那个参数作为一个列表。
{{/* _deployment.tpl */}}
{{- define "deployment" -}}
{{- $name := index 0 . -}}
{{- $top := index 1 . -}}
---
apiVersion: apps/v1
kind: Deployment
...
name: {{ $name }}
...
name: {{ $top.Values.env1 }}
...
{{ end -}}
{{/* aa1.yaml */}}
{{- template "deployment" (list "aa1" .) -}}
{{- template "service" (list "aa1" .) -}}
这几乎可以变得任意复杂(您可以根据当前对象名称设置条件;您可以使用模板index 函数在值对象中查找值;等等)。 helm template 将做一些验证并将渲染的模板写入标准输出,而不调用 Kubernetes,这有助于观察它,并且可以作为自动化测试的基础。
文本/模板“继承”功能(使用例如 block)在这里不是很好的匹配。 (*text/template.Template).Parse 的文档指出,如果多次调用 Parse,最后找到的 define 将获胜,这为您提供了一个空间来放置 Parse 一个带有占位符 block 的基本模板,然后是 Parse a重新定义的精致模板。 Helm 并没有真正使用这个功能。虽然它将所有 YAML 和支持模板文件加载到同一个模板实例中,但它会单独渲染所有顶级文件,而不是渲染一些允许覆盖的根模板。