Skip to content

1. Helm流程控制

1.1 运算符

运算符作用
eq等于(equal to)
ne不等于(not equal to)
lt小于(less than)
le小于等于(less than or equal to)
gt大于(greater than)
ge大于等于(greater than or equal to)

1.2 if/else 条件块

  • 语法

image-20240709172058586

如果值为如下情况,则if条件评估为 false

bash
一个布尔型的假

一个数字零

一个空的字符串

一个 nil(空或 null)

一个空的集合(map,slice,tuple,dict,array)
一个布尔型的假

一个数字零

一个空的字符串

一个 nil(空或 null)

一个空的集合(map,slice,tuple,dict,array)

例子:

image-20240709172126263

上面配置是基于同一个pod 部署两个容器,一个是应用一个是nginx 的配置的通用模板。 也就是说默认是关闭nginx 配置的,如果启用可以通过--set nginx.enabled=true 方式。

💡 说明

当模板引擎运行时,它会删除 image-20240709173149693 中的内容,但保留其余空白,如下方式删除空行

image-20240709172340334 花括号里面的中横行“-” 的用途是清除helm 渲染后的yml 文件里面的空行,由于像if 判断这些语句不是k8s里面yml 文件里的配置信息,所以渲染后的yml 文件中if 等语句的位置会产生空行,所以加上“-”就会清除空行

谨慎使用:如: -}} ,这将会把如上的结果生成在同一行,因为它消除了两边的换行符.

1.3 with 指定范围

  • 定义

with作用域,用来控制变量范围。回想一下,.是对 当前作用域 的引用。因此 .Values就是告诉模板在当前作用域查找Values对象。

with语句块内不能再 .Release.Name对象,否则报错

  • 语法
{{ with PIPELINE }}
  # restricted scope
{{ end }}
{{ with PIPELINE }}
  # restricted scope
{{ end }}
  • 案例
yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
{{- with .Values.favorite}}
drink: {{.drink | default "tea" | quote}}
food: {{.food | upper | quote}}
{{- end}}

注意,现在我们可以引用 .drink 和 .food 无需对其进行限定。这是因为该 with 声明设置 . 为指向 .Values.favorite。在 {{end}} 后 . 复位其先前的范围。


但是请注意!在受限范围内,此时将无法从父范围访问其他对象。例如,下面会报错:
{{- with .Values.favorite}}
drink: {{.drink | default "tea" | quote}}
food: {{.food | upper | quote}}
release: {{.Release.Name}}    #此处报错
{{- end}}

解决方式:
{{- $releaseName := .Release.Name -}}      #在with区域外定义要引入的值,在里面再通过变量引入
{{- with .Values.favorite}}
drink: {{.drink | default "tea" | quote}}
food: {{.food | upper | quote}}
release: {{ $releaseName }}              #通过定义的变量引入
{{- end}}
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
{{- with .Values.favorite}}
drink: {{.drink | default "tea" | quote}}
food: {{.food | upper | quote}}
{{- end}}

注意,现在我们可以引用 .drink 和 .food 无需对其进行限定。这是因为该 with 声明设置 . 为指向 .Values.favorite。在 {{end}} 后 . 复位其先前的范围。


但是请注意!在受限范围内,此时将无法从父范围访问其他对象。例如,下面会报错:
{{- with .Values.favorite}}
drink: {{.drink | default "tea" | quote}}
food: {{.food | upper | quote}}
release: {{.Release.Name}}    #此处报错
{{- end}}

解决方式:
{{- $releaseName := .Release.Name -}}      #在with区域外定义要引入的值,在里面再通过变量引入
{{- with .Values.favorite}}
drink: {{.drink | default "tea" | quote}}
food: {{.food | upper | quote}}
release: {{ $releaseName }}              #通过定义的变量引入
{{- end}}

1.4 range 循环块

  • 定义

Helm 的模板语言中,遍历集合的方式是使用 range 操作(类似for)

  • 语法
{{ range PIPELINE }}
  # restricted scope
{{ end }}
{{ range PIPELINE }}
  # restricted scope
{{ end }}
  • 案例
yaml
cat values.yaml 
  favorite:
    drink: coffee
    food: pizza
  pizzaToppings:
    - mushrooms
    - cheese
    - peppers
    - onions


将这个列表打印到我们的 ConfigMap 中:
  cat templates/configmap.yaml 
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: {{.Release.Name}}-configmap
    data:
      myvalue: "Hello World"
  {{- with .Values.favorite}}
    drink: {{.drink | default "tea" | quote}}
    food: {{.food | upper | quote}}
  {{- end}}
    toppings: |-                            #因为此处要引入的是多行字符串,所以通过"|-"方式 
  {{- range .Values.pizzaToppings}}
    - {{. | title | quote}}               #"." 就是循环的对象中的单个元素,由此可见range也具有with 一样的功能,可以限定范围。
  {{- end}}



循环自建的元祖

  有时能快速在模板中创建一个列表,然后遍历该列表是很有用的。Helm 模板有一个功能可以使这个变得简单:tuple。
  sizes: |-
  {{- range tuple "small" "medium" "large"}}
  - {{.}}
  {{- end}}
 

 {{/*输出如下*/}}
  sizes: |-
    - small
    - medium
    - large



用于类似列表的对象以同时捕获索引和值:

  toppings: |-
  {{- range $index, $topping := .Values.pizzaToppings}}
  {{$index}}: {{ $topping }}
  {{- end}}

 注意,range 首先是变量,然后是赋值运算符,然后是列表。这将分配整数索引(从零开始)给 $index,值给 $topping。运行它将产生:

 

对于同时具有键和值的数据结构,我们可以使用 range 来获得两者

  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: {{.Release.Name}}-configmap
  data:
    myvalue: "Hello World"
    {{- range $key, $val := .Values.favorite}}
    {{$key}}: {{ $val | quote }}
    {{- end}}

  #favorite 定义在 values.yaml中,如上文所示。
cat values.yaml 
  favorite:
    drink: coffee
    food: pizza
  pizzaToppings:
    - mushrooms
    - cheese
    - peppers
    - onions


将这个列表打印到我们的 ConfigMap 中:
  cat templates/configmap.yaml 
    apiVersion: v1
    kind: ConfigMap
    metadata:
      name: {{.Release.Name}}-configmap
    data:
      myvalue: "Hello World"
  {{- with .Values.favorite}}
    drink: {{.drink | default "tea" | quote}}
    food: {{.food | upper | quote}}
  {{- end}}
    toppings: |-                            #因为此处要引入的是多行字符串,所以通过"|-"方式 
  {{- range .Values.pizzaToppings}}
    - {{. | title | quote}}               #"." 就是循环的对象中的单个元素,由此可见range也具有with 一样的功能,可以限定范围。
  {{- end}}



循环自建的元祖

  有时能快速在模板中创建一个列表,然后遍历该列表是很有用的。Helm 模板有一个功能可以使这个变得简单:tuple。
  sizes: |-
  {{- range tuple "small" "medium" "large"}}
  - {{.}}
  {{- end}}
 

 {{/*输出如下*/}}
  sizes: |-
    - small
    - medium
    - large



用于类似列表的对象以同时捕获索引和值:

  toppings: |-
  {{- range $index, $topping := .Values.pizzaToppings}}
  {{$index}}: {{ $topping }}
  {{- end}}

 注意,range 首先是变量,然后是赋值运算符,然后是列表。这将分配整数索引(从零开始)给 $index,值给 $topping。运行它将产生:

 

对于同时具有键和值的数据结构,我们可以使用 range 来获得两者

  apiVersion: v1
  kind: ConfigMap
  metadata:
    name: {{.Release.Name}}-configmap
  data:
    myvalue: "Hello World"
    {{- range $key, $val := .Values.favorite}}
    {{$key}}: {{ $val | quote }}
    {{- end}}

  #favorite 定义在 values.yaml中,如上文所示。

1.5 变量

  • 定义

Helm模板中,变量是对另一个对象的命名引用。遵循$name变量的格式且指定了一个特殊的赋值运算符::=

变量通常不是 “全局” 的。它们的范围是它们所在的块

  • 案例

这段代码会失败

yaml
{{- with .Values.favorite}}
   drink: {{.drink | default "tea" | quote}}
   food: {{.food | upper | quote}}
   release: {{.Release.Name}}
{{- end}}

Release.Name 不在该 with 块中限制的范围内。解决范围问题的一种方法是将对象分配给可以在不考虑当前范围的情况下访问的变量。
{{- with .Values.favorite}}
   drink: {{.drink | default "tea" | quote}}
   food: {{.food | upper | quote}}
   release: {{.Release.Name}}
{{- end}}

Release.Name 不在该 with 块中限制的范围内。解决范围问题的一种方法是将对象分配给可以在不考虑当前范围的情况下访问的变量。

使用变量重写上面的 Release.Name

yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
{{- $relname := .Release.Name -}}
{{- with .Values.favorite}}
  drink: {{.drink | default "tea" | quote}}
  food: {{.food | upper | quote}}
  release: {{$relname}}
{{- end}}

注意,在我们开始 with 块之前,我们赋值 $relname :=.Release.Name。现在在 with 块内部,$relname 变量仍然指向发布名称。因为变量不受with 范围限制。
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name}}-configmap
data:
  myvalue: "Hello World"
{{- $relname := .Release.Name -}}
{{- with .Values.favorite}}
  drink: {{.drink | default "tea" | quote}}
  food: {{.food | upper | quote}}
  release: {{$relname}}
{{- end}}

注意,在我们开始 with 块之前,我们赋值 $relname :=.Release.Name。现在在 with 块内部,$relname 变量仍然指向发布名称。因为变量不受with 范围限制。

1.6 命名模板

模版

❌ 注意

在命名模板时要注意一个重要的细节:模板名称是全局的。如果声明两个具有相同名称的模板,则最后加载一个模板是起作用的模板。

define定义命名模板

可以在/templates/*.yaml 文件中定义命名模板也可以在/templates/_helpers.tpl 定义

template/include 使用命名模板

include与template 区别

include 是可以替代template 的更高级的用法,可以增加缩进功能。

例如创建一个configmap 它的lable 和 data 下面的数据缩进是不同的,lable 缩进在metadata 下面,所以lable 下面的数据是相比于顶格是缩进四个空格。data 本身就是顶格写的,它下面的数据缩进两个空格即可

define 定义的命名模板内容如果同时引入到lable 和 data 下面,那么相同的内容但是缩进不同,如果直接用template 引入那么就会原模原样引入不缩进而是顶格引入到yaml 中

yaml
这样不符合configmap 的定义语法可能不报错但是不会生效这两部分内容,
即使在模本文件中缩进引用{{- template "mychart.labels" . }},依然不生效,
所以在引入过程中需要增加空格所以include 可以替代template 增加空格,语法为:{{- include "mychart.labels" .| indent 4 }} 数字4表示缩进几个空格
这样不符合configmap 的定义语法可能不报错但是不会生效这两部分内容,
即使在模本文件中缩进引用{{- template "mychart.labels" . }},依然不生效,
所以在引入过程中需要增加空格所以include 可以替代template 增加空格,语法为:{{- include "mychart.labels" .| indent 4 }} 数字4表示缩进几个空格
  • 案例
yaml
cat _helpers.tpl
  {{/* 生成基本的资源配置 */}}
  {{- define "resources" }}
  {{- with .Values.resources}}
  limits:
    cpu: {{ .limits.cpu }}
    memory: {{ .limits.memory }}
  requests:
    cpu: {{ .requests.cpu }}
    memory: {{ .requests.memory }}
   {{- end }}
   {{- end }}

cat templates/deployment.yaml
...
  - name: {{ .Release.Name }}-nginx
    image: {{ .Values.image.repository }}/nginx-qa:{{ .Values.image.tagn }}
    imagePullPolicy: {{ .Values.image.pullPolicy }}
    ports:
    - containerPort: 80
      protocol: TCP
    resources:
    {{- include "resources" .| indent 10 }}            #在此处通过命名模板名字引用
    volumeMounts:
    - name: nginx-config
      mountPath: /etc/nginx/conf.d
    ...
cat _helpers.tpl
  {{/* 生成基本的资源配置 */}}
  {{- define "resources" }}
  {{- with .Values.resources}}
  limits:
    cpu: {{ .limits.cpu }}
    memory: {{ .limits.memory }}
  requests:
    cpu: {{ .requests.cpu }}
    memory: {{ .requests.memory }}
   {{- end }}
   {{- end }}

cat templates/deployment.yaml
...
  - name: {{ .Release.Name }}-nginx
    image: {{ .Values.image.repository }}/nginx-qa:{{ .Values.image.tagn }}
    imagePullPolicy: {{ .Values.image.pullPolicy }}
    ports:
    - containerPort: 80
      protocol: TCP
    resources:
    {{- include "resources" .| indent 10 }}            #在此处通过命名模板名字引用
    volumeMounts:
    - name: nginx-config
      mountPath: /etc/nginx/conf.d
    ...

1.7 模板中"-"

yaml
示例一
...
name: {{- Values.name -}} #话括号里面的横线左边的会删除括号左边的空格,右边的会删除右边的空格,在此处一般不加这俩“-”
...
示例二
...
{{-if Values.nginx.enable }} #此处作用就是删除if 和 end 逻辑语句所占的空行,因为这些流程控制语句不会渲染成实际的yaml 配置,默认保留空行再yaml 文件中,所以需要用“-”删除
...
{{- end }}
...
示例一
...
name: {{- Values.name -}} #话括号里面的横线左边的会删除括号左边的空格,右边的会删除右边的空格,在此处一般不加这俩“-”
...
示例二
...
{{-if Values.nginx.enable }} #此处作用就是删除if 和 end 逻辑语句所占的空行,因为这些流程控制语句不会渲染成实际的yaml 配置,默认保留空行再yaml 文件中,所以需要用“-”删除
...
{{- end }}
...

1.8 调试

Helm也提供了--dry-run --debug调试参数,帮助验证模板正确性。在执行helm install时候带上这两个参数就可以把对应的values值和渲染的资源清单打印出来,而不会真正的去部署一个release

bash
helm install web --dry-run /root/mychart
helm install web --dry-run /root/mychart