Helm模板与环境变量

huangapple go评论57阅读模式
英文:

Helm template with environment variables

问题

我有以下结构,其中serviceaserviceb中的公共环境变量放在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 }}

serviceavalues.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及其值在serviceavalues.yaml中不存在,因为它仅在commonvalues.yaml中存在。如果我在serviceavalues.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

Helm模板与环境变量

Below is the content of _helpers.tpl of common

{{/* servicea/templates/_helpers.tpl */}}
{{- define &quot;servicea.env&quot; }}
 - 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: &quot;servicea&quot;
      env:
        - name: role
          value: role
{{ include &quot;servicea.env&quot; . | 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 &quot;servicea.env&quot; ., 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 &quot;servicea.env&quot; }}
{{- $spring := .Values.spring | default dict }}
{{- $cloud := $spring.cloud | default dict }}
{{- $kubernetes := $cloud.kubernetes | default dict }}
 - name: KEY
{{- if hasKey $kubernetes &quot;enabled&quot; }}
   value: {{ $kubernetes.enabled | toString | quote }}
{{- else }}
   value: &quot;true&quot;
{{- 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.

huangapple
  • 本文由 发表于 2023年5月28日 01:37:41
  • 转载请务必保留本文链接:https://go.coder-hub.com/76348219.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定