Akemi

Helm定义规范与模板全解析

2025/01/16

众所周知helm chart中有几个文件:
Chart.yaml图表文件
template资源文件
Values.yaml变量文件
_helpers.tpl模板函数文件

定义规范

定义规范就是“官方推荐的”,默认自带的东西

使用helm create创建出来的chart就是这些东西都带的

Chart图表文件

这个文件没什么东西

1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: v2
name: qa-data-platform
description: A Helm chart for Kubernetes
version: 0.5.1
appVersion: "1.16.0"

基本上不太重要

需要注意的是 这几个ky是可以被chart.name这样的方式直接引用到
比如这两个version是被_helpers.tpl中的函数引用了

但是不重要,毕竟没有环境的app tag会简单到像是1.16这种,顶多当成一个chart的version

父子chart

如果想要使用父子chart的结构,需要在父Chart.yaml中新增定义依赖项

像是这样

1
2
3
4
5
6
7
8
9
10
11
apiVersion: v2
name: qa-data-platform
description: A Helm chart for Kubernetes
version: 0.5.1
appVersion: "1.16.0"
# 定义依赖项
dependencies:
- name: wangsheng
version: 22.0.0
repository: "@wangsheng" ←这是一个别名,如果真的有helm仓库,也可以直接填url
condition: wangsheng.enabled ←开启依赖项条件,即wangsheng.enabled字段为true

_helpers.tpl助手函数文件

这是最唬人的一个文件,用的是Helm模板语言

官方的规范在里面定义了:应用的名称、pod的labels、selector的labels、sa名称等

要我说直接变量文件里指定一个name,然后这些东西全都用这个name就行,就不需要绕来绕去了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
定义qa-ws应用的名称
{{- define "qa-ws.fullname" -}}
{{- if .Values.ws.fullNameOverride }}
如果有ws.fullNameOverride就用fullNameOverride
{{- .Values.ws.fullNameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
如果没有ws.fullNameOverride,也没有ws.nameOverride,就默认用chart.name
{{- $name := default .Chart.Name .Values.ws.nameOverride }}
{{- if contains $name .Release.Name }}
如果release的name包含了变量name,就用release的name
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
如果不包含,就把$name赋给release并且格式化成字符串后输出
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}

定义sa名称
{{- define "wangsheng-chart.serviceAccountName" -}}
{{- if .Values.serviceAccount.create }} 如果serviceAccount.create字段为true
{{- default (include "wangsheng-chart.fullname" .) .Values.serviceAccount.name }}
并且如果serviceAccount.name没有定义,则默认使用wangsheng-chart.fullname
{{- else }}
如果serviceAccount.create字段为false
{{- default "default" .Values.serviceAccount.name }}
{{- end }}
{{- end }}

Values.yaml变量文件

这个也没什么可讲的,变量文件和模板文件是呼应的,用yaml缩进的方式来定义

helm模板解析

着重解读一下资源文件,也就是yaml部署文件

关键字段介绍

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if 条件判断语句,后面可以接and not这种逻辑运算符,如果为真则渲染域中内容

with 条件判断语句,判断如果该字段存在且不为空,就会渲染这个域中的内容

include 表示引用_helpers.tpl中的一些函数——最后会指向Values文件

toYaml 表示将下面获取到的字段使用yaml格式返回,经常与| nindent一起使用,且经常用于多行内容
| nindent 8 表示向后8个空格,防止yaml的缩进出现错误

default 默认定义,优先级最低,字段不存在或为空时会使用

merge 合并字段,如果B字段存在则合并到A,常与with一起使用

end 宣告结束一个域,因为with和if都会领域展开

模板解读

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
{{- if and .Values.bge .Values.bge.enabled }} 如果bge字段存在且enabled字段为true,则进行部署
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "qa-data-platform-bge.fullname" . }} 在_helpers.tpl中定义的,具体会在定义规范里讲
labels:
{{- include "qa-data-platform-bge.labels" . | nindent 4 }} 见定义规范
spec:
{{- if not .Values.autoscaling.enabled }}
如果autoscaling.enabled不为true,则加载这一段,并获取replicaCount
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "qa-data-platform-bge.selectorLabels" . | nindent 6 }} 见定义规范
template:
metadata:
{{- with .Values.podAnnotations }}
annotations:
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "qa-data-platform-bge.selectorLabels" . | nindent 8 }}见定义规范
spec:
{{- with default .Values.imagePullSecrets .Values.global.common.imagePullSecrets }}
默认使用.Values.imagePullSecrets,如果不存在,则使用.Values.global.common.imagePullSecrets
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "qa-data-platform.serviceAccountName" . }}
securityContext: 获取podSecurityContext并解析为yaml,向后缩进8字符
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }} Chart.yaml中定义
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.bge.image.repository }}:{{ .Values.bge.image.tag | default .Chart.AppVersion }}"
{{- with .Values.bge.image.command }}
command: 如果bge.image中定义了command,就引入command这段,直到end
{{- toYaml . | nindent 12 }}
{{- end }}
imagePullPolicy: {{ .Values.bge.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.bge.service.port }}
protocol: TCP
{{- with .Values.bge.env }}
env: 获取env,并以yaml方式返回
{{- toYaml . | nindent 12 }}
{{- end }}
{{- if .Values.bge.healthCheck.enabled }}
livenessProbe: 健康检查是否开启,如果开启则引入这一段直到end
httpGet:
path: {{ default `/` .Values.bge.healthCheck.healthPath }}
port: http
readinessProbe:
httpGet:
path: {{ default `/` .Values.bge.healthCheck.healthPath }}
port: http
startupProbe:
httpGet:
path: {{ default `/` .Values.bge.healthCheck.healthPath }}
port: http
failureThreshold: 30
periodSeconds: 10
{{- end }}
resources:
以yaml格式获取资源配额
{{- toYaml .Values.bge.resources | nindent 12 }}
{{- with .Values.bge.volumeMounts }}
volumeMounts:
{{- toYaml . | nindent 12 }}
{{- end }}
{{- with merge .Values.global.common.nodeSelector .Values.nodeSelector }}
合并父子变量文件后,判断是否存在,如果存在则引入nodeSelector配置
nodeSelector:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.affinity }}
affinity:
{{- toYaml . | nindent 8 }}
判断是否存在亲和性配置,存在则用yaml引入
{{- end }}
{{- with .Values.global.common.tolerations }}
tolerations:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.bge.volumes }}
volumes:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- with .Values.bge.hostAliases }}
hostAliases:
{{- toYaml . | nindent 8 }}
{{- end }}
{{- end }} 第一行if的域的闭合

引入子Chart与应用

那么现在我要在一个父子结构的chart中新加入一个应用、或者直接加一个子chart,应该遵循什么样的规范?

添加子chart

这个在另外一篇博客中讲了

主要是chart.yaml中依赖项添加与父子变量文件的管理

迁移或添加新应用

根据上面的内容:

1.为新的应用添加应用的名称、pod的labels等内容,在_helpers.tpl中

2.使用合适的变量存放位置,一般推荐在父变量中方便管理

3.对比新旧环境差异,对于节点容忍度、镜像拉取密钥、镜像仓库位置、节点亲和性等需要逐一对比

CATALOG
  1. 1. 定义规范
    1. 1.1. Chart图表文件
    2. 1.2. _helpers.tpl助手函数文件
    3. 1.3. Values.yaml变量文件
    4. 1.4. helm模板解析
  2. 2. 引入子Chart与应用