流程控制——if else

上两节我们了解了模板函数管道,但是有的场景需要添加一些判断逻辑,这些逻辑比仅仅插入字符串要复杂得多。 下面我们将来了解模板语言中提供的控制流程。

Helm 的模板语言提供了以下一些流程控制,为模板作者提供了多样的功能:

  • if/else :条件语句
  • with :指定一个作用域范围
  • range :提供类似于 for each 这样的循环样式

if/else逻辑

if/else 条件判断的基本结构如下所示:

{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

可以看到我们这里判断的是管道而不是一个 values 值。如果值为以下的一些内容,则将管道判断为 false:

  • 布尔 false
  • 数字零
  • 一个空字符串
  • nil(empty 或者 null)
  • 一个空集合(map、slice、tuple、dict、array)

在其他条件下,条件都为真。

动手实验

创建新的chart conditional-learn:

kongpingfan:~/environment/helm $ helm create conditional-learn 
Creating conditional-learn
kongpingfan:~/environment/helm $ cd conditional-learn/

将template目录下除service.yaml外所有文件都删除,删除后的目录结构如下:

kongpingfan:~/environment/helm/conditional-learn $ tree
.
├── charts
├── Chart.yaml
├── templates
│   └── service.yaml
└── values.yaml

修改values.yaml的内容:

replicaCount: 2
image: nginx
orgLabel: payroll

templates/service.yaml内容:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  {{ if .Values.orgLabel }}  
  labels:
    org: {{ .Values.orgLabel }}
  {{ end }}
spec:
  ports:
    - port: 80
      name: http
  selector:
    app: hello-world

如果在values.yaml中设置了orgLabel字段,则生成的service yaml中包括这个字段:

image-20211217200717193

如果在values.yaml中没有设置orgLabel字段,则生成的service yaml中不包含这个字段:

image-20211217200704322

去掉生成的空行

我们注意到,上面渲染生成的yaml中含有两个空行:

image-20211219191105788

这是因为if逻辑本身需要占用一行内容:

image-20211217200737428

如果不想生成空行,则可以使用-标记实现:

image-20211217200842118

此时生成的yaml不会再有空行:

image-20211219191416523


当我们在查看很多平台的helm代码时,经常会看到这种用法,例如 https://github.com/prometheus-community/helm-charts/blob/main/charts/prometheus/templates/server/cm.yaml

image-20211219191737949

else if实验

if/else 条件判断的基本结构如下所示:

{{ if PIPELINE }}
  # Do something
{{ else if OTHER PIPELINE }}
  # Do something else
{{ else }}
  # Default case
{{ end }}

else if部分可以使用多种判断逻辑,例如eq, ne, gt, ge...:

image-20211217200946252

更新service.yaml内容如下:

apiVersion: v1
kind: Service
metadata:
  name: nginx
  {{- if .Values.orgLabel }}
  labels:
    org: {{ .Values.orgLabel }}
  {{- else if eq .Values.orgLabel "hr" }}
  labels:
    org: human resources
  {{- else }}
  labels:
    org: no-org
  {{- end }}
spec:
  ports:
    - port: 80
      name: http
  selector:
    app: hello-world

现在的判断逻辑为:

  • 当orgLabel为hr时,生成org: human resources
  • 当orgLabel为其他值时,生成org: orgLabel
  • 当orgLabel为空时,则生成org: no-org

执行测试:

image-20211219193053405

控制K8S对象是否生成

if逻辑一个常用的功能是控制一个K8s对象是否生成。

把变量抽离到values.yaml中,create参数来进行整体的控制:

serviceAccount:
  create: false

对变量进行判断,当为true时,则渲染出相应的yaml;当为false时,则不进行渲染。

service.yaml

{{- if .Values.serviceAccount.create }}
apiVersion: v1
kind: Service
metadata:
  name: nginx 
spec:
  ports:
    - port: 80
      name: http
  selector:
    app: hello-world
{{- end }}

执行测试:

image-20211219193913235

参考

https://www.qikqiak.com/k8strain/helm/templates/flow/