Helm模板传参时$未指向根上下文 $.Files.Glob报错如何解决
Helm自定义模板传字符串参数时$.Files.Glob报错问题解决
问题现象
在Helm模板中需要遍历.Files.Glob匹配文件,因为要给自定义模板传入glob匹配字符串作为参数,尝试用$.Files.Glob写法回指根上下文,运行时抛出类型错误:
error calling include: template: example/templates/_helpers.tpl:77:29: executing "apiMounts" at <$.Files.Glob>: can't evaluate field Files in type string
出问题的自定义模板定义(_helpers.tpl中):
{{- define "apiMounts" -}} {{- range $path, $_ := $.Files.Glob . }} {{- $name := (base $path) }} - name: specs mountPath: {{ printf "/etc/apis/%s" $name }} subPath: {{ sha256sum $name }} {{- end }} {{- end }}
Deployment资源中调用该模板的原有写法:
volumeMounts: {{- include "apiMounts" "common/**.json" | indent 12 }} {{- include "apiMounts" "v1/**.json" | indent 12 }}
根据Helm的变量规则,$本应始终指向全局根上下文,在range等会重置当前作用域的场景中可用来获取根级对象,但当前场景下$实际指向了传入模板的字符串参数,导致无法调用.Files相关能力,需要在保留按不同匹配字符串传参调用的前提下修复该问题。
故障原因
使用include调用自定义模板时,如果只传入单个字符串、数值等非结构体类型参数,模板的初始根作用域(包括$的默认指向)会被直接重置为传入的这个参数,不再指向Chart的全局根上下文,这是Helm模板作用域规则的固有逻辑,并非$全局指向规则失效。
修复方案
通过字典打包的方式同时传入全局根上下文和自定义匹配参数,既保留灵活传参的能力,也能在模板内正常访问根级的.Files对象,具体修改如下:
- 调整自定义模板的逻辑,从传入的字典中分别解析出全局根对象和glob匹配规则:
{{- define "apiMounts" -}} {{- $root := .root -}} {{- $pattern := .pattern -}} {{- range $path, $_ := $root.Files.Glob $pattern }} {{- $name := (base $path) }} - name: specs mountPath: {{ printf "/etc/apis/%s" $name }} subPath: {{ sha256sum $name }} {{- end }} {{- end }}
- 调整Deployment侧的模板调用写法,在调用位置(此时仍处于Deployment模板的正常作用域,
$正确指向全局根上下文)用dict函数把根对象和匹配字符串打包后传入:
volumeMounts: {{- include "apiMounts" (dict "root" $ "pattern" "common/**.json") | indent 12 }} {{- include "apiMounts" (dict "root" $ "pattern" "v1/**.json") | indent 12 }}
提示:这是Helm自定义模板传参的通用实践,只要模板内需要访问
.Files、.Values、.Release这类根级对象,同时又需要传入自定义参数,都可以用这种字典打包的方式处理,能完全避免作用域错乱问题。
内容的提问来源于stack exchange,提问作者Roddy of the Frozen Peas
相关产品推荐
相关产品推荐

