zl程序教程

您现在的位置是:首页 >  后端

当前栏目

Kubernetes Helm Chart模板语法:函数与管道

Kubernetes模板 函数 语法 管道 Chart Helm
2023-09-14 09:15:18 时间

Helm template快速入门


Helm是Kubernetes的包管理工具,如果把比作操作系统,那么Helm就好比yum,apt-get,homebrew。使用Helm template可以方便我们部署和管理自己的应用。本篇将基于Helm3.0+带你快速入门Helm template。

Prerequisite 


若需要执行本篇示例,需要准备:

  • 安装Helm (Helm 3.0+)
  • 一个Kubernetes集群

Quick Start


在开始之前,我们简单理解一下Helm template的基本原理。其实也很简单,Helm使用go template模板语言来编写代表Kubernetes资源(deployment,service, etc...)的模板文件,并提供让用户配置这些模板变量的能力。在部署时Helm通过模板引擎将模板渲染成真正的Kubernetes资源文件,并将它们部署到节点上。

使用以下命令创建模板:

$ helm create mychart
复制代码

该命令会在当前目录下创建如下结构的文件夹:

mychart
├── Chart.yaml
├── charts
├── templates
│   ├── NOTES.txt
│   ├── _helpers.tpl
│   ├── deployment.yaml
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── service.yaml
│   ├── serviceaccount.yaml
│   └── tests
│       └── test-connection.yaml
└── values.yaml
  •  Chart.yaml:用于描述这个 Chart的基本信息,包括名字、描述信息以及版本等。
  •  values.yaml :用于存储 templates 目录中模板文件中用到变量的值。(变量文件)用户可以在helm install 或者 helm upgrade可以指定新的值来覆盖默认值。
  • Templates: 目录里面存放所有yaml模板文件。
  •  charts:目录里存放这个chart依赖的所有子chart。
  • NOTES.txt :用于介绍Chart帮助信息, helm install 部署后展示给用户。例如:如何使用这个 Chart、列出缺省的设置等。
  • _helpers.tpl:放置模板的地方,可以在整个 chart 中重复使用。

现在手动创建chart目录学习模板的使用


[root@k8s-master ~]# mkdir -p mychart
[root@k8s-master mychart]# mkdir -p templates
[root@k8s-master mychart]# ls
templates

这里面是chart的描述信息

[root@k8s-master mychart]# vim Chart.yaml
[root@k8s-master mychart]# cat Chart.yaml 
apiVersion: v2
name: mychart
description: A Helm chart for Kubernetes
type: application
version: 0.1.0
appVersion: 1.16.0
[root@k8s-master mychart]# ls
Chart.yaml  templates

这里把基本需要的变量先写上

[root@k8s-master mychart]# cat values.yaml 
replicaCount: 1
image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: "1.16"
selectorLabels: "nginx"
[root@k8s-master mychart]# ls
Chart.yaml  templates  values.yaml

这个目录下就放着其模板文件

[root@k8s-master mychart]# cd templates/
[root@k8s-master templates]# ls
deployment.yaml  service.yaml

创建一个空的

[root@k8s-master templates]# touch _helpers.tpl  

部署好chart会显示

[root@k8s-master templates]# touch NOTES.txt
[root@k8s-master templates]# vim NOTES.txt 
[root@k8s-master templates]# cat NOTES.txt 
hello this is mychart

这样就将差异化的地方通过模板做了替换,heml之后会将其字段替换为具体值

helm模板语法


  1. 模板引用方式,{{ .Release.Name }}, 通过双括号注入,小数点开头表示从最顶层命名空间引用。

  2. helm内置对象
    1. Release, release相关属性

    2. Chart, Chart.yaml文件中定义的内容

    3. Values, values.yaml文件中定义的内容

Chart模板:函数与管道


常用函数:

• quote:将值转换为字符串,即加双引号

• default:设置默认值,如果获取的值为空则为默认值

• indent和nindent:缩进字符串

• toYaml:引用一块YAML内容

• 其他函数:upper、title等

quote:将值转换为字符串,即加双引号


apiVersion: apps/v1
kind: Deployment
metadata:
  name: web
  namespace: default
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      nodeSelector:
        gpu: true
      containers:
      - name: web
        image: nginx:1.19


[root@k8s-master templates]# kubectl apply -f deployment.yaml 
Error from server (BadRequest): error when creating "deployment.yaml": Deployment in version "v1" cannot be handled as a Deployment: v1.Deployment.Spec: v1.DeploymentSpec.Template: v1.PodTemplateSpec.Spec: v1.PodSpec.NodeSelector: ReadString: expects " or n, but found t, error found in #10 byte of ...|":{"gpu":true}}}}}
|..., bigger context ...|nginx:1.19","name":"web"}],"nodeSelector":{"gpu":true}}}}}
|..

以为gpu的值true不是字符串类型,因为这个是布尔的类型,这里需要不管输入的是什么值都需要转成字符串,使用这个函数就非常有用了,quote:将值转换为字符串,即加双引号

[root@k8s-master ~]# cat mychart/templates/deployment.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}
  namespace: default
spec:
  replicas: {{ .Values.replicaCount }}
  selector:
    matchLabels:
      app: {{ .Values.selectorLabels }}
  template:
    metadata:
      labels:
        app: {{ .Values.selectorLabels }}
    spec:
      nodeSelector: 
        gpu: {{  .Values.nodeSelector.gpu  }}
      containers:
      - name: web
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"



[root@k8s-master ~]# cat mychart/values.yaml 
replicaCount: 1
image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: "1.16"
selectorLabels: "nginx"
nodeSelector:
  gpu: true 


[root@k8s-master ~]# helm install web1 --dry-run  mychart/
    spec:
      nodeSelector: 
        gpu: true


修改之后渲染
    spec:
      nodeSelector:
        gpu: {{ quote .Values.nodeSelector.gpu }}

[root@k8s-master ~]# helm install web1 --dry-run  mychart/
    spec:
      nodeSelector: 
        gpu: "true"

针对一些字符串是函数类型,那么使用该函数

default:设置默认值,如果获取的值为空则为默认值


示例: 以防止忘记定义而导致模板文件缺少字段无法创建资源,这时可以为字段定义一个默认值。
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }} 这里用到了管道符“|”,前面的值传递后函数验证是否为空。
这个是values.yml里面的定义
replicaCount: 1
image:
  repository: nginx
  pullPolicy: IfNotPresent
  tag: ""
selectorLabels: "nginx"
nodeSelector:
  gpu: true
namespace: ""

deployment.yml定义
metadata:
  name: {{ .Release.Name }}
  namespace: {{ .Values.namespace | default "default" }}

[root@k8s-master ~]# helm install web1 --dry-run  mychart/
metadata:
  name: web1
  namespace: default

[root@k8s-master ~]# helm install web1 --set namespace=test --dry-run  mychart/
metadata:
  name: web1
  namespace: test

indent和nindent(缩进,引用内容块)


indent和nindent函数都是缩进字符串,主要区别在于nindent会在缩进前多添加一个换行符。

metadata:
  labels:
    app: web
    app: {{ .Release.Name | indent 6 }}
    app: {{ .Release.Name | nindent 6 }

metadata:
  labels:
    app: web
    app:       web
    app: 
      web
  name: web

indent用的很少,nindent用的多,一般是结合引用内容块,也就是从另外一块yaml当中将其引用过来

      nodeSelector:
        {{- toYaml . | nindent 8 }}
      {{- end }}
      {{- with .Values.affinity }}
      affinity:
        {{- toYaml . | nindent 8 }}

toYaml:引用一块YAML内容


示例:在values.yaml里写结构化数据,引用内容块,结合上面的nindent换行缩进
像健康检查,资源配额resources,或者端口,这都是一块一块的内容,可以通过toYaml引用,也可以写死在deployment模板文件当中。
          ports:
            - name: http
              containerPort: 80
              protocol: TCP
          livenessProbe:
            httpGet:
              path: /
              port: http
          readinessProbe:
            httpGet:
              path: /
              port: http
          resources:
            {{- toYaml .Values.resources | nindent 12 }}
      {{- with .Values.nodeSelector }}

当然了,块这种通过引用,那种变量为键值类型的,那么在values里面定义以层级关系定义,在引用的时候通过.来层级引用,多个层级多个.去引用{{ .valuse.image.repository  }},对于复杂的块的方式不适合.去取值,适合使用toYaml,不管有多少东西都拿过来。

image:
  repository: nginx
  pullPolicy: IfNotPresent
  # Overrides the image tag whose default is the chart appVersion.
  tag: "1.17"

示例 toYaml用法:(toYaml是顶头放的,所以需要换行缩进)

[root@k8s-master ~]# vim mychart/templates/deployment.yaml 
      containers:
      - name: web
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
        resources:
          {{- toYaml .Values.resources | nindent 10 }}


[root@k8s-master mychart]# vim values.yaml 
resources:
  limits:
    cpu: 100m
    memory: 128Mi
  requests:
    cpu: 100m
    memory: 128Mi

[root@master ~]# helm install web testchart/ --dry-run
      - image: nginx:1.17
        name: nginx
        resources:
          limits:
            cpu: 100m
            memory: 128Mi
          requests:
            cpu: 100m
            memory: 128Mi

[root@k8s-master ~]# helm install web1 --set resources.limits.cpu="200m" --dry-run mychart/
        resources:
          limits:
            cpu: 200m

resources和健康检查都可以写到values.yaml里面去,并且在deployment模板文件里面通过toYaml进行引用进来。