Chart模板:函数与管道

常用函数:

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

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

  • indent和nindent:缩进字符串

  • toYaml:引用一块YAML内容

  • 其他函数:upper、title等

            upper:  将值修改为大写
    
            title:  将值首字母修改为大写
    

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

示例:nodeSelector标签的值用了true正常使用会报错,这是因为它是关键字,需要加引号才可以。

#vi mychart/values.yaml 
replicaCount: 1
image:
repository: nginx
tag: "latest"
selectorLabels: "nginx"
nodeSelector:
gpu: true
#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: web2
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.selectorLabels }}
template:
metadata:
labels:
app: {{ .Values.selectorLabels }}
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: nginx
apiVersion: v1
kind: Service
metadata:
labels:
app: web2
name: {{ .Release.Name }}
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: {{ .Values.selectorLabels }}

验证部署

helm install web2 --dry-run mychart/
helm install web2 mychart/

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

示例:以防止忘记定义而导致模板文件缺少字段无法创建资源,这时可以为字段定义一个默认值。

#vi mychart/values.yaml 
replicaCount: 1
image:
repository: nginx
tag: "latest"
selectorLabels: "nginx"
nodeSelector:
gpu: true
labels:
app: ""
#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ .Values.labels.app | default "web2" }}
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.selectorLabels }}
template:
metadata:
labels:
app: {{ .Values.selectorLabels }}
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: nginx

验证部署

helm install web3 --dry-run mychart/
helm install web3 mychart/

这里用到了管道符“|”,前面的值传递后函数验证是否为空。

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

示例:

toYaml:引用一块YAML内容

示例:在values.yaml里写结构化数据,引用内容块

#vi mychart/values.yaml 
replicaCount: 1
image:
repository: nginx
tag: "latest"
selectorLabels: "nginx"
nodeSelector:
gpu: true
labels:
app: ""
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ .Values.labels.app | default "web2" }}
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.selectorLabels }}
template:
metadata:
labels:
app: {{ .Values.selectorLabels }}
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: nginx
resources:
{{ toYaml .Values.resources | nindent 10 }}

验证

helm  install web4 --dry-run /root/mychart/

helm install web4 --set resources.limits.cpu="200m" --dry-run /root/mychart/

Chart模板:流程控制

Helm模板语言提供以下流程控制语句:

  • if/else:条件判断

  • range:循环

  • with:指定变量作用域

Chart模板:流程控制之if/else

条件判断:根据不同的条件做不同的行为

语法:

{{ if <表达式> }} 

# 做某事

{{ else if <表达式> }}

# 做某事

{{ else }}

# 默认

{{ end }}

示例:部署一个应用,在没明确启用ingress时,默认情况下不启用

# values.yaml
ingress:
enabled: false
#vi mychart/templates/ingress.yaml 
{{ if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: minimal-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- http:
paths:
- path: /testpath
pathType: Prefix
backend:
service:
name: test
port:
number: 80
{{ end }}

验证

helm install web1 --set ingress.enabled=true --dry-run /root/mychart/

如果值为以下几种情况则为false:

  • 一个布尔类型 false

  • 一个数字 0

  • 一个空的字符串

  • 一个 nil(空或 null)

  • 一个空的集合( map、 slice、 tuple、 dict、 array)

条件表达式也支持操作符:

  • eq 等于

  • ne 不等于

  • lt 小于

  • gt 大于

  • and 逻辑与

  • or 逻辑或

示例:如果是一个空的集合则不启用资源配额

#vi mychart/values.yaml 
replicaCount: 1
image:
repository: nginx
tag: "latest"
selectorLabels: "nginx"
nodeSelector:
gpu: true
labels:
app: ""
resources: {}
# limits:
# cpu: 100m
# memory: 128Mi
# requests:
# cpu: 100m
# memory: 128Mi
ingress:
enabled: false

#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: {{ .Values.labels.app | default "web2" }}
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.selectorLabels }}
template:
metadata:
labels:
app: {{ .Values.selectorLabels }}
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: nginx
{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
{{- end }}

验证渲染结果:

helm  install test --dry-run mychart/

渲染结果会发现有多余的空行,这是因为模板渲染时会将 指令删除,所以原有的位置就空白了。可以使用横杠“-” 消除空

Chart模板:流程控制之range

循环:一般用于遍历序列结构的数据。例如序列、键值

语法:

{{ range <值> }} 

# 引用内容

{{ end }}

示例:遍历数据

#vi mychart/values.yaml 
test:
- 1
- 2
- 3

#vi mychart/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
test: |
{{- range.Values.test }}
{{ . }} # 引用当前元素
{{- end }}

验证渲染结果

helm install web1 --dry-run mychart/

Chart模板:流程控制之with

with:指定变量作用域

语法:

{{ with <值> }} 

# 限制范围

{{ end }}

with语句可以允许将当前范围 . 设置为特定的对象,比如我们前面一直使用 的 .Values.nodeSelecotr,我们可以使用 with来将 . 范围指向 .Values.nodeSelecotr:

示例:

#vi mychart/values.yaml 
labels:
project: "ms"
app: "gateway"

#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
{{- with .Values.labels }}
project: {{ .project }}
app: {{ .app }}
{{- end }}
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.selectorLabels }}
template:
metadata:
labels:
app: {{ .Values.selectorLabels }}
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: nginx
{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
{{- end }}

验证渲染结果

helm install web1 --dry-run mychart/

with块限制了变量作用域,也就是无法直接引用模板对象,例 如.Values、.Release,如果还想使用,可以定义变量来解决该问题。

示例:

#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
{{- $rs := .Values.replicaCount }}
{{- with .Values.labels }}
project: {{ .project }}
app: {{ .app }}{{ $rs }}
# test: {{ $rs }}
{{- end }}
name: {{ .Release.Name }}
spec:
...

验证

helm install web1 --dry-run mychart/

或者

Chart模板:变量

变量是实际应用中不多,但有时候结合with、range能更好处理数据。

示例:k8s变量是键值,可以range遍历生成

#vi mychart/values.yaml 
env:
NAME: "gateway"
JAVA_OPTS: "-Xmx1G"

#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
{{- $rs := .Values.replicaCount }}
{{- with .Values.labels }}
project: {{ .project }}
app: {{ .app }}{{ $.Values.replicaCount }}
# test: {{ $rs }}
{{- end }}
name: {{ .Release.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Values.selectorLabels }}
template:
metadata:
labels:
app: {{ .Values.selectorLabels }}
spec:
nodeSelector:
gpu: {{ quote .Values.nodeSelector.gpu }}
containers:
- image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
name: nginx
{{- if .Values.resources }}
resources:
{{- toYaml .Values.resources | nindent 10 }}
{{- end }}
env:
{{- range $k,$v := .Values.env }}
- name: {{ $k }}
value: {{ quote $v }}
{{- end }}

验证渲染结果:

helm install web1 --dry-run mychart/

Chart模板:命名模板

命名模板类似于开发语言中的函数。指一段可以直接被另一段程序或代码引用的程序或代码。 在编写chart时,可以将一些重复使用的内容写在命名模板文件中供公共使用,这样可减少重 复编写程序段和简化代码结构。

命名模块使用define定义,template或include引入,在templates目录中默认下划线开头的 文件为公共模板(helpers.tpl)。

示例:资源名称生成指令放到公共模板文件,作为所有资源名称

#vi mychart/templates/_helpers.tpl 
{{- define "fullname" -}}
{{- .Chart.Name -}}-{{ .Release.Name }}
{{- end -}}

#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
{{- $rs := .Values.replicaCount }}
{{- with .Values.labels }}
project: {{ .project }}
app: {{ .app }}{{ $.Values.replicaCount }}
# test: {{ $rs }}
{{- end }}
name: {{ template "fullname" . }}

验证渲染结果:

helm install web1 --dry-run mychart/

template指令是将一个模板包含在另一个模板中的方法。但是,template函 数不能用于Go模板管道。为了解决该问题,引入include指令。

示例:

#vi mychart/templates/_helpers.tpl 
{{- define "labels" -}}
project: {{ .Values.labels.project }}
app: {{ .Values.labels.app }}
{{- end -}}

#vi mychart/templates/deploy.yaml 
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
{{- include "labels" .| nindent 4 }}
name: {{ template "fullname" . }}

验证渲染结果:

helm install web1 --dry-run mychart/

带你写一个通用的Chart

  1. 先创建模板示例 helm create demo

  2. 修改Chart.yaml,Values.yaml,参考示例预留变动的字段值

  3. 在templates目录下准备部署应用所需的yaml文件,并添加指令引用 Values.yaml字段

  4. 将重复使用的内容作为命名模板

  5. 使用Chart结合参数部署多个同类服务

demo-0.1.0.tgz

使用Harbor作为Chart仓库

Harbor是一个主流的镜像仓库系统,在 v1.6 版本以后的 harbor 中新增加了 helm charts 的管理功能,可以存储Chart文件。

使用步骤:

1、启用Harbor的Chart仓库服务

# ./install.sh --with-chartmuseum

启用后,默认创建的项目就带有helm charts功能了。

2、安装push插件

helm plugin install https://github.com/chartmuseum/helm-push
ls /root/.local/share/helm/plugins/helm-push/ #家目录

3、推送

# helm push demo-0.1.0.tgz --username=admin --password=Harbor12345 http://192.168.0.13/chartrepo/library

4、添加repo

helm repo add myrepo --username=admin --password=Harbor12345 http://192.168.0.13:/chartrepo/library
helm repo update
helm repo list

5、部署

# helm install web --version 0.1.0 myrepo/demo   #--version指定chart版本,如果未指定,使用最新版本
helm install web1 --set service.type=NodePort --set service.nodeport=30010 myrepo/demo

公共Chart仓库

国内Chart仓库,可直接使用它们制作好的包:

添加仓库方式:

helm repo add stable http://mirror.azure.cn/kubernetes/charts 
helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
helm repo update
helm repo list