helm2-chart模板指南

1、创建一个模板

helm create mychart          # 创建一个名为mychart的模板
rm -rf mychart/templates/*   # 删除模板目录下的全部内容,方便接下来测试

创建一个没有渲染的模板

  • 创建一个名为 mychart/templates/configmap.yaml的文件
apiVersion: v1
kind: ConfigMap
metadata:
  name: mychart-configmap
data:
  myvalue: "Hello World"
# 安装chart
helm install test-mychart1 ./mychart

# 查看实际加载的模板
helm get manifest test-mychart1

# 卸载chart
helm uninstall test-mychart1

创建一个使用渲染的模板

  • 重新配置mychart/templates/configmap.yaml文件
  • 使用{{ .Release.Name }}构建confimgmap的name
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
# 安装
helm install test-chart2 ./mychart

# 查看渲染后的模板
helm get manifest test-chart2

# 卸载
helm uninstall test-chart2

不安装chart,查看模板渲染效果

  • 使用--dry-run --dubeg,chart将不会安装到kubenetes集群中,只会渲染模板内容到控制台(用于测试)
  • --dry-run可以正常运行,并不能保证chart可以成功安装到Kubernetes
  • 会与k8s集群交互,可以排查API版本不支持、命名空间不存在等问题,适合部署前最终校验。
helm install --debug --dry-run goodly-guppy ./mychart
  • helm template适合快速渲染模板,可以在没有k8s的环境下运行
helm template test-chart ./mychart
  • 只渲染一个文件
helm templage test-chart ./mychart -s path/to/file.yaml

2、模板内置对象

  • 接着上边的例子。在mychart目录下创建test-files。其中放置测试的yaml文件
  • Release、Values、Chart、Files、Capabilities是在模板中访问的顶层对象
  • Values对应values.yaml文件中的数据结构

语法解释

image

示例

configmap.yaml被选然后的输出示例
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{ .Release.Name }}-configmap"
data:
  myvalue: "Hello World"
  Release:
    Release.Namespace: {{ .Release.Namespace }}          # 当前应用的命名空间
    Release.IsUpgrade: {{ .Release.IsUpgrade }}          # 如果当前操作是升级或回滚,该值为true
    Release.IsInstall: {{ .Release.IsInstall }}          # 如果当前操作是安装,该值为true
    Release.Revision: {{ .Release.Revision | quote }}    # 此次修订的版本号。安装时是1,每次升级或回滚都会自增
    Release.Service: {{ .Release.Service }}
  Chart:
    Chart.Name: {{ .Chart.Name }}
    Chart.Version: {{ .Chart.Version }}
  Files:
    Files.Get: |-     # 通过文件名获取文件内容
      {{- $.Files.Get "test-files/config.yaml" | nindent 6}}
    Files.lines: |-   # 逐行读取文件内容的
      {{- range $.Files.Lines "test-files/config.yaml" }}
        {{- . | nindent 6}}
      {{- end }}
    Files.Glob: |-
      {{$root := .}}
      {{- range $path, $bytes := .Files.Glob "**.yaml" -}}
      {{$path}}: |-
        {{- $root.Files.Get $path | nindent 8 }}
      {{end}}
# Capabilities提供关于Kubernetes集群支持功能的信息
  Capabilities:
    Capabilities.APIVersions: {{ .Capabilities.APIVersions | quote }}                            # 是K8S的版本列表
    Capabilities.APIVersions.Has $version: {{ .Capabilities.APIVersions.Has "apps/v1" }}         # 说明集群中的版本 (例如:batch/v1) 或是资源 (例如: apps/v1/Deployment) 是否可用或存在于上面的列表中,可用或存在为true
    Capabilities.KubeVersion: {{ .Capabilities.KubeVersion.Version | quote }}                    # Kubernetes的版本号
    Capabilities.KubeVersion.Version: {{ .Capabilities.KubeVersion.Version }}                    # Kubernetes的版本号
    Capabilities.KubeVersion.Major: {{ .Capabilities.KubeVersion.Major }}                        # Kubernetes的主版本号
    Capabilities.KubeVersion.Minor: {{ .Capabilities.KubeVersion.Minor }}                        # Kubernetes的次版本号
    Capabilities.HelmVersion: {{ .Capabilities.HelmVersion.Version | quote }}                    # 当前Helm的版本号
    Capabilities.HelmVersion.Version: {{ .Capabilities.HelmVersion.Version }}                    # 当前Helm的版本号
    Capabilities.HelmVersion.GitCommit: {{ .Capabilities.HelmVersion.GitCommit | quote }}        # Helm的git sha1值
    Capabilities.HelmVersion.GitTreeState: {{ .Capabilities.HelmVersion.GitTreeState | quote }}  # Helm git树的状态
    Capabilities.HelmVersion.GoVersion: {{ .Capabilities.HelmVersion.GoVersion | quote }}        # 使用的Go编译器版本
# Template包含当前被执行的模板信息
  Template:
    Template.Name: {{ .Template.Name | quote }}            # 当前chart模板的文件路径
    Template.BasePath: {{ .Template.BasePath | quote }}    # 当前chart模板目录的路径

# 这条命令是在mychart目录下执行的
helm template test-chart .

image

image

3、values.yaml文件

values的赋值方式

  • Helm模板提供的内置对象Values其内容来自于多个位置,优先级由低到高分别是
    • chart中的values.yaml文件
    • 如果是子chart,就是父chart中的values.yaml文件
    • 使用-f参数(helm install -f myvalues.yaml ./mychart)传递到 helm install 或 helm upgrade的values文件
    • 使用--set (比如helm install --set foo=bar ./mychart)传递的单个参数

values文件结构化

  • values.yaml文件可以配置单行的内容,例如:hobby: game
  • 也可以包含更多结构化的内容。比如我们可以在values.yaml文件中创建一个favorite项,然后添加一些key
hobby: game
favorite:
  drink: coffee
  food: pizza
  • 模板中使用以下变量进行引用:
hobby: {{ .Values.hobby }}
drink: {{ .Values.favorite.drink }}
food: {{ .Values.favorite.food }}

删除默认的key

  • 假设develop.yaml中有一个httpGet方式的livenessProbe
  • 如果想替换掉httpGet用exec重写活动探针,可以使用--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt]
  • Helm会把默认的key和重写的key合并在一起,从而生成以下YAML:
livenessProbe:
  httpGet:
    path: /user/login
    port: http
  exec:
    command:
    - cat
    - docroot/CHANGELOG.txt
  initialDelaySeconds: 120
  • 因为Kubernetes中不能同时声明多个livenessProbe,从而会应用发布会失败。
  • 为了解决这个问题,Helm可以指定通过设定null来删除livenessProbe.httpGet
helm install test-release \
--set image=my-registry/drupal:0.1.0 \
--set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] \
--set livenessProbe.httpGet=null

4、模板函数

  • Helm 有超过60个可用函数。少部分是Go语言本身的,大部分是Sprig 模板库中的。
  • Srig不是Go的官方库,是K8s/Helm生态的标配扩展库,专门解决Go原生模板函数太少、能力太弱的问题
  • Helm可用的函数在以下链接中查看

更多函数和用法参见模板函数列表

https://helm.sh/zh/docs/chart_template_guide/function_list/

quote函数

  • 将传入的字符串值用双引号包裹起来

upper函数

  • 将传入的字符串大写表示

repeat函数

  • 将传入的字符串重复特定的次数

示例

  • Valuses.yaml
favorite:
  drink: "coffee"
  food: "pizza"
  • configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{.Release.Name }}-configmap
data:
  myvalue: "Hello World"
  drink: {{.Values.favorite.drink | repeat 5 | quote }}
  food: {{.Values.favorite.food | upper | quote }}

image

default函数

  • 在模板中指定一个默认值,当key没有指定值时,使用默认值
  • Values.yaml
favorite:
  drink:
  • configmap.yaml
# 当.Values.favorite.drink 没有指定其值时,drink的值为"tea"
drink: {{.Values.favorite.drink | default "tea" | quote }}

lookup函数

image

  • configmap.yaml
apiVersion: v1
kind: configmap
metadata:
  name: "{{ .Release.Name }}-configmap"
data:
  value: |-
    {{- range $index, $pod := (lookup "v1" "Pod" "calico-system" "").items }}
      {{ $index }}: {{ $pod.metadata.name }}
    {{- end }}

使用with修改变量的作用域

  • . 是对当前作用域的引用,可以使用with来重置。.表示的作用域,作用范围到{{ end }}为止
  • Values.yaml
favorite:
  drink: 
  food: "pizza"
  • configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{.Release.Name }}-configmap"
data:
  myvalue: |-
  {{- with .Values.favorite }}                # - 这行表示将作用域切换为.Values.favorite。默认的作用域是.
  drink: {{.drink | default "tea" | quote }}  # 因为作用域发生了变化,因此不用这样指定.Values.favorite.drink
  food: {{.food | upper | quote }}
  release: {{ $.Release.Name }}               # 因为作用域发生了变化,需要使用$,表示使用默认的作用域。因为作用域发生了变化。这样写会报错release: {{ .Release.Name }}
  {{- end }}

使用range操作循环

  • Values.yaml
favorite:
  drink: coffee
  food: pizza
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
  • configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{ .Release.Name }}-configmap"
data: |-
  {{ with .Values.favorite }}
  drink: {{ .drink | default "tea" | quote }}
  food: {{ .food | upper | quote }}
  toppings: |-
  {{- range $.Values.pizzaToppings }}  # 遍历pizzaToppings列表
    - {{ . | title | quote }}
    {{- end }}
  {{- end }}

image

  • 对于有key和value的数据结构,可以使用range获取key和value。Values.yaml和上个例子相同
  • configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-configmap
data:
  myvalue: "Hello World"
  {{- range $key, $val := .Values.favorite }}
  {{ $key }}: {{ $val | quote }}
  {{- end }}

image

AsConfig 和 AsSecrets

  • AsConfig 和 AsSecrets 是 Helm 3 引入的两个内置函数,用于将字符串或文件内容转换为 ConfigMap 和 Secret 对象的数据格式。简化 ConfigMap 和 Secret 数据的生成
  • 创建测试文件
cd mychart
mkdir conf secrets

# 创建配置文件(用于 AsConfig)
echo -e "app: test\nport: 8080" > conf/app.conf
echo "log_level: info" > conf/log.yaml

# 创建敏感文件(用于 AsSecrets)
echo "db_password=123456" > secrets/db.txt
echo "token=abcdefg123" > secrets/token.key
  • configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{ .Release.Name }}-app-config"
  labels:
    app: test-app
    data:
{{ (.Files.Glob "conf/*").AsConfig | indent 4 }}
  • configmap.yaml渲染后的效果

image

  • secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: {{ .Release.Name }}-app-secret
  labels:
    app: test-app
type: Opaque
data:
{{ (.Files.Glob "secrets/*").AsSecrets | indent 2 }}
  • secret.yaml渲染后的效果

image

b64enc

  • b64nc是Helm内置的Base64编码函数。作用是将字符串或文本内容转为 Base64 编码格式,使其符合 K8s Secret 对值的编码要求。常和 Files.Get 配合使用
  • Base64 是编码不是加密,能通过 echo "ZGJfcGFzc3dvcmQ9MTIzNDU2Cg==" | base64 -d 解码
  • secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: "{{ .Release.Name }}-app-secret"
type: Opaque
token: {{ .Files.Get "secrets/db.txt" | b64enc }}
  • secret.yaml渲染后的效果

image

5、命名模板

使用define生声明模板

  • 模板命名
    • 使用define关键字命名模板
    • 自定义的模板名称以 _ 开头,常用的命名规则是用chart的名字作为模板的前缀: {{ define "mychart.xxxx" }}
  • 模板位置
    • 模板名称是全局的。因此,如果两个模板使用相同名字声明,会使用最后出现的那个。
    • 将模板放在_helpers.tpl文件中,使用helm create mychart命令时templates目录下有_helpers.tpl文件
  • 示例,_helpers.tpl的内容如下
{{- define "mychart.labels" -}}
generator: helm
date: {{ now | htmlDate}}
chart: {{ .Chart.Name }}
version: {{ .Chart.Version }}
{{- end -}}

使用template或include引用模板

  • 注意在template和include尾部的.,它的作用是将上下文传递给模板里的内容,而要传递的就是根上下文。
  • 没有.模板中的.Chart.Name、.Chart.Version将无法被渲染出来
  • 示例,使用template引用模板的configmap.yaml的内容如下
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{ .Release.Name }}-configmap"
  labels:
    {{- include "mychart.labels" . | nindent 4 }}

image

  • 示例,使用include引用模板的configmap.yaml的内容如下
apiVersion: v1
kind: ConfigMap
metadata:
  name: "{{ .Release.Name }}-configmap"
  labels:
    {{ template "mychart.labels" .}}  # 不能向上面的include一样使用 | nindent 4,会报错

6、全局chart值

在子chart中添加值

# 创建子chart
cd mychart/charts
helm create mysubchart
rm -rf mysubchart/templates/*

# 在子chart的values.yaml中添加值
echo "dessert: cake" >> mysubchart/values.yaml
  • mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-cfgmap2
data:
  dessert: {{ .Values.dessert }}
helm template --generate-name mychart/charts/mysubchart

在父chart中添加值

  • 父chart中的值会覆盖子chart中的值
  • 父chart将dessert的值改为 ice cream
cat << EOF >> mychart/values.yaml
mysubchart:
  dessert: ice cream
EOF
  • 再次执行创建子chart的命令,发现dessert的值由cake改为 ice cream
helm template --generate-name mychart/charts/mysubchart

设置全局chart值

  • 使用global关键字,在父chart的values.yaml文件中添加值。父或子chart均可使用
cat << EOF >> mychart/values.yaml
global:
  dessert: cookie
EOF
# mychart/charts/mysubchart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-cfgmap2
data:
  dessert: {{ .Values.global.dessert }}

# mychart/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: {{ .Release.Name }}-cfgmap2
data:
  dessert: {{ .Values.global.dessert }}
  • 执行创建父chart的命令,可以看到父和子chart的值都与global设置的值一致

image

  • 单独执行创建子chart的命令会提示空指针

image

.helmignore文件

  • 排除不想包含在chart中的文件
  • 位于chart的顶级目录中
  • .helmignore文件示例
# 匹配任意文件或目录名字叫.helmignore
.helmignore
# 匹配任意文件或目录名字叫.git
.git
# 匹配任意txt文件
*.txt
# 只匹配目录,名字叫mydir
mydir/
# 只匹配顶级目录中的txt文件
/*.txt
# 只匹配顶级目录中的foo.txt文件
/foo.txt
# 匹配任意文件叫 ab.txt, ac.txt, or ad.txt
a[b-d].txt
# 匹配子目录temp*下的任意文件
*/temp*
*/*/temp*
temp?
# 忽略名称为secret.yaml的文件
secret.yaml

7、调试模板

helm lint

image

  • helm lint会检查mychart中的Chart.yaml。因为在mychart/charts目录下有子chart(mysubchart),在Chart.yaml文件中没有指定依赖,所以会报错
  • 在Chart.yaml文件中添加依赖即可解决
cat << EOF >> Chart.yaml
dependencies:
  - name: mysubchart
EOF
posted @ 2024-05-10 10:14  立勋  阅读(34)  评论(0)    收藏  举报