英文:
Helm template with environment variables
问题
我有以下结构,其中servicea
和serviceb
中的公共环境变量放在common文件夹的_helpers.tpl
中
以下是common的_helpers.tpl
的内容
{{/* servicea/templates/_helpers.tpl */}}
{{- define "servicea.env" }}
- name: KEY
value: {{ .Values.spring.cloud.kubernetes.enabled }}
- name: OTHER
value: test
{{ end -}}
以及其values.yaml
如下:
spring:
cloud:
kubernetes:
enabled: true
例如,在servicea
中,如果我需要包含公共环境变量,我会按以下方式操作:
containers:
- name: "servicea"
env:
- name: role
value: role
{{ include "servicea.env" . | indent 12 }}
在servicea
的values.yaml
中,它们如下列出:
servicea:
replicaCount: 1
和dev-values.yaml
如下:
servicea:
replicaCount: 2
serviceb:
replicaCount: 2
现在我面临的问题是,当我运行helm template
生成清单时,它给我一个错误Error: template: <.Values.spring.cloud.kubernetes.enabled>: nil pointer evaluating interface {}。
我可以理解,当它尝试在本地运行模板时,属性spring.cloud.kubernetes.enabled
及其值在servicea
的values.yaml
中不存在,因为它仅在common
的values.yaml
中存在。如果我在servicea
的values.yaml
中添加属性spring.cloud.kubernetes.enabled
,它就能正常工作。但是我不想这样做,因为我不想在所有服务中重复这个属性。是否有一个函数可以“执行模板,然后在执行后导入它”?
谢谢。
英文:
I have a structure as per below whereby common environment variables across servicea
and serviceb
are placed in _helpers.tpl
in the common folder
Below is the content of _helpers.tpl
of common
{{/* servicea/templates/_helpers.tpl */}}
{{- define "servicea.env" }}
- name: KEY
value: {{ .Values.spring.cloud.kubernetes.enabled }}
- name: OTHER
value: test
{{ end -}}
and its values.yaml
as per below:
spring:
cloud:
kubernetes:
enabled: true
for example in servicea
, if I need to include the common env variables, I will do as per below:
containers:
- name: "servicea"
env:
- name: role
value: role
{{ include "servicea.env" . | indent 12 }}
In the values.yaml
of servicea
, they are listed as below:
servicea:
replicaCount: 1
and the dev-values.yaml
as per below:
servicea:
replicaCount: 2
serviceb:
replicaCount: 2
Now the issue I am facing is that when I run helm template to generate the manifests, it is giving me the error Error: template: <.Values.spring.cloud.kubernetes.enabled>: nil pointer evaluating interface {}.
I can understand that when it is trying to run the template locally, the property spring.cloud.kubernetes.enabled and its value are not present in the values.yaml of servicea as it is only present in the values.yaml of common. If I add the property spring.cloud.kubernetes.enabled in values.yaml of servicea, it works fine. But I do not want as I do not want to repeat the property across all services. Is there a function that "execute the template and then import it after the execution"?
Thank you.
答案1
得分: 1
如果您从其他(依赖)图表中调用命名模板,它仍然在父图表的上下文中运行,并查看 parent 的 .Values
。在这里没有一种方法可以 "切换到子级";您需要在模板代码中提供默认值。
从机械角度来看:在 servicea.env
内部,您调用 .Values
,但在此上下文中 .
是模板的参数。当您 include "servicea.env" .
时,在该上下文中 .
是服务-A 图表的顶级 Helm 对象,并将其作为参数传递。在这个过程中,.Values
的定义从未更改为通用图表的值。
(我甚至不确定父图表是否能够看到通用图表中的默认值;我认为例如 .Values.common.spring
只会看到父图表的 values.yaml
和部署时配置中的内容,而不会看到 common/values.yaml
中的内容。您也无法使用 .Files
访问这些文件。)
与其在通用图表的 values.yaml
中包含此默认配置,您需要将其包含在代码中。在这里,您需要考虑这些配置可能根本不存在的可能性;如果没有 .Values.spring
,那么您需要提供一个默认的空 dict
,以便在更深层级上继续工作的查找仍然有效。我可能会这样写:
{{- define "servicea.env" }}
{{- $spring := .Values.spring | default dict }}
{{- $cloud := $spring.cloud | default dict }}
{{- $kubernetes := $cloud.kubernetes | default dict }}
- name: KEY
{{- if hasKey $kubernetes "enabled" }}
value: {{ $kubernetes.enabled | toString | quote }}
{{- else }}
value: "true"
{{- end }}
{{- end }}
您可以考虑使用更浅的值结构,而不是在这里复制 Spring 的配置。如果这是设置 Spring 环境变量 SPRING_CLOUD_KUBERNETES_ENABLED
,您可以始终强制启用它,除非您有特定的需求需要有时禁用它。
英文:
If you call a named template from an other (dependency) chart, it still runs in the parent chart's context, and sees the parent's .Values
. There's not a way to "switch into the child" here; you need to provide the defaults in the template code itself.
Mechanically: inside servicea.env
you call .Values
, but in this context .
is the parameter to the template. When you include "servicea.env" .
, in that context .
is the top-level Helm object for the service-A chart, and you're passing that as the parameter. There's never a point where the definition of .Values
changes to the common-chart values.
(I'm not even sure it's possible for the parent chart to see the default values in the common chart; I think e.g. .Values.common.spring
will only see what's in the parent chart's values.yaml
and deploy-time configuration, but not what's in common/values.yaml
. You also can't access these files using .Files
.)
Instead of including this default configuration in the common chart's values.yaml
you need to include it in code. Here you need to account for the possibility that none of this configuration will exist at all; if there isn't a .Values.spring
then you need to provide a default
empty dict
instead so lookups at deeper levels continue to work. I'd probably write this as:
{{- define "servicea.env" }}
{{- $spring := .Values.spring | default dict }}
{{- $cloud := $spring.cloud | default dict }}
{{- $kubernetes := $cloud.kubernetes | default dict }}
- name: KEY
{{- if hasKey $kubernetes "enabled" }}
value: {{ $kubernetes.enabled | toString | quote }}
{{- else }}
value: "true"
{{- end }}
{{- end }}
You might consider using a shallower values structure, rather than replicating Spring's configuration here. If this is setting the Spring environment variable SPRING_CLOUD_KUBERNETES_ENABLED
you might just always force it on, unless you have a specific need to disable it sometimes.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论