主讲内容:docker/kubernetes 云原生技术,大数据架构,分布式微服务,自动化测试、运维。
腾讯课堂:点击进入
网易课堂:点击进入
7月1号-7月29号 8折优惠!!!
7月1号-7月29号 8折优惠!!!
7月1号-7月29号 8折优惠!!!
全栈工程师开发手册 (作者:栾鹏)
架构系列文章
Helm之于Kubernetes好比yum之于RHEL,或者apt-get之于Ubuntu。Helm使用Chart帮助我们管理应用,Chart就好像RPM一样,里面描述了应用及其依赖关系。主要概念:
参考:https://blog.csdn.net/luanpeng825485697/article/details/80873236
helm init
时指定sahelm -h
和 helm [command] -h
Helm管理的kubernetes资源包称之为Chart,Chart是一个结构相对固定的文件目录。一个单独的Chart可以用于部署一下简单的Kubernetes资源,如:memcached,又或者更复杂的应用,如完整的Web应用:HTTP servers, databases, caches等等。
Helm的结构:
[root@k8s-master mychart]# tree mychart/
mychart # Chart的名字,也就是目录的名字
├── charts # Chart所依赖的子Chart
│ ├── jenkins-0.14.0.tgz # 被“mychart”依赖的其中一个subChart
│ ├── mysubchart # 被“mychart”依赖的另一个subChart
│ │ ├── charts
│ │ ├── Chart.yaml
│ │ ├── templates
│ │ │ └── configmap.yaml
│ │ └── values.yaml
│ └── redis-1.1.17.tgz
├── Chart.yaml # 记录关于该Chart的描述信息:比如名称、版本等等
├── config1.toml # 其他文件:可以是任何文件
├── config2.toml # 其他文件:可以是任何文件
├── requirements.yaml # 记录该Chart的依赖,类似pom.xml
├── templates # 存放模版文件,模板也就是将k8s的yml文件参数化,最终还是会被helm处理成k8s的正常yml文件,然后用来部署对应的资源
│ ├── configmap.yaml # 一个ConfigMap资源模版
│ ├── _helpers.tpl # "_"开头的文件不会本部署到k8s上,可以用于定于通用信息,在其他地方应用,如loables
│ └── NOTES.txt # 在执行helm instll安装此Chart之后会被输出到屏幕的一些自定义信息
└── values.yaml # 参数定义文件,这里定义的参数最终会应用到模版中
Chart可以是目录,也可以是tgz格式的压缩包。
charts目录和requirements.yaml文件到区别就和lib和pom.xml的区别类似,一个用于存放,一个用于描述
[root@k8s-master charts]# pwd
/root/charts
[root@k8s-master charts]# helm create mychart-2
[root@k8s-master charts]# ll
drwxr-xr-x. 4 root root 93 3月 12 10:48 mychart-2
[root@k8s-master charts]# tree mychart-2
mychart-2
├── charts
├── Chart.yaml
├── templates
│ ├── deployment.yaml
│ ├── _helpers.tpl
│ ├── ingress.yaml
│ ├── NOTES.txt
│ └── service.yaml
└── values.yaml
2 directories, 7 files
### 为了后面的实验,我们先删除helm默认生成的文件 ###
[root@k8s-master charts]# rm -rf mychart-2/templates/*
helm会帮我们创建一下必要的模版文件,简单的Chart直接修改这些文件即可
[root@k8s-master charts]# vi mychart-2/Chart.yaml apiVersion: v1
appVersion: "1.0"description: A Helm chart for Kubernetes
name: mychart-2version: 0.1.0
这里仅列举了重要的数据项,还有很多可选项:keywords、home、maintainers等,参考。这些内容在打包分享时很有用。
此文件主要用来存放Chart的默认值,这些值会被应用到模版中,替换掉模版中的变量,生成最终k8s的yaml部署文件,例如:
[root@k8s-master charts]# vi mychart/values.yamlfavorite:
drink: coffee
food: pizza
[root@k8s-master charts]# vi mychart/templates/configmap.yaml apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ quote .Values.favorite.drink }}
food: {{ .Values.favorite.food}}
在这个例子中,我们有一个configmap.yaml模版,模版中点了一个ConfigMap,模版中包含了很多
{{}}
,这些{{}}
中以**.Values开头的会被替换成values.yaml中的值,.Release**开头的会被替换成release相关的变量值,Release是内置变量中的一员。quote是一个function,当然还有很多其他的function。
这里为什么说默认值呢,因为在执行helm install
时,可以通过helm install --set tags.front-end=true --set subchart2.enabled=false
这种方式来改变实际的值。
关于template的详细内容,将在下文阐述。
Release.Name
: 实例的名称(注意:不是应用的名称)Release.Time
: 应用实例最后被更新的时间. 就是实例对象的 Last Released
属性.Release.Namespace
: 应用实例的命名空间.Release.Service
: 进行发布的服务。通常这是Tiller .Release.IsUpgrade
: 如果当前对实例的操作是更新或者回滚,这个变量的值就会被置为true.Release.IsInstall
: 如果当前对实例的操作是安装,则这边变量被置为true.Release.Revision
: 版本序号,从1开始,每次使用helm upgrade命令都会增加1.Chart
: Chart.yaml文件中的内容,所以我们可以使用Chart.Version
表示应用版本,Chart.Maintainers
函数应用的维护信息.Files
: A map-like object containing all non-special files in the chart. This will not give you access to templates, but will give you access to additional files that are present (unless they are excluded using .helmignore
). Files can be accessed using {{index .Files "file.name"}}
or using the {{.Files.Get name}}
or {{.Files.GetString name}}
functions. You can also access the contents of the file as []byte
using {{.Files.GetBytes}}
Capabilities
:一个map对象, ({{.Capabilities.KubeVersion}}
,包含kubernetes的版本信息 ({{.Capabilities.TillerVersion}}
, 包含tiller的版本信息,({{.Capabilities.APIVersions.Has "batch/v1"
)包含kubernetes api版本信息Helm的变量是有作用域的:父Chart可以访问子Chart的值,而子Chart不能访问父Chart的值:
[root@k8s-master charts]# vi mychart-2/values.yaml
title: "MyChart-2"
mysubchart1:
title: mysubchart1
mysubchart2:
title: mysubchart2
[root@k8s-master charts]# vi mychart-2/charts/mysubchart1/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
title: {{ .Values.title }}
[root@k8s-master charts]# vi mychart-2/charts/mysubchart2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
title: {{ .Values.title }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-2/
[debug] Created tunnel using local port: '37936'
[debug] SERVER: "127.0.0.1:37936"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-2
NAME: cautious-hare
REVISION: 1
RELEASED: Mon Mar 12 13:51:29 2018
CHART: mychart-2-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
mysubchart1:
global: {}
title: mysubchart1
mysubchart2:
global: {}
title: mysubchart2
title: MyChart-2
HOOKS:MANIFEST:
---
# Source: mychart-2/charts/mysubchart1/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cautious-hare-configmap
data:
title: mysubchart1
---
# Source: mychart-2/charts/mysubchart2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cautious-hare-configmap
data:
title: mysubchart2
---
# Source: mychart-2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cautious-hare-configmap
data:
title: MyChart-2
mysubchart1: mysubchart1
mysubchart2: mysubchart2
上例中,mychart-2/charts/mysubchart1/values.yaml和mychart-2/charts/mysubchart2/values.yaml为空白文件。mysubchart1和mysubchart2可以正常访问到mychart-2/values.yaml文件中定义的对应子Chart的内容。如果直接访问其他变量,比如:
{{ .Values.mysubchart2.xxx }}
将得到一个错误。
你也可以理解为父charts覆盖了子charts。
如果在父Chart和子Chart中同时定义了相同的值,则父Chart覆盖子Chart:
[root@k8s-master charts]# vi mychart-2/values.yaml
title: "MyChart-2"
mysubchart1:
title: mysubchart1
[root@k8s-master charts]# vi mychart-2/charts/mysubchart1/values.yaml
title: xxxxxxx
[root@k8s-master charts]# vi mychart-2/charts/mysubchart2/values.yaml
title: nnnnnnnnnn
[root@k8s-master charts]# helm install --debug --dry-run mychart-2/
[debug] Created tunnel using local port: '35979'
[debug] SERVER: "127.0.0.1:35979"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-2
NAME: nosy-lobster
REVISION: 1
RELEASED: Mon Mar 12 13:57:58 2018
CHART: mychart-2-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
mysubchart1:
global: {}
title: mysubchart1
mysubchart2:
global: {}
title: nnnnnnnnnn
title: MyChart-2
HOOKS:
MANIFEST:
---
# Source: mychart-2/charts/mysubchart1/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nosy-lobster-configmap
data:
title: mysubchart1
---
# Source: mychart-2/charts/mysubchart2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nosy-lobster-configmap
data:
title: nnnnnnnnnn
---
# Source: mychart-2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nosy-lobster-configmap
data:
title: MyChart-2 mysubchart1: mysubchart1 mysubchart2: nnnnnnnnnn
可以在父Chart中定义全局变量,子Chart可以通过 .Values.global.name
访问全局变量:
[root@k8s-master charts]# vi mychart-2/values.yaml
global:
app: MyTestAPP
title: "MyChart-2"
mysubchart1:
title: mysubchart1
[root@k8s-master charts]# vi mychart-2/charts/mysubchart1/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
title: {{ .Values.title }}
appName: {{ .Values.global.app }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-2/
[debug] Created tunnel using local port: '39141'
[debug] SERVER: "127.0.0.1:39141"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-2
NAME: ignorant-gerbil
REVISION: 1
RELEASED: Mon Mar 12 14:03:02 2018
CHART: mychart-2-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
global:
app: MyTestAPP
mysubchart1:
global:
app: MyTestAPP
title: mysubchart1
mysubchart2:
global:
app: MyTestAPP
title: nnnnnnnnnn
title: MyChart-2
HOOKS:
MANIFEST:
---# Source: mychart-2/charts/mysubchart1/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ignorant-gerbil-configmap
data:
title: mysubchart1
appName: MyTestAPP
---# Source: mychart-2/charts/mysubchart2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ignorant-gerbil-configmap
data:
title: nnnnnnnnnn
---# Source: mychart-2/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: ignorant-gerbil-configmap
data:
title: MyChart-2
mysubchart1: mysubchart1
mysubchart2: nnnnnnnnnn
这个文件需要手动创建,requirements.yaml文件用来定义Chart的依赖,直接将这些依赖放到chart目录下也是可以的。使用文件来管理是来会更加便利。简单文件的格式如下:
dependencies:
- name: redis
version: 1.1.17
repository: https://kubernetes-charts.storage.googleapis.com
文件内容表明当前Chart依赖redis-1.1.17这个Chart,这个Chart的仓库地址是https://kubernetes-charts.storage.googleapis.com,这个地址必须已经添加到你的helm中,添加命令:helm repo add
,查看命令:helm repo list
。
然后我们执行 helm dependency update chartName
命令helm就会帮我们下载requirements.yaml文件中定义的其他Chart,这些Chart会存放在charts目录中。
[root@k8s-master charts]# helm dependency update mychart-2/
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 1 charts
Downloading redis from repo https://kubernetes-charts.storage.googleapis.com
Deleting outdated charts
[root@k8s-master charts]# ll mychart-2/charts/
总用量 8
-rw-r--r--. 1 root root 6189 3月 12 10:54 redis-1.1.17.tgz
命令简写:
helm dep up mychart-2/
下面是一个复杂一点的例子:
dependencies:
- name: redis
version: 1.1.17
repository: https://kubernetes-charts.storage.googleapis.com
condition: redis.enabled
tags:
- redis
- name: jenkins
version: 0.14.0
repository: https://kubernetes-charts.storage.googleapis.com
condition: jenkins.enabled
tags:
- jenkins
- name: redis
version: 1.1.17
repository: https://kubernetes-charts.storage.googleapis.com
alias: newname
tags:
- redis
在这个例子中,涉及到alias、condition、tags三个关键字,我们配合下面的values.yaml文件一项一项来解释,values.yaml文件内容:
redis:
enabled: false
jenkins:
enabled: false
tags:
redis: false
jenkins: true
[root@k8s-master charts]# helm dep up mychart-2/
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "stable" chart repository
Update Complete. ⎈Happy Helming!⎈
Saving 3 charts
Downloading redis from repo https://kubernetes-charts.storage.googleapis.com
Downloading jenkins from repo https://kubernetes-charts.storage.googleapis.com
Downloading redis from repo https://kubernetes-charts.storage.googleapis.com
Deleting outdated charts
[root@k8s-master charts]# ll mychart-2/charts/
总用量 24
-rw-r--r--. 1 root root 12685 3月 12 11:18 jenkins-0.14.0.tgz
-rw-r--r--. 1 root root 6189 3月 12 11:18 redis-1.1.17.tgz
[root@k8s-master charts]# helm install --debug --dry-run mychart-2/
[debug] Created tunnel using local port: '43383'
[debug] SERVER: "127.0.0.1:43383"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-2
NAME: reeling-puffin
REVISION: 1
RELEASED: Mon Mar 12 11:24:30 2018
CHART: mychart-2-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
jenkins:
enabled: false
redis:
enabled: false
tags:
jenkins: true
redis: false
HOOKS:
MANIFEST:
helm install
用于在k8s上部署Chart,–debug –dry-run选项用于调试,加了两个选项之后,不会在k8s上部署任何资源,仅输出helm转换之后的模版信息和相关变量
### 修改values.yaml文件 ###
[root@k8s-master charts]# vi mychart-2/values.yaml
redis:
enabled: false
jenkins:
enabled: false
tags:
redis: true
jenkins: true
### 再次执行install ###
[root@k8s-master charts]# helm install --debug --dry-run mychart-2/
[debug] Created tunnel using local port: '45794'
[debug] SERVER: "127.0.0.1:45794"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-2
NAME: sweet-hyena
REVISION: 1
RELEASED: Mon Mar 12 11:29:49 2018
CHART: mychart-2-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
jenkins:
enabled: false
newname:
global: {}
image: bitnami/redis:4.0.8-r5
imagePullPolicy: IfNotPresent
metrics:
annotations:
prometheus.io/port: "9121"
prometheus.io/scrape: "true"
enabled: false
image: oliver006/redis_exporter
imagePullPolicy: IfNotPresent
imageTag: v0.11
resources: {}
networkPolicy:
allowExternal: true
enabled: false
nodeSelector: {}
persistence:
accessMode: ReadWriteOnce
enabled: true
path: /bitnami
size: 8Gi
subPath: ""
podAnnotations: {}
podLabels: {}
resources:
requests:
cpu: 100m
memory: 256Mi
securityContext:
enabled: true
fsGroup: 1001
runAsUser: 1001
service:
annotations: {}
loadBalancerIP: null
serviceType: ClusterIP
tolerations: []
usePassword: true
redis:
enabled: false
tags:
jenkins: true
redis: true
HOOKS:
MANIFEST:
---# Source: mychart-2/charts/newname/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: sweet-hyena-newname
labels:
app: sweet-hyena-newname
chart: "newname-1.1.17"
release: "sweet-hyena"
heritage: "Tiller"
type: Opaque
data:
redis-password: "anVXdzdJQjJRTg=="---# Source: mychart-2/charts/newname/templates/pvc.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
name: sweet-hyena-newname
labels:
app: sweet-hyena-newname
chart: "newname-1.1.17"
release: "sweet-hyena"
heritage: "Tiller"
spec:
accessModes:
- "ReadWriteOnce"
resources:
requests:
storage: "8Gi"---# Source: mychart-2/charts/newname/templates/svc.yaml
apiVersion: v1
kind: Service
metadata:
name: sweet-hyena-newname
labels:
app: sweet-hyena-newname
chart: "newname-1.1.17"
release: "sweet-hyena"
heritage: "Tiller"
annotations:
spec:
type: ClusterIP
ports:
- name: redis
port: 6379
targetPort: redis
selector:
app: sweet-hyena-newname
---# Source: mychart-2/charts/newname/templates/deployment.yaml
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: sweet-hyena-newname
labels:
app: sweet-hyena-newname
chart: "newname-1.1.17"
release: "sweet-hyena"
heritage: "Tiller"
spec:
template:
metadata:
labels:
app: sweet-hyena-newname
spec:
securityContext:
fsGroup: 1001
runAsUser: 1001
containers:
- name: sweet-hyena-newname
image: "bitnami/redis:4.0.8-r5"
imagePullPolicy: "IfNotPresent"
env:
- name: REDIS_PASSWORD
valueFrom:
secretKeyRef:
name: sweet-hyena-newname
key: redis-password
ports:
- name: redis
containerPort: 6379
livenessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 30
timeoutSeconds: 5
readinessProbe:
exec:
command:
- redis-cli
- ping
initialDelaySeconds: 5
timeoutSeconds: 1
resources:
requests:
cpu: 100m
memory: 256Mi
volumeMounts:
- name: redis-data
mountPath: /bitnami
subPath:
volumes:
- name: redis-data
persistentVolumeClaim:
claimName: sweet-hyena-newname
忽略输出内容的细节,注意看
COMPUTED VALUES
和# Source:
,这里只有newname的相关资源和计算值,行为正好和我们预期的一致。说明condition和tags只在install时有效,在dependency update时无效。
还有一点,执行helm install
之前,如果requirements.yaml中有charts中不存在的依赖,必须先执行helm dep up
更新所有的依赖,否则会提示:
[debug] Created tunnel using local port: '45706'
[debug] SERVER: "127.0.0.1:45706"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-2
Error: found in requirements.yaml, but missing in charts/ directory: redis, jenkins, redis
目录charts用来存放当前Chart依赖的其他Chart,这些被依赖的Chart可以是上文requirements.yaml文件中描述的,也可以直接在charts目录下创建新的charts
[root@k8s-master charts]# cd mychart-2/charts/
[root@k8s-master charts]# pwd
/root/charts/mychart-2/charts
[root@k8s-master charts]# helm create mysubchart-1Creating mysubchart-1
[root@k8s-master charts]# helm create mysubchart-2Creating mysubchart-2
[root@k8s-master charts]# ll
drwxr-xr-x. 4 root root 93 3月 12 12:10 mysubchart-1
drwxr-xr-x. 4 root root 93 3月 12 12:10 mysubchart-2
每个subChart都是一个结构完整的Chart,可以是目录,也可以是tgz文件,tgz文件可以用
tar -zxvf
命令解压
此时若部署mychart-2,也会连同mysubchart-1和mysubchart-2一同部署到k8s上
####3.1.6、目录:templates
templates的具体内容在下文专门作为一个章节来阐述。
Hook允许我们干涉执行 helm install
的过程。正常情况下 helm install
的执行步骤如下:
helm install foo
foo
templates而可用的hook包括:
在正常的执行步骤中加入 pre-install
和 post-install
之后:
helm install foo
foo
templatespre-install
hooks (loading hook resources into Kubernetes)--wait
flag is set, Tiller will wait until all resources are in a ready state and will not run the post-install
hook until they are ready.post-install
hook (loading hook resources)注意:hook是安装weight值的大小,由小到大排序之后,按顺序执行,如果weight值相同则按名称排序。
Hook通常可以用来备份/回复数据之类的操作。
[root@k8s-master charts]# vi mychart-2/templates/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: "{{.Release.Name}}"
labels:
heritage: {{.Release.Service | quote }}
release: {{.Release.Name | quote }}
chart: "{{.Chart.Name}}-{{.Chart.Version}}"
annotations:
# This is what defines this resource as a hook. Without this line, the
# job is considered part of the release.
"helm.sh/hook": pre-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
metadata:
name: "{{.Release.Name}}"
labels:
heritage: {{.Release.Service | quote }}
release: {{.Release.Name | quote }}
chart: "{{.Chart.Name}}-{{.Chart.Version}}"
spec:
restartPolicy: Never
containers:
- name: pre-install-job
image: "alpine:3.7"
command: ["/bin/sleep","{{default "20" .Values.sleepyTime}}"]
“helm.sh/hook”:定义一个hook,如果需要定义为多个hook,可以用逗号分隔:post-install,post-upgrade
“helm.sh/hook-weight”:定义weight,可以是正数或者负数
“helm.sh/hook-delete-policy”:定义hook的删除策略
测试:可以执行helm install mychart-2
部署此Chart,用kubectl get cm
观察k8s上资源出现的时间
Helm的repository是一个HTTP服务,可以用于管理Chart:
### 查看已添加的repository ###
[root@k8s-master charts]# helm repo list
### 使用帮助 ###
[root@k8s-master charts]# helm repo -h
### Chart打包 ###
[root@k8s-master charts]# helm package mychart-2/Successfully packaged chart and saved it to: /root/charts/mychart-2-0.1.0.tgz
drwxr-xr-x. 4 root root 143 3月 12 14:01 mychart-2
-rw-r--r--. 1 root root 19642 3月 12 14:33 mychart-2-0.1.0.tgz
Helm提供一个serve,用于管理本地Chart:
### 使用帮助 ###
[root@k8s-master charts]# helm serve -h
### 启动本地服务 ###
[root@k8s-master charts]# helm serve --address "0.0.0.0:8879"
Regenerating index. This may take a moment.
Now serving you on 0.0.0.0:8879
然后在浏览器中访问,地址:http://192.168.119.160:8879
前面的内容也提到了模版,模版主要功能就是将k8s部署用的yaml文件中的会发生改变的内容参数话,将不变的内容固定到模版文件中。
对于一个Chart,所有的模版都存放在templates目录内,在部署时,templates目录内的所有内容(处理”_”开头的内容)都会在被处理后发生到k8s。
### 创建一个Chart ###
[root@k8s-master charts]# helm create mychart-3
Creating mychart-3### 删除helm生成的文件,从零开始 ###
[root@k8s-master charts]# rm -rf mychart-3/templates/*
### 创建第一个模版文件,一个简单的ConfigMap ###
[root@k8s-master charts]# vi mychart-3/templates/configmap.yamlapiVersion: v1
kind: ConfigMap
metadata:
name: mychart-configmap
data:
myvalue: "Hello World"
### 安装部署到k8s上 ###
[root@k8s-master charts]# helm install mychart-3/NAME: veering-owl
LAST DEPLOYED: Mon Mar 12 15:09:37 2018NAMESPACE: defaultSTATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
mychart-configmap 1 0s
### 查看release ###
[root@k8s-master charts]# helm ls
NAME REVISION UPDATED STATUS CHART NAMESPACE
veering-owl 1 Mon Mar 12 15:09:37 2018 DEPLOYED mychart-3-0.1.0 default
### 查看k8s部署情况 ###
[root@k8s-master charts]# kubectl get cm
NAME DATA AGE
mychart-configmap 1 56s
[root@k8s-master charts]# kubectl describe cm mychart-configmap Name: mychart-configmap
Namespace: defaultLabels:
Annotations:
Data
====
myvalue:
----
Hello World
Events:
### 删除release ###
[root@k8s-master charts]# helm del veering-owl
release "veering-owl" deleted
[root@k8s-master charts]# kubectl get cm
No resources found.
[root@k8s-master charts]# helm ls
[root@k8s-master charts]# helm ls -a
NAME REVISION UPDATED STATUS CHART NAMESPACE
veering-owl 1 Mon Mar 12 15:09:37 2018 DELETED mychart-3-0.1.0 default
[root@k8s-master charts]# helm del --purge veering-owl
release "veering-owl" deleted
[root@k8s-master charts]# helm ls -a
Release的名称在不指定的情况下,随机产生。
使用helm get manifest releaseName
可以重新查看 install 时的输出。
上面的例子中,将name硬编码到文件中可能不是一个好主意,下面的配置使我们得到一个和release name名称相仿的CM:
[root@k8s-master charts]# vi mychart-3/templates/configmap.yamlapiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
[root@k8s-master charts]# helm install mychart-3/NAME: peddling-moose
LAST DEPLOYED: Mon Mar 12 15:37:46 2018NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
peddling-moose-configmap 1 0s
[root@k8s-master charts]# helm ls
NAME REVISION UPDATED STATUS CHART NAMESPACE
peddling-moose 1 Mon Mar 12 15:37:46 2018 DEPLOYED mychart-3-0.1.0 default
[root@k8s-master charts]# kubectl get cm
NAME DATA AGE
peddling-moose-configmap 1 12s
Release是helm的内置变量,上文有详细说明,或者官方文档
在模版中,使用闭合的{{
和}}
块来引用变量
变量本身支持namespace,Release前面的 “.” 表示最高级namespace,后面的 “.” 作为分隔符
关于values.yaml文件上文有简单说明过,这里做进一步说明:values.yaml文件中的内容可以通过Values对象引用,Values对象的内容包括:
helm install
或者 helm update
时 -f 参数指定的yaml文件,例如:helm install -f myvals.yaml ./mychart
--set
参数指定的内容,例如:helm install --set foo=bar ./mychart
—set具有最高优先级
[root@k8s-master charts]# vi mychart-3/values.yaml
favoriteDrink: coffee
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favoriteDrink }}
### 使用默认值 ###
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '46193'
[debug] SERVER: "127.0.0.1:46193"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: odd-wallaby
REVISION: 1
RELEASED: Mon Mar 12 16:06:58 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favoriteDrink: coffee
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: odd-wallaby-configmap
data:
myvalue: "Hello World"
drink: coffee
### 使用 --set 赋值 ###
[root@k8s-master charts]# helm install --debug --dry-run --set drink:=slurm mychart-3/
[debug] Created tunnel using local port: '40468'
[debug] SERVER: "127.0.0.1:40468"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: volted-chinchilla
REVISION: 1
RELEASED: Mon Mar 12 16:09:16 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
'drink:': slurm
COMPUTED VALUES:
'drink:': slurm
favoriteDrink: coffee
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: volted-chinchilla-configmap
data:
myvalue: "Hello World"
drink: coffee
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink }}
food: {{ .Values.favorite.food }}
[root@k8s-master charts]# vi mychart-3/values.yaml
favorite:
drink: coffee
food: pizza
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '42576'
[debug] SERVER: "127.0.0.1:42576"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: whimsical-rabbit
REVISION: 1
RELEASED: Mon Mar 12 16:13:41 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favorite:
drink: coffee
food: pizza
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: whimsical-rabbit-configmap
data:
myvalue: "Hello World"
drink: coffee
food: pizza
在下载或者安装Chart时,如果想删除掉某个已经定义在values.yaml文件中的值,可以将该值设置为 null:
[root@k8s-master charts]# helm install mychart-3/ --set favorite.food=null
NAME: mothy-hare
LAST DEPLOYED: Mon Mar 12 16:32:37 2018
NAMESPACE: default
STATUS: DEPLOYED
RESOURCES:
==> v1/ConfigMap
NAME DATA AGE
mothy-hare-configmap 3 0s
[root@k8s-master charts]# kubectl get cm
NAME DATA AGE
mothy-hare-configmap 3 5s
[root@k8s-master charts]# kubectl describe cm mothy-hare-configmap
Name: mothy-hare-configmap
Namespace: default
Labels:
Annotations:
Data
====drink:
----
coffee
food:
----
myvalue:
----
Hello World
Events:
这个在使用—debug –dry-run时,对应的值会被设置为 “null”,在k8s上则被设置为空。
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ quote .Values.favorite.drink }}
表现结果
apiVersion: v1
kind: ConfigMap
metadata:
name: lunging-stingray-configmap
data:
myvalue: "Hello World"
drink: "coffee
在这个例子中,我们调用了quote方法,并为其传递了一个参数.Values.favorite.drink
Helm有超过60个可用的方法,其中一部分上Go template language自己定义的,大部分其他的Sprig template library。
和UNIX操作系统类似,管道用于连接两个命令,将前一个命令的输出传递给后一个命令输入,对于上面的例子可以修改为:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
drink: {{ .Values.favorite.drink | quote }}
另一个例子:
[root@k8s-master charts]# vi mychart-3/templates/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 }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '34727'
[debug] SERVER: "127.0.0.1:34727"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: looming-pig
REVISION: 1
RELEASED: Mon Mar 12 16:47:24 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favorite:
drink: coffee
food: pizza
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: looming-pig-configmap
data:
myvalue: "Hello World"
drink: "coffeecoffeecoffeecoffeecoffee"
food: "PIZZA"
[root@k8s-master charts]# vi mychart-3/templates/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 }}
game: {{ .Values.favorite.game | default "NFS" | quote }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '46170'
[debug] SERVER: "127.0.0.1:46170"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: cautious-opossum
REVISION: 1
RELEASED: Mon Mar 12 16:50:59 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favorite:
drink: coffee
food: pizza
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: cautious-opossum-configmap
data:
myvalue: "Hello World"
drink: "coffeecoffeecoffeecoffeecoffee"
food: "PIZZA"
game: "NFS"
Values.yaml文件中并未定义game。
Helm实现了所有的操作符( eq
、 ne
、 lt
、 gt
、 and
、 or
等等),并且可以使用”()”进行分组
Helm支持的流程控制语句包括:if
/else
、with
、range
,接下来分别介绍
{{ if PIPELINE }}
# Do something
{{ else if OTHER PIPELINE }}
# Do something else
{{ else }}
# Default case
{{ end }}
[root@k8s-master charts]# vi mychart-3/templates/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 }}
game: {{ .Values.favorite.game | default "NFS" | quote }}
{{ if eq .Values.favorite.drink "coffee" }}
mug: true
{{ end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '36351'
[debug] SERVER: "127.0.0.1:36351"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: bald-newt
REVISION: 1
RELEASED: Mon Mar 12 17:11:01 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favorite:
drink: coffee
food: pizza
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: bald-newt-configmap
data:
myvalue: "Hello World"
drink: "coffeecoffeecoffeecoffeecoffee"
food: "PIZZA"
game: "NFS"
mug: true
可以看到正确输出了mug: true,但是格式不好看,莫名其妙多个一个空白行,这是因为helm在处理{{}}时,单纯的替换掉了{{}}块,保留了换行字符。
说明
PIPELINE 为一个boolean值,下面的所有内容都将被当作false处理:
a boolean false
a numeric zero
an empty string
a nil
(empty or null)
an empty collection (map
, slice
, tuple
, dict
, array
)
上面的例子中,多出了一行空白行,我们可以使用 {{-
去掉左边的空白字符,或者使用 -}}
去掉右边的空白字符,也可以同时使用,去掉两遍的空白字符。注意,换行也属于空白字符,例如:
aaa
{{- xxxx }}
bbb
将得到:
aaa
bbb
因为中间一行左边的换行符被去掉,但是右边的换行符被保留。
在看:
aaa
{{- xxxx -}}
bbb
将得到:
aaabbb
因为中间一行两遍的换行符都被去掉了。
因此,上面的例子可以修改为:
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 }}
game: {{ .Values.favorite.game | default "NFS" | quote }}
{{- if eq .Values.favorite.drink "coffee" }}
mug: true
{{- end }}
{{ with PIPELINE }}
# restricted scope
{{ end }}
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- with .Values.favorite }}
drink: {{ .drink | repeat 5 | quote }}
food: {{ .food | upper | quote }}
game: {{ .game | default "NFS" | quote }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '40227'
[debug] SERVER: "127.0.0.1:40227"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: maudlin-yak
REVISION: 1
RELEASED: Mon Mar 12 17:28:58 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favorite:
drink: coffee
food: pizza
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: maudlin-yak-configmap
data:
myvalue: "Hello World"
drink: "coffeecoffeecoffeecoffeecoffee"
food: "PIZZA"
game: "NFS"
With将默认的命名空间改变为”.Values.favorite”,使with块内部可以方便的引用变量。
With块内部不能在访问其他任何命令空间的内容,比如下面的写法将得到一个异常:
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- with .Values.favorite }}
drink: {{ .drink | repeat 5 | quote }}
food: {{ .food | upper | quote }}
game: {{ .game | default "NFS" | quote }}
release: {{ .Release.Name }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '38400'
[debug] SERVER: "127.0.0.1:38400"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
Error: render error in "mychart-3/templates/configmap.yaml": template: mychart-3/templates/configmap.yaml:11:22: executing "mychart-3/templates/configmap.yaml" at <.Release.Name>: can't evaluate field Name in type interface {}
可以修改为:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- with .Values.favorite }}
drink: {{ .drink | repeat 5 | quote }}
food: {{ .food | upper | quote }}
game: {{ .game | default "NFS" | quote }}
{{- end }}
release: {{ .Release.Name }}
Helm使用range来实现循环。
[root@k8s-master charts]# vi mychart-3/values.yaml
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
toppings: |-
{{- range .Values.pizzaToppings }}
- {{ . | title | quote }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '38008'
[debug] SERVER: "127.0.0.1:38008"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: illocutionary-molly
REVISION: 1
RELEASED: Mon Mar 12 17:43:35 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: illocutionary-molly-configmap
data:
toppings: |-
- "Mushrooms" - "Cheese" - "Peppers" - "Onions"
Range块中,”.“表示当前值,title是一个首字母大写的function,toppings后面的”|”表示后面的内容是一个可择行的大字符串,在之后的”-“表示去掉末尾的空白字符。
sizes: |-
{{- range tuple "small" "medium" "large" }}
- {{ . }}
{{- end }}
sizes: |-
- small
- medium
- large
使用自定义变量可以更好的使用 with
和 range
。在上面的例子中,我们使用下面的内容会出现异常:
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
release: {{ .Release.Name }}
{{- end }}
因为Release.Name不再with块范围内,一种可以避免错误的办法就是在with块之外定义一个变量,然后将Release.Name的值赋给这个变量:
[root@k8s-master charts]# vi mychart-3/values.yaml
favorite:
drink: coffee
food: pizza
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
{{- $relname := .Release.Name -}}
{{- with .Values.favorite }}
drink: {{ .drink | default "tea" | quote }}
food: {{ .food | upper | quote }}
release: {{ $relname }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '40191'
[debug] SERVER: "127.0.0.1:40191"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: moldy-labradoodle
REVISION: 1
RELEASED: Mon Mar 12 17:58:56 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
favorite:
drink: coffee
food: pizza
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: moldy-labradoodle-configmap
data:
drink: "coffee"
food: "PIZZA"
release: moldy-labradoodle
另外一个例子:定义循环下标
[root@k8s-master charts]# vi mychart-3/values.yaml
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
{{- range $index, $topping := .Values.pizzaToppings }}
{{ $index }}: {{ $topping }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '40932'
[debug] SERVER: "127.0.0.1:40932"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: wobbly-macaw
REVISION: 1
RELEASED: Mon Mar 12 18:02:04 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: wobbly-macaw-configmap
data:
0: mushrooms
1: cheese
2: peppers
3: onions
同理:
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
myvalue: "Hello World"
{{- range $key, $val := .Values.favorite }}
{{ $key }}: {{ $val | quote }}
{{- end}}
将得到:
# Source: mychart/templates/configmap.yamlapiVersion: v1
kind: ConfigMap
metadata:
name: eager-rabbit-configmap
data:
myvalue: "Hello World"
drink: "coffee"
food: "pizza"
命名模版允许我们定义模版块,从而将完整的大模版拆分成数个小模版。将重复的部门抽取来定义成命名模版使我们的模版文件看起来更清晰。模版的命名规范如下:
NOTES.txt
是一个例外,它并不包含kubernetes对象定义#####4.4.3.1、定义和引用模版
{{ define "MY_NAME" }}
# body of template here
{{ end }}
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
{{- define "my_labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}{{- end }}
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "my_labels" }}
data:
{{- range $index, $topping := .Values.pizzaToppings }}
{{ $index }}: {{ $topping }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '39896'
[debug] SERVER: "127.0.0.1:39896"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: yucky-tuatara
REVISION: 1
RELEASED: Tue Mar 13 09:26:51 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: yucky-tuatara-configmap
labels:
generator: helm
date: 2018-03-13
data:
0: mushrooms
1: cheese
2: peppers
3: onions
Helm建议我们将这类用来引用的模版定义到 _helpers.tpl
文件中:
[root@k8s-master charts]# vi mychart-3/templates/_helpers.tpl
{{- define "my_labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}{{- end }}
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "my_labels" }}
data:
{{- range $index, $topping := .Values.pizzaToppings }}
{{ $index }}: {{ $topping }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
默认情况下,命名模版不能够使用任何参数或者内建对象(如:Release、Values等),但是可以调用function,比如下面的例子:
[root@k8s-master charts]# vi mychart-3/templates/_helpers.tpl
{{/* Generate basic labels */}}{{- define "my_labels" }}
labels:
generator: helm
date: {{ now | htmlDate }}
chart: {{ .Chart.Name }}
version: {{ .Chart.Version }}{{- end }}
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "my_labels" }}
data:
{{- range $index, $topping := .Values.pizzaToppings }}
{{ $index }}: {{ $topping }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '44449'
[debug] SERVER: "127.0.0.1:44449"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: nonplussed-toucan
REVISION: 1
RELEASED: Tue Mar 13 11:03:16 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: nonplussed-toucan-configmap
labels:
generator: helm
date: 2018-03-13
chart:
version:
data:
0: mushrooms
1: cheese
2: peppers
3: onions
可以正常使用now和管道,但是
{{ .Chart.Name }}
和{{ .Chart.Version }}
的值为空
解决这个问题的方案就是在引用模版时,为其传递一个命名空间,将上述事例做如下改动:
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
{{- template "my_labels" . }}
data:
{{- range $index, $topping := .Values.pizzaToppings }}
{{ $index }}: {{ $topping }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '35723'
[debug] SERVER: "127.0.0.1:35723"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: dinky-worm
REVISION: 1
RELEASED: Tue Mar 13 11:06:57 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---
# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: dinky-worm-configmap
labels:
generator: helm
date: 2018-03-13
chart: mychart-3
version: 0.1.0
data:
0: mushrooms
1: cheese
2: peppers
3: onions
将
{{- template "my_labels" }}
修改为{{- template "my_labels" . }}
,”.” 表示顶级命名空间,你也可以更具需要传递.Values
或者.Values.favorite
等任何你想要传递的范围。
使用include引用模版允许我们使用管道和函数,看下面的例子:
### 假设有如下模版 ###
[root@k8s-master charts]# vi mychart-3/templates/_helpers.tpl
{{- define "mychart_app" -}}
app_name: {{ .Chart.Name }}
app_version: "{{ .Chart.Version }}+{{ .Release.Time.Seconds }}"
{{- end -}}
### 引用 ###
[root@k8s-master charts]# vi mychart-3/templates/configmap.yamlapiVersion: v1
kind: ConfigMapmetadata:
name: {{ .Release.Name }}-configmap
labels:
{{ template "mychart_app" .}}
data:
myvalue: "Hello World"
### 测试 ###
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '38909'
[debug] SERVER: "127.0.0.1:38909"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: kind-giraffe
REVISION: 1RELEASED: Tue Mar 13 11:15:34 2018CHART: mychart-3-0.1.0USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:MANIFEST:
---
# Source: mychart-3/templates/configmap.yamlapiVersion: v1
kind: ConfigMapmetadata:
name: kind-giraffe-configmap
labels:
app_name: mychart-3app_version: "0.1.0+1520910934"data:
myvalue: "Hello World"
[root@k8s-master charts]#
输出与预期有些出入,app_version: "0.1.0+1520910934"
没有对齐,因为模版中的内容是没有左边的空白符的,而我们也不能在定义模版时添加空白字符,并且 template
不支持函数,一种解决办法是:
### 修改上例引用 ###
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
labels:
{{ include "mychart_app" . | indent 4 }}
data:
myvalue: "Hello World"
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
注意:
{{ include "mychart_app" . | indent 4 }}
要顶格写,左边不要有空格
除了命名模版,helm还可以直接应用文件。Helm提供 .Files
对象来支持文件访问,并给出以下建议:
.Files
访问:.Files
object.[root@k8s-master charts]# vi mychart-3/config1.toml
message = Hello from config 1
[root@k8s-master charts]# vi mychart-3/config2.toml
message = This is config 2
[root@k8s-master charts]# vi mychart-3/config3.toml
message = Goodbye from config 3
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
{{- $files := .Files }}
{{- range tuple "config1.toml" "config2.toml" "config3.toml" }}
{{ . }}: |-
{{ $files.Get . }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '42465'
[debug] SERVER: "127.0.0.1:42465"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: loopy-mastiff
REVISION: 1
RELEASED: Tue Mar 13 12:14:13 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: loopy-mastiff-configmap
data:
config1.toml: |-
message = Hello from config 1
config2.toml: |-
message = This is config 2
config3.toml: |-
message = Goodbye from config 3
### 修改上面的事例 ###
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
{{- $files := .Files }}
{{ range $path, $bytes := .Files.Glob "**.toml" }}
{{ $path }}: |-
{{ $files.Get $path }}
{{ end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
官网上的例子:
{{ range $path := .Files.Glob "**.yaml" }}{{ $path }}: |
{{ .Files.Get $path }}{{ end }}
是有问题的,此时$path为文件内容的字节码,而非路径,而且在循环内部不能使用 .Files
,当然也不排除我做实验时姿势不对的原因!
### 两个便利的函数 ###
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
{{ (.Files.Glob "**.toml").AsConfig | indent 2 }}
{{ (.Files.Glob "**.toml").AsSecrets | indent 2 }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '40984'
[debug] SERVER: "127.0.0.1:40984"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: mangy-antelope
REVISION: 1
RELEASED: Tue Mar 13 12:26:12 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mangy-antelope-configmap
data:
config1.toml: |
message = Hello from config 1
config2.toml: |
message = This is config 2
config3.toml: |
message = Goodbye from config 3
config1.toml: bWVzc2FnZSA9IEhlbGxvIGZyb20gY29uZmlnIDEK
config2.toml: bWVzc2FnZSA9IFRoaXMgaXMgY29uZmlnIDIK
config3.toml: bWVzc2FnZSA9IEdvb2RieWUgZnJvbSBjb25maWcgMwo=
### 有一个便利的函数 ###
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
token: |-
{{ .Files.Get "config1.toml" | b64enc }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '40126'
[debug] SERVER: "127.0.0.1:40126"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: mortal-warthog
REVISION: 1
RELEASED: Tue Mar 13 12:28:25 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: mortal-warthog-configmap
data:
token: |-
bWVzc2FnZSA9IEhlbGxvIGZyb20gY29uZmlnIDEK
[root@k8s-master charts]# vi mychart-3/config1.toml
message = Hello from config 1
message = Hello from config 2
message = Hello from config 3
message = Hello from config 4
message = Hello from config 5
message = Hello from config 6
message = Hello from config 7
message = Hello from config 8
[root@k8s-master charts]# vi mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-configmap
data:
some-file.txt: |
{{- range .Files.Lines "config1.toml" }}
{{ . }}
{{- end }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '43350'
[debug] SERVER: "127.0.0.1:43350"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
NAME: giddy-rat
REVISION: 1
RELEASED: Tue Mar 13 12:32:59 2018
CHART: mychart-3-0.1.0
USER-SUPPLIED VALUES:
{}
COMPUTED VALUES:
pizzaToppings:
- mushrooms
- cheese
- peppers
- onions
HOOKS:
MANIFEST:
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: giddy-rat-configmap
data:
some-file.txt: |
message = Hello from config 1
message = Hello from config 2
message = Hello from config 3
message = Hello from config 4
message = Hello from config 5
message = Hello from config 6
message = Hello from config 7
message = Hello from config 8
NOTE.txt是一个文本文件,文件内容会在 chart install
或者 chart upgrade
之后输出到屏幕上,因此我们可以给出一些提示信息:
[root@k8s-master charts]# vi mychart-3/templates/NOTE.txt
Thank you for installing {{ .Chart.Name }}.
Your release is named {{ .Release.Name }}.
To learn more about the release, try:
$ helm status {{ .Release.Name }}
$ helm get {{ .Release.Name }}
[root@k8s-master charts]# helm install --debug --dry-run mychart-3/
[debug] Created tunnel using local port: '34825'
[debug] SERVER: "127.0.0.1:34825"
[debug] Original chart version: ""
[debug] CHART PATH: /root/charts/mychart-3
Error: YAML parse error on mychart-3/templates/NOTE.txt: error converting YAML to JSON: yaml: line 4: mapping values are not allowed in this context
---# Source: mychart-3/templates/configmap.yaml
apiVersion: v1
kind: ConfigMap
metadata:
name: whopping-wolf-configmap
data:
some-file.txt: |
message = Hello from config 1
message = Hello from config 2
message = Hello from config 3
message = Hello from config 4
message = Hello from config 5
message = Hello from config 6
message = Hello from config 7
message = Hello from config 8
---# Source: mychart-3/templates/NOTE.txt
Thank you for installing mychart-3.
Your release is named whopping-wolf.
To learn more about the release, try:
$ helm status whopping-wolf
$ helm get whopping-wolf
关于全局变量的部分内容已经在Chart一节中介绍过,更多详细内容可参考:https://docs.helm.sh/chart_template_guide/#subcharts-and-global-values
网盘链接:https://pan.baidu.com/s/1YUkLahajwqxH9hoPW74x9Q
解压:
tar -zxvf tiller-v2.8.1-tar.gz
导入:docker load -i tiller-v2.8.1-tar
调试模板可能会很棘手,因为模板在 Tiller 服务器而不是 Helm 客户端上渲染。然后渲染的模板被发送到 Kubernetes API 服务器,可能由于格式以外的原因,服务器可能会拒绝接收这些 YAML 文件。
有几个命令可以帮助您进行调试。
helm lint
是验证 chart 是否遵循最佳实践的首选工具
helm install --dry-run --debug
:我们已经知道了这个窍门。这是让服务器渲染你的模板,然后返回结果清单文件的好方法。
helm get manifest
:这是查看服务器上安装的模板的好方法。
当你的 YAML 没有解析,但想看看生成了什么时,检索 YAML 的一个简单方法是注释模板中的问题部分,然后重新运行 helm install --dry-run --debug
:
apiVersion: v1
# some: problem section
# {{ .Values.foo | quote }}
以上内容将被完整渲染并返回。
apiVersion: v1
# some: problem section
# "bar"
这提供了一种快速查看生成的容的方式,而不会由于YAML分析错误而被阻止。
写了个python脚本,放在helm应用文件夹外面 修改代码中的文件夹名称.可以生成new文件夹,里面是配置好yml文件
import os,io
import shutil
helm_app = 'prometheus'
# 执行命令获取返回值
status = os.popen("helm install --dry-run --debug "+helm_app)
result = status.read()
status.close()
# print(result)
# 正则匹配输出文件
canwrite=False
nowpath = ""
nowfile=None
allline = result.split('\n')
if os.path.exists('new'):
shutil.rmtree('new')
for line in allline:
if(line.startswith('# Source: ')):
if (nowpath):
nowfile.close()
nowpath = 'new/'+line.replace('# Source: ','')
nowdir = os.path.dirname(nowpath)
if(not os.path.exists(nowdir)):
os.makedirs(nowdir)
nowfile=open(nowpath,mode='w')
canwrite=True
if (canwrite and nowpath and nowfile):
nowfile.write(line+"\n")
print(line)