helm3调试和基础函数if/with/range原创
金蝶云社区-云社区用户26064194
云社区用户26064194
5人赞赏了该文章 127次浏览 未经作者许可,禁止转载编辑于2023年09月27日 15:02:22

在开发一个chart的时候就需要对整个模板进行了解,从使用角度来说,是简单的。但是去开发的时候就需要一定的认识才能够完成一个模板的开发。

而在其中用的较多的就是内置的一些函数,或者说是对象,通常,在helm的模板变量中,以大写开头的都是系统提供的,这由Go的函数约定。

内置对象

release

release:release是作为顶级对象的,与下面的其他不同的是她是内置函数。字面上release是发布的意思,这个对象描述了也是关于发布的一些信息,如下:

  • Release.Name: 顾名思义,release名称

  • Release.Namespace: release名称空间

  • Release.IsUpgrade: release当在升级或者回滚的时候,值为true

  • Release.IsInstall: 如果当前是安装则为true

  • Release.Revision: release版本号,第一次安装是1,升级和回滚都会增加

  • Release.Service: 渲染helm的服务

values.yaml

除此之外,还有values.yaml,这个文件的提供信息是传递到values的,而默认情况下是空的, 所以我们可以进去定制。values.yaml也是用的最多的文件

Chart.yaml

而chart.yaml的内容的值最终是被渲染到helm中的,这些使用helm ls的时候就可以看到,比如name和version等,这些信息可以进行定制值

name: linueaVersion: 1.1.1 复制

渲染后就变成了linuxea-1.1.1

Files

Files可以访问chart的非特殊文件,无法访问模板,提供以下参数

  • Files.Get 或许文件,如: .Files.Get confuig.ini

  • Files.GetBytes 以bytes数组获取文件内函数

  • Files.Glob 用于返回名称给到shell glob模式匹配的文件列表

  • Files.Lines 逐行读取文件的函数,遍历每行内容

  • Files.Assecrets 以Base64编码字符串返回

  • Files.AsConfig 以yaml字典返回

Capabilities

Capabilities用于获取与kubernetes集群支持功能信息的对象

  • Capabilities.APIVersion: 支持的版本

  • Capabilities.APIVersion.Has.version 判断版本或者资源是否可用

  • Capabilities.Kube.Version k8s版本,同时也是Capabilities.Kube 的缩写

  • Capabilities.Kube.Major k8s主版本

  • Capabilities.Kube.Minor k8s次版本

Template

Template包含当前正在执行的模板信息

  • Name: 当前模板文件路径

  • BasePath: 当前chart模板目录的路径

创建chart

使用create就可以进行创建,helm create --help可以看到帮助信息中有想要的参数,直接创建的将会是一个nginx的Deployment的yaml的清单,尝试创建即可

helm create linuxea 复制
[root@linuxea.com /data/helm/mysql]# helm create linuxeaWARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/config
WARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/config
Creating linuxea 复制

目录结构如下

[root@linuxea.com /data/helm/mysql]# tree linuxea/linuxea/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml3 directories, 10 files 复制

values.yaml

实际上我们不需要创建的这些文件,只需要一个目录结构即可,最重要的是values.yaml

这个文件可以使用-f传递给helm install或helm upgrade

helm install -f values.yaml linuxea 复制

再者,使用--set传递各个参数

helm install --set image=123 linuxea 复制

values.yaml的是被用来渲染模板,而--set的值是优先于values.yaml的,因此--set可以覆盖values.yaml的值

既然默认创建的chart并不是期望的,可以删除模板文件和vlaues.yaml的内容,或者手动创建目录结构即可

手动创建目录

mkdir -p  liunuxea/{templates,charts}touch values.yaml liunuxea/touch configmap.yaml liunuxea/templates/configmap.yaml 复制
cat > liunuxea/Chart.yaml << EOFapiVersion: v2name: linuxeadescription: A Helm chart for Kubernetestype: applicationversion: 0.1.0appVersion: "1.16.0"EOF 复制

结构如下

[root@linuxea.com /data/helm/mysql]# tree liunuxea/liunuxea/
├── charts
├── Chart.yaml
├── templates
│   └── configmap.yaml
└── values.yaml2 directories, 3 files 复制

示例1

此时渲染一个参数的值,比如,有一个configmap

apiVersion: v1kind: ConfigMapmetadata:
  name: linuxea-cmp
  labels:
    app: linuxea-cmpdata:
  test:  复制

这里的test是空的,在values.yaml中定义一行

mydata: hi mark, my www.linuxea.com 复制

而现在要想在configmap中使用values.yaml的mydata,就需要使用{{ .Vaules }}来使用

apiVersion: v1kind: ConfigMapmetadata:
  name: linuxea-cmp
  labels:
    app: linuxea-cmpdata:
  test: {{ .Values.mydata }} 复制

{{ .Values.mydata }}这种方式是go的模板方式

helm使用template可以进行渲染,直接在windows就可以渲染模板以共查看

PS H:\k8s-1.20.2\helm> helm.exe template test .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: linuxea-cmp
  labels:
    app: linuxea-cmpdata:
  test: hi mark, my www.linuxea.com 复制

除此之外,当我们输入的是test的时候,我们希望test被替换城什么值的时候就可以使用Release

比如,Release.Name

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  test: {{ .Values.mydata }} 复制

这次chart名称换 marksugar

helm.exe template marksugar .\liunuxea\ 复制
PS H:\k8s-1.20.2\helm>  helm.exe template marksugar .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  test: hi mark, my www.linuxea.com 复制

这里引用{{ .Release.Name }}的地方就被替换城了marksugar

--set

除此之外,还可以使用helm的--set来覆盖--set mydata=linuxea.com

PS H:\k8s-1.20.2\helm> helm.exe template marksugar --set mydata=linuxea.com .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  test: linuxea.com 复制

--dry-run

template只是用来本地模板渲染,但是--dry-run是用来模拟安装,这两个在调试的时候有一些差别,--dry-run也可以使用--debug

helm install marksugar --dry-run   --set mydata=linuxea.com liunuxea/ 复制

如下

[root@linuxea.com /data/helm]# helm install marksugar --dry-run   --set mydata=linuxea.com liunuxea/WARNING: Kubernetes configuration file is group-readable. This is insecure. Location: /root/.kube/configWARNING: Kubernetes configuration file is world-readable. This is insecure. Location: /root/.kube/configNAME: marksugarLAST DEPLOYED: Sat Apr 16 02:09:37 2022NAMESPACE: defaultSTATUS: pending-installREVISION: 1TEST SUITE: NoneHOOKS:MANIFEST:---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  test: linuxea.com 复制

示例2

而values.yaml有多个值的时候,如

mydata:
  names: linuxea
  data: hi mark, my www.linuxea.com 复制

引用的时候就发生了变化

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  name: {{ .Values.mydata.names }}
  test: {{ .Values.mydata.data }} 复制

本地渲染

PS H:\k8s-1.20.2\helm>  helm.exe template marksugar  .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  name: linuxea
  test: hi mark, my www.linuxea.com 复制

--set覆盖也是一样

PS H:\k8s-1.20.2\helm>  helm.exe template marksugar --set mydata.data=linuxea.com .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  name: linuxea
  test: linuxea.com 复制

基本语法

函数和管道

函数

values.yaml有些托拉,有时候更希望有一些函数更快的方式转换来提供数据,而这些函数大多数都由golang的template提供。这里面包含了一些逻辑和运算。另外,还有一些模板在sprig的包,如日期,时间等。阅读模板函数能更快了解

  • quote: 转换成字符串,加上双引号

  • upper: 转换大写

  • with: 作用域

.Values中的点(.)其实就是作用域。而with可以控制变量的作用域并且重新使用,调用就是对当前作用域的引用,.values是在当前作用域下查找values对象
  • indent: 空格

indent的用户是要顶行进行配置,比如想让test: ok前有两个空格,如下

data:
  name: {{ .Values.mydata.names | default "supper" }}
  test: {{ .Values.mydata.data | upper  | repeat 5 }}
  status: ok
  namestatus: "true"
  defaultstaus: true{{ indent 2 "test: ok" }} 复制

管道

管道非常常用,并没有什么特别的区别

参数 | 函数
参数 | 函数 | 函数2 复制

如上:转换字符串的话

{{ .Values.mydata.name | quote | upper }}
{{ .Values.mydata.name | upper | quote }} 复制
  • repeat : repeat COUNT STRING 将字符串重复多少次

如下

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  name: {{ .Values.mydata.names }}
  test: {{ .Values.mydata.data | upper  | repeat 5 }} 复制

渲染

PS H:\k8s-1.20.2\helm>  helm.exe template marksugar  .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  name: linuxea
  test: HI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COM 复制
  • default : 如果没有给定参数就使用默认参数

这个在shell中也很常用,在helm也非常常用,特别是在你的values.yaml中不能使用一个静态配置的时候,default就排上用场了

举个例子,如果names变量为空,就默认赋值supper

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  name: {{ .Values.mydata.names | default "supper" }}
  test: {{ .Values.mydata.data | upper  | repeat 5 }} 复制

values.yaml中把值删掉

mydata:
  names: 
  data: hi mark, my www.linuxea.com 复制

渲染下

PS H:\k8s-1.20.2\helm>  helm.exe template marksugar  .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  name: supper
  test: HI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COM 复制
  • printf

printf和在go中的printf类似,用来打印字符串或者其他的数组,如下

test: {{ .Vaules.test | default (printf "%s-1" (include "test" ))}} 复制

条件语句

流程控制在go template中也是非常重要的一部分,和大多数判断语法一样,不但如此,还有一些声明和命名模板的操作,如下:

  • if/else 条件

  • with 作用域范围

  • range 遍历的一种,类似与for each

  • define 在模板内声明新的命名模板

  • template 导入一个命名模板

  • blok 声明特殊的可填充模块区域

if/else

if 条件判断不管是在什么语言类型中,都是有一个结束标记的,而在helm中使用的是end结束

{{ if TEST }}  test{{ else if TEST2 }}
  test2
{{ elese }}
  default test{{ end }} 复制

如果test为真则test,如果test为test2则test2,否则defalut test

判断的是管道而非values值,这里控制结构可以执行这个判断语句管道,而不仅仅是一个值,如果结果是如下几项,则为false,否则则是true:

  • 布尔 false

  • 0

  • 空字符串

  • nil或者null

  • 空的集合,如map,slice,tuple,dict,array

示例1 if

以上个configmap为例,如果此时希望用一个判断语句来确定是否添加一个字段的话,就可以使用if来进行操作

{{ if eq .Values.mydata.status "isok" }}status: ok{{ end }} 复制

如果此时使用的是换行的if,如

{{ if eq .Values.mydata.status "isok" }}status: ok
{{ end }} 复制

那么很有可能不在一行,解决这个问题的版本是加一个-

  • -是用来删除if之后和end之前的空格的,不可以加载if之前,加在前面就跳到上一行了

{{ if eq .Values.mydata.status "isok" -}}status: ok
{{- end }} 复制

如果Values.mydata.status等于"isok",就添加status: ok

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  name: {{ .Values.mydata.names | default "supper" }}
  test: {{ .Values.mydata.data | upper  | repeat 5 }}
  {{ if eq .Values.mydata.status "isok" }}status: ok{{ end }} 复制

values.yaml

mydata:
  names: marksugar
  data: hi mark, my www.linuxea.com
  status: isok 复制

渲染

PS H:\k8s-1.20.2\helm> helm.exe template marksugar  .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: marksugar-cmp
  labels:
    app: marksugar-cmpdata:
  name: marksugar
  test: HI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COM
  status: ok 复制
  • else if

除此之外,还可以进行嵌套else

  {{ if eq .Values.mydata.status "isok" -}}  status: ok
  {{ else if  eq .Values.mydata.names "marksugar" -}}  namestatus: "true"
  {{ else -}}  defaultstaus: true
  {{- end }} 复制

如果等于isok,就结束,否则就继续判断第二个else if,如果第二个else if等于marksugar就结束,否则就else的默认值。如下

NAME -}}

{{- NAME

这里的-号是删除空格的意思

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  name: {{ .Values.mydata.names | default "supper" }}
  test: {{ .Values.mydata.data | upper  | repeat 5 }}
  {{ if eq .Values.mydata.status "isok" -}}
  status: ok
  {{ else if  eq .Values.mydata.names "marksugar" -}}
  namestatus: "true"
  {{ else -}}
  defaultstaus: true
  {{- end }} 复制

执行

PS H:\k8s-1.20.2\helm> helm template .\liunuxea\
---# Source: linuxea/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:
  name: release-name-cmp
  labels:
    app: release-name-cmpdata:
  name: marksugar
  test: HI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COMHI MARK, MY WWW.LINUXEA.COM
  status: ok 复制

由于第一个if执行完成就是true,逻辑结束

示例2 with

上述的.Values是对当前模板引擎下的作用域内查找.vaules对象,而with是控制变量的作用域,并且和if语句类似

with中默认是不能使用内置的函数,比如:.Release.Name之类的,如果要使用,需要另外的办法

使用示例1的文件重新配置。如下

  {{ with  .Values.mydata -}}
  {{ if eq .status "isok" -}}  status: ok
  {{- else if  eq .names "marksugar" -}}  namestatus: "true"
  {{ else -}}  defaultstaus: true
  {{- end }}
  {{- end }} 复制

一旦 {{ with .Values.mydata -}}配置之后,在whth中,就不在使用.Vaules.mydata.names来调用了,而是.names

apiVersion: v1kind: ConfigMapmetadata:
  name: {{ .Release.Name }}-cmp
  labels:
    app: {{ .Release.Name }}-cmpdata:
  name: {{ .Values.mydata.names | default "supper" }}
  test: {{ .Values.mydata.data | upper  | repeat 5 }}
  {{ with  .Values.mydata -}}
  {{ if eq .status "isok" -}}
  status: ok
  {{- else if  eq .names "marksugar" -}}
  namestatus: "true"
  {{ else -}}
  defaultstaus: true
  {{- end }}
  {{- end }}{{ indent 2 "test: ok" }} 复制

示例3 range

通过在helm中使用range来遍历,比如使用range遍历一个列表或者字典

首先定义一个列表mylist

mylist:
  - mark
  - edwin
  - sean   复制

而后使用range

  mylist: |-
    {{- range .Values.mylist }}
    - {{ . | title | quote }}
    {{- end }} 复制
这里的|-的作用,|是将以下的数据放在一个字符串中,如果不加|就不是一个字符串了。而-是换行
而这里的.的作用域是在range中的,作用域与range开始,end结束

|-|+

  • |-

|-的意思是将文末的换行符删掉

  • |+

|+的意思是将文末的换行符保留


赞 5