【问题标题】:Can kubernetes-helm templates use variables?kubernetes-helm 模板可以使用变量吗?
【发布时间】:2017-08-07 00:14:45
【问题描述】:

我有一个 k8s 资源的通用模板,我想将它扩展 n 次(如果你好奇,我可以创建一个 mongo 集群的 n 个成员,并且他们正在使用 statefulset 资源,以便每个成员都有一个稳定的网络名称)。

显然我每次循环都需要不同的值。我正在循环由 Sprig“直到”函数生成的一系列索引。但是循环的 $index 没有在“。”中设置。命名空间。所以我无法在我的 _helpers.tpl 文件中引用我定义的模板中的当前迭代。

这是一个带有完整 k8s 资源 yaml 的示例模板(我是其中大部分的缩写):

{{- define "mytest" -}} 
---
apiVersion: apps/v1beta1
kind: StatefulSet
  abbreviated...
  containers:
  - name: mongod-$index
  abbreviated...
{{- end -}}

来电者:

{{ range $index, $e := until .Values.mongod_count }}
    {{include "mytest" .}}
{{ end}}

我刚刚得到:未定义的变量“$index”

我也尝试过使用块,例如在我的(调用者)模板中:

{{ $foo := "somevalue" }}
{{ define "my_extra_labels" }} bla {{ .Values.test }}_{{$foo}}{{end}}
{{ template "mytest" . }}

这在我的 _helpers.tpl 中

{{/* Test stuff */}} 
{{- define "mytest" -}}
hello: world_how_are_{{ block "my_extra_labels" . }}{{ end }}
{{- end -}} 

变量 $foo 未在“define”主体中定义。

这个模板作用域感觉非常受限制,以至于我现在看不出如何使用它来解决我当前的情况。

有没有办法将变量推入“。”命名空间?如果是这样(我的手指交叉)有没有办法以某种方式合并命名空间,以便我仍然可以访问 .Values 和 .Chart 变量?

【问题讨论】:

    标签: kubernetes-helm


    【解决方案1】:

    helm 中的模板无法访问变量。但是,传递给模板的上下文是字典。 sprig 库可从 Go 模板中访问,并可用于操作字典。

    采用这个简化的模板:

    {{- define "mytest" -}} 
      - name: mongod-{{ .index }}
    {{- end -}}
    

    您现在可以将此模板称为示例:

    {{ range $index := until 5 }}
      {{- $p := dict "index" $index }}
      {{include "mytest" $p}}
    {{- end -}}
    

    这将输出:

    - name: mongod-0
    - name: mongod-1
    - name: mongod-2
    - name: mongod-3
    - name: mongod-4
    

    您还可以将项目添加到现有或当前范围的字典:

    {{- $_ := set . "index" "none" }}
    {{include "mytest" .}}
    

    $_ 用于抑制不需要的输出,因为“set”返回新字典。以上返回:

    - name: mongod-none
    

    添加到字典中的任何值都将在调用之后继续存在。如果您想避免污染现有字典,可以使用以下命令强制进行深层复制:

    {{-  $d := merge (dict) . -}}
    

    添加到“$d”的任何内容都不会存在于“.”中。

    【讨论】:

    • 根据 helm 的当前版本(2018 年 5 月),这仍然是将变量传递给模板的唯一方法吗? @kscoder 我试图找到其他来源,但除了您的帖子之外没有找到任何信息。
    • 请注意,虽然这是一个深度 合并,但它不是深度复制。因此,如果您修改 $d 中继承自 . 的项目,则原始 .可以修改。
    • setmerge 这样的函数记录在哪里?我在golang.org/pkg/text/templatemasterminds.github.io/sprig 中找不到它们。
    • @rcorre。我用于 sprig 的文档在这里:masterminds.github.io/sprig
    • 啊,找到了。它在 dict 函数下:masterminds.github.io/sprig/dicts.html
    【解决方案2】:

    我将把它留在这里,因为有些人可能会尝试为 Helm 中的变量设置静态值以在模板中重新使用它,他们可能会通过标题找到这个 SO 问题。所以,这里有一个技巧:

    更新:

    有更好的方法来做到这一点:

    {{- $_ := set . "appName" "app_name_one"-}}
    
    ---
    apiVersion: v1
    kind: Deployment
    apiVersion: apps/v1beta2
    metadata:
      name: {{ .appName }}
    
    

    旧的建议(不要使用)

    结合@kscoder 建议的上述答案中的语法

        ---
        # values.yml
    
        static_vars:
          app_name_one: app_name_one
          text_to_reuse: text_to_reuse
    
        ---    
        # templates/deployment.yml
    
        # now you don't need to copy-n-paste values, just set them here once
        {{- $text_to_reuse := index .Values "static_vars" "text_to_reuse" -}}
        {{- $app_name := index .Values "static_vars" "app_name_one" -}}
        {{- $_ := set . "app_name" $app_name -}}
    
        apiVersion: v1
        kind: Deployment
        apiVersion: apps/v1beta2
        metadata:
          name: {{ .app_name }}
        spec:
          selector:
            # https://github.com/kubernetes/kubernetes/issues/26202
            matchLabels:
              name: {{ .app_name }}
          template:
            metadata:
              labels:
                name: {{ .app_name }}
                name_alt: {{ $app_name }}
                other_label: {{ $text_to_reuse }}
        # and so on
    

    【讨论】:

    • 有没有办法定义一个可以在多个模板中使用的全局变量?我想随机化一个字符串并在多个 yaml 文件中重用相同的值
    • 我不确定这是否可能(也许)。但我建议将逻辑移至 CI 并将随机字符串作为值传递。
    • 如果该字符串被反映为一个对象(例如秘密) - 它可以完成(因为它创建一次,然后我们可以引用它)。但实际上现在唯一的选择是将其移至 CI
    猜你喜欢
    • 1970-01-01
    • 2020-05-16
    • 2021-11-01
    • 1970-01-01
    • 2019-03-06
    • 2019-10-29
    • 2016-10-31
    • 2020-05-28
    • 2012-07-20
    相关资源
    最近更新 更多