管道与函数
quote 函数实现:从.Values 中读取的值变成字符串,可以使用
[root@master ~]# vi templates/deployment.yaml
app: {{ quote .Values.label.app }} #
[root@master ~]# helm install --dry-run test3 m
app: "nginx"
default 函数,该函数允许在模板中指定默认值,以防止该值被忽略掉。
[root@master ~]# cat templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
...
- name: {{ .Values.name | default "nginx" }}
其他函数:
缩进:{{ .Values.resources | indent 12 }}
大写:{{ upper .Values.resources }}
首字母大写:{{ title .Values.resources }}
流程控制
流程控制是为模板提供了一种能力,满足更复杂的数据逻辑处理。
Helm 模板语言提供以下流程控制语句: if/else 条件块 , with 指定范围 , range 循环块
if/else 块是用于在模板中有条件地包含文本块的方法,条件块的基本结构如下:
cat templates/deployment.yaml
...
template:
metadata:
labels:
app: nginx
{{ if eq .Values.devops "k8s" }}
key: value1
{{ else }}
key: value2
{{ end }}
在上面条件语句使用了 eq 运算符判断是否相等,除此之外,还支持 ne、 lt、 gt、 and、 or 等运算符。
[root@master ~]# cat mychart/values.yaml
...
devops: test //这里devops先为test测试
[root@master ~]# helm install --dry-run test3 mychart
...
labels:
app: nginx
key: value2 //将mychart/values.yaml的devops: test改k8s,择取用value1
可以看到渲染出来会有多余的空行,这是因为当模板引擎运行时,会将控制指令删除,
所有之前占的位置也就空白了,需要使用{{- if …}} 的方式消除此空行:
[root@master ~]# cat mychart/templates/deployment.yaml
...
labels:
app: {{.Values.label}}
{{- if eq .Values.devops "k8s" }}
key: value1
{{- else }}
key: value2
{{- end }}
[root@master ~]# helm install --dry-run test3 mychart
...
labels:
app: nginx
key: value1
如果判断为以下几种情况,则为 false,其他所有条件都为真。
一个布尔类型的 false,一个数字 零 ,一个空的字符串 ,一个空的集合( map、 slice、 tuple、 dict、 array)
range
在 Helm 模板语言中,使用 range 关键字来进行循环操作。
[root@master ~]# cat mychart/values.yaml
...
devops: k8s
test:
- 1
- 2
- 3
[root@master ~]# cat mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
test: |
{{- range .Values.test }}
{{ . }}
{{- end }}
[root@master ~]# helm install --dry-run test3 mychart
...
# Source: mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: test3
data:
test: |
1
2
3
with 控制变量作用域
with 语句可以允许将当前范围 .设置为特定的对象,比如我们前面一直使用的 .Values.label,我们可以使用 with 来将范围指向 .Values.label
[root@master ~]# cat mychart/values.yaml
...
nodeSelector:
team: a
gpu: yes
[root@master ~]# cat mychart/templates/deployment.yaml
...
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
team: {{ .team }}
gpu: {{ .gpu }}
{{- end }}
[root@master ~]# helm install --dry-run test3 mychart
spec:
nodeSelector:
team: a
gpu: true
优化后
[root@master ~]# cat mychart/templates/deployment.yaml
...
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
//测试结果跟上面的一样“| nindent 8”,缩进8
变量
在模板中,使用变量的场合不多,但我们将看到如何使用它来简化代码,并更好地利用 with 和 range。
获取数组键值
[root@master ~]# cat mychart/values.yaml
...
env:
NAME: "gateway"
JAVA_OPTS: "-Xmx1G"
[root@master ~]# cat mychart/templates/deployment.yaml
...
env:
{{- range $k,$v := .Values.env }}
- name: {{ $k }}
value: {{ $v | quote }}
{{- end }}
[root@master ~]# helm install --dry-run test3 mychart
...
env:
- name: JAVA_OPTS
value: "-Xmx1G"
- name: NAME
value: "gateway"
上面在 range 循环中使用 k e y 和 key 和 key和value 两个变量来接收后面列表循环的键和值。
with 中不能直接使用内置对象,这里将对象赋值给一个变量解决:
[root@master ~]# cat mychart/templates/deployment.yaml
...
labels:
app: {{.Values.label}}
{{- $releaseName := .Release.Name -}}
{{- with .Values.label }}
release: {{ $releaseName }}
{{- end }}
[root@master ~]# helm install --dry-run test3 mychart
# Source: mychart/templates/deployment.yaml
...
labels:
app: nginx
release: test3
变量的传递 {{ template “define NAME” . }}
_helpers.tpl:放置模板助手的地方,可以在整个 chart 中重复使用
[root@master ~]# helm search repo redis
NAME CHART VERSION APP VERSION DESCRIPTION
aliyun/sensu 0.2.0 Sensu monitoring framework backed by the Redis ...
[root@master ~]# helm fetch aliyun/sensu
[root@master ~]# tar xf sensu-0.2.0.tgz
[root@master sensu]# cat templates/_helpers.tpl
//定义了sensu.name sensu.redis.fullname sensu.fullname,三个变量
{{/* vim: set filetype=mustache: */}}
{{/*
Expand the name of the chart.
*/}}
{{- define "sensu.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
//拼接成 sensu-
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "sensu.redis.fullname" -}}
{{- printf "%s-%s" .Release.Name "redis" | trunc 63 | trimSuffix "-" -}}
//拼接 test2-redis
{{- end -}}
{{/*
Create a default fully qualified app name.
We truncate at 63 chars because some Kubernetes name fields are limited to this (by the DNS naming spec).
*/}}
{{- define "sensu.fullname" -}}
{{- $name := default .Chart.Name .Values.nameOverride -}}
//变量赋值sensu给$name
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" -}}
//%s-%s占位传递,.Release.Name是实例名test2,最后截取到64位(k8s规则),-号拼接,成test2-sensu
{{- end -}}
[root@master ~]# helm install --dry-run test2 sensu
...
# Source: sensu/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: test2-sensu #{{ template "sensu.fullname" . }}
labels:
heritage: "Helm" #{{ .Release.Service | quote }}
release: "test2" #{{ .Release.Name | quote }}
chart: "sensu-0.2.0" #{{ .Chart.Name }}-{{ .Chart.Version }}
spec:
replicas: 1 #{{ .Values.replicaCount }}
selector:
matchLabels:
app: test2-sensu #{{ template "sensu.fullname" . }}
template:
metadata:
labels:
app: test2-sensu #{{ template "sensu.fullname" . }}
release: "test2" # {{ .Release.Name | quote }}
spec:
containers:
- name: server
image: "sstarcher/sensu:0.28" #"{{ .Values.image }}:{{ .Values.imageTag }}"
imagePullPolicy: IfNotPresent #{{ .Values.pullPolicy }}
args:
- server
resources: #{{ toYaml .Values.server.resources | indent 10 }}
requests:
cpu: 100m
memory: 100Mi
env:
- name: API_HOST
value: localhost
- name: API_PORT
value: '4567'
- name: REDIS_HOST
value: test2-redis #{{ template "sensu.redis.fullname" . }}
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: test2-redis #{{ template "sensu.redis.fullname" . }}
key: redis-password
- name: REDIS_DB
value: "0" #{{ .Values.REDIS_DB | quote }}
- name: REDIS_AUTO_RECONNECT
value: "true" # {{ .Values.REDIS_AUTO_RECONNECT | quote }}
- name: REDIS_RECONNECT_ON_ERROR
value: "true" # {{ .Values.REDIS_RECONNECT_ON_ERROR | quote }}
- name: REDIS_PORT
value: "6379" #{{ .Values.REDIS_PORT | quote }}
- name: api
image: "sstarcher/sensu:0.28"
imagePullPolicy: IfNotPresent
args:
- api
resources:
requests:
cpu: 50m
memory: 100Mi
env:
- name: REDIS_HOST
value: test2-redis
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: test2-redis #{{ template "sensu.redis.fullname" . }}
key: redis-password
- name: REDIS_DB
value: "0" #{{ .Values.REDIS_DB | quote }}
- name: REDIS_AUTO_RECONNECT
value: "true" # {{ .Values.REDIS_AUTO_RECONNECT | quote }}
- name: REDIS_RECONNECT_ON_ERROR
value: "true" #{{ .Values.REDIS_RECONNECT_ON_ERROR | quote }}
- name: REDIS_PORT
value: "6379" #{{ .Values.REDIS_PORT | quote }}
ports:
- containerPort: 4567
readinessProbe:
httpGet:
path: /info
port: 4567
initialDelaySeconds: 30
timeoutSeconds: 1
livenessProbe:
httpGet:
path: /info
port: 4567
initialDelaySeconds: 30
timeoutSeconds: 1
...
1. Get the Sensu API URL to visit by running these commands in the same shell:
echo 'API endpoints docs at https://sensuapp.org/docs/0.24/api/health-and-info-api.html'
export POD_NAME=$(kubectl get pods --namespace default -l "app=test2-sensu" -o jsonpath="{.items[0].metadata.name}")
echo http://127.0.0.1:4567/info
kubectl port-forward $POD_NAME 4567:4567