当前位置: 首页 > 工具软件 > Python Helm > 使用案例 >

Helm模板常用语法介绍与简单应用场景

楚煜
2023-12-01

Helm模板常用语法介绍与简单应用场景

什么是Helm

Helm就是一个kubernetes的对象文件管理工具,有的介绍说Helm类似于python的Pip,是包管理工具。我们可以从使用的角度看看Helm的功能,进而明白它是什么工具。

一般我们在部署kubernetes的时候,会定义Deployment、Service、ConfigMap等对象,使用kubectl apply -f的命令,但是,如果你想重新发布,修改,甚至支持多租户(多个环境),修改起来很麻烦。虽然可以使用kubectl edit等命令,但是,我们更加倾向于可以一次性更新我们的服务,并且,最好支持我们做版本管理功能。

所以,Helm就诞生了,帮助我们管理kubenetes的yaml对象文件,借助go的template语法,将kubernetes对象模板化,并允许自己定义填充模板的值,做到一套模板多个发布,并支持版本管理。使用Helm命令行工具,就可以直接管理kubernetes服务——Helm install / uninstall 直接管理整个服务(包含deployment、service、configMap、pvc等等对象)。


本篇文章主要从Helm模板文件的语法讲解,介绍常用的语法与一般的使用环境。

这里贴一下Helm文档的链接:
https://helm.sh/docs/chart_template_guide/getting_started/

_help.tpl子模版

下划线开头的就是子模版,格式:{{- define “模板名字” -}} 模板内容 {{- end -}}

{{- define "nginx.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" -}}
{{- end -}}

# 若 .Values.nameOverride 为空,则默认值为 .Chart.Name

模板引用
{{ include “模板名字” 作用域 }}

apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "nginx.fullname" . }}
应用场景

可以在_help.tpl中编写子模板,完成镜像image字段的拼接。

```yaml
#_helo.tpl中定义规则
{{- define "get-image" -}}
{{- $registryName := .image.registry -}}
{{- $repositoryName := .image.repository -}}
{{- $tag := .image.tag | toString -}}
{{- if .global}}
    {{- if .global.imageRegistry }}
        {{- $registryName := .global.imageRegistry -}}
    {{- end -}}
{{- end -}}
{{- if $registryName }}
{{- printf "%s/%s:%s" $registryName $repositoryName $tag -}}
{{- else -}}
{{- printf "%s"%s" $repositoryName $tag -}}
{{- end -}}
{{- end -}}

# get image nginx
{{- define "my-nginx.image" -}}
{{ include  "get-image" (dict "image" .Values.myNginx "global" .Values.global)}}
{{- end -}}
```

使用时,将registry、repository、tag在values.yaml的定义完成,然后在template文件中使用。

```yaml
# my-nginx deployment.yaml
# ···
image: {{ template "my-nginx.image" .}}
# ···
```

预定义对象

预定义对象可以直接在模板中使用。

Release:      代表Release对象,属性包含:Release.Name、Release.Namespace、Release.Revision等
Values:       表示 values.yaml 文件数据
Chart:        表示 Chart.yaml 数据
Files:        用于访问 chart 中非标准文件

Capabilities: 用于获取 k8s 集群的一些信息
   - Capabilities.KubeVersion.Major:K8s的主版本

Template:     表示当前被执行的模板
   - Name:表示模板名,如:mychart/templates/mytemplate.yaml
   - BasePath:表示路径,如:mychart/templates

# Release
其代表一次应用发布,下面是Release对象包含的属性字段:
Release.Name       - release的名字,一般通过Chart.yaml定义,或者通过helm命令在安装应用的时候指定。
Release.Time       - release安装时间
Release.Namespace  - k8s名字空间
Release.Revision   - release版本号,是一个递增值,每次更新都会加一
Release.IsUpgrade  - true代表,当前release是一次更新.
Release.IsInstall  - true代表,当前release是一次安装
Release.Service    - The service that is rendering the present template. On Helm, this is always Helm.

# Values对象
values 对象的值有四个来源:
    1. chart 包中的 values.yaml 文件
    2. 父 chart 包的 values.yaml 文件
    3. 使用 helm install 或者 helm upgrade 的 -f 或者 --values 参数传入的自定义的 yaml 文件
    4. 通过 --set 参数传入的值

关于变量

  • . 表示全局作用域,可以引用全局对象,并且,可以嵌套链式调用

    # Values
    # 这里引用了全局作用域下的Values对象中的key属性。
    {{ .Values.key }}
    Values代表的就是values.yaml定义的参数,通过.Values可以引用任意参数。
    例子:
    {{ .Values.replicaCount }}
    
    # 引用嵌套对象例子,跟引用json嵌套对象类似
    {{ .Values.image.repository }}
    
  • 自定义模板变量
    可以自定义变量然后在下面使用。

    # 变量名以$开始命名, 赋值运算符是 := (冒号+等号)
    {{- $relname := .Release.Name -}}
    
    #引用自定义变量:
    #不需要 . 引用
    {{ $relname }}
    

关键字及应用

  • wiht 关键字
    with 关键字可以控制变量的作用域,主要就是用来修改 . 作用域的,默认 . 代表全局作用域,with 语句可以修改 . 的含义

    # 例子:
    # .Values.favorite 是一个 object 类型
    {{- with .Values.favorite }}
    drink: {{ .drink | default "tea" | quote }}   # 相当于.Values.favorite.drink
    food:  {{ .food  | upper | quote }}
    {{- end }}
    

    应用场景
    存在某些相关的模板变量上:

    #例子:
    #.Values.favorite是一个object类型
    {{- with .Values.favorite }}
    drink: {{ .drink | default "tea" | quote }}   #相当于.Values.favorite.drink
    food: {{ .food | upper | quote }}
    {{- end }}
    
  • range 关键字
    range用于循环遍历数组类型

    range主要用于循环遍历数组类型。
    
    语法1:
    # 遍历map类型,用于遍历键值对象
    # 变量key代表对象的属性名,val代表属性值
    {{- range key,val := 键值对象 }}
    {{ $key }}: {{ $val | quote }}
    {{- end}}
    
    语法2:
    {{- range 数组 }}
    {{ . | title | quote }} # . (点),引用数组元素值。
    {{- end }}
    
    例子:
    # values.yaml定义
    # map类型
    favorite:
    drink: coffee
    food: pizza
    
    # 数组类型
    pizzaToppings:
    - mushrooms
    - cheese
    - peppers
    - onions
    
    # map类型遍历例子:
    {{- range $key, $val := .Values.favorite }}
    {{ $key }}: {{ $val | quote }}
    {{- end}}
    
    # 数组类型遍历例子:
    {{- range .Values.pizzaToppings}}
    {{ . | quote }}
    {{- end}}
    

    函数

  • include 函数
    include是一个函数,一般输出结果可以传给其他函数

    include 是一个函数,所以他的输出结果是可以传给其他函数的
    
    # 例子1:
    env:
    {{- include "xiaomage" . }}
    
    # 结果:
    env:
        - name: name
        value: xiaomage
        - name: age
        value: secret
        - name: favourite
        value: "Cloud Native DevSecOps"
        - name: wechat
        value: majinghe11
    
    # 例子2:
    env:
    {{- include "xiaomage" . | indent 8}}
    
    # 结果:
    env:
        - name: name
        value: xiaomage
        - name: age
        value: secret
        - name: favourite
        value: "Cloud Native DevSecOps"
        - name: wechat
        value: majinghe11
    
  • 管道Piplines
    管道的概念与liunx中管道命令类似,都是将一系列模板命令串联起来,并进行一系列转化。使用管道命令针对数据格式转换十分方便。

    k8s:  {{ quote .Values.course.k8s }} # 加双引号
    k8s:  {{ .Values.course.k8s | upper | quote }} # 大写字符串加双引号
    k8s:  {{ .Values.course.k8s | repeat 3 | quote }} # 加双引号和重复3次字符串
    
  apiVersion: v1
  kind: ConfigMap
  metadata:
      name: {{ .Release.Name }}-configmap
  data:
      myvalue: "Hello World"
      drink: {{ .Values.favorite.drink | quote }}
      food: {{ .Values.favorite.food | upper | quote }}
  ```
  • lookup 函数
    lookup对象可以用于查找运行的集群中查找资源。查找 apiVersion, kind, namespace, name -> 资源或者资源列表。

    # 对应关系
    kubectl get pod mypod -n mynamespace  ==》    lookup "v1" "Pod" "mynamespace" "mypod"
    kubectl get pods -n mynamespace          ==》  lookup "v1" "Pod" "mynamespace" ""
    kubectl get pods --all-namespaces     ==》  lookup "v1" "Pod" "" ""
    kubectl get namespace mynamespace     ==》    lookup "v1" "Namespace" "" "mynamespace"
    kubectl get namespaces                ==》  lookup "v1" "Namespace" "" ""
    
    (lookup "v1" "Namespace" "" "mynamespace").metadata.annotations
    
    {{ range $index, $service := (lookup "v1" "Service" "mynamespace" "").items }}
    {{/* do something with each service */}}
    {{ end }}
    
  • 运算符函数
    and, coalesce, default, empty, eq, fail, ge, gt, le, lt, ne, not, and or。

    and .Arg1 .Arg2
    
    eq .Arg1 .Arg2 # (Arg1 == Arg2)
    ne .Arg1 .Arg2 # (Arg1 != Arg2)
    
    le .Arg1 .Arg2 # (Arg1 <= Arg2)
    lt .Arg1 .Arg2 # (Arg1 < Arg2)
    
    gt .Arg1 .Arg2 # (Arg1 > Arg2)
    ge .Arg1 .Arg2 # (Arg1 >= Arg2)
    
    default "foo" .Bar
    
    empty .Foo # true false
    
    fail "Please accept the end user license agreement" # 无条件地返回带有指定文本的空 string 或者 error。
    
    coalesce 0 1 2 # 获取一个列表并返回第一个非空值 # 用于扫描多个对象或者多个值
    coalesce .name .parent.name "Matt"
    #上述示例会优先检查 .name 是否为空。如果不是,就返回值。如果 是 空, 继续检查.parent.name。 最终,如果 .name 和 .parent.name 都是空,就会返回 Matt。
    
    ternary "foo" "bar" true # 就像if判断一样, 如果第三个值返回的是true,则返回第一个值(foo),反之返回第二个值(bar)
    true | ternary "foo" "bar"
    # 上述示例会输出foo
    
  • 字符串处理函数
    Helm 包含了字符串函数:
    abbrev, abbrevboth, camelcase, cat, contains, hasPrefix, hasSuffix, indent, initials, kebabcase, lower, nindent, nospace, plural, print, printf, println, quote, randAlpha, randAlphaNum, randAscii, randNumeric, repeat, replace, shuffle, snakecase, squote, substr, swapcase, title, trim, trimAll, trimPrefix, trimSuffix, trunc, untitle, upper, wrap, 和 wrapWith。

    具体使用:
    https://helm.sh/zh/docs/chart_template_guide/function_list/

流程与控制

if/else 针对流程控制的方法。

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

# 判断条件,如果值为以下几种情况,管道的结果为 false:
1. 一个布尔类型的假
2. 一个数字零
3. 一个空的字符串
4. 一个 nil(空或null)
5. 一个空的集合(map, slice, tuple, dict, array)
除了上面的这些情况外,其他所有的条件都为真。

常用的模板语法就是这些,并且,在模板中做好各种判空操作,多层数据选择,是可以十分灵活定义kubernetes对象的。

 类似资料: