本文基于helm v2版本书写,当前主流使用helm v3版本。
helm v2和v3的区别 之一是移除tiller,基本使用的区别不大,helm v3可以参考本文。
【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。
随着业务容器化与向微服务架构转变,通过分解巨大的单体应用为多个服务的方式,分解了单体应用的复杂性,使每个微服务都可以独立部署和扩展,实现了敏捷开发和快速迭代和部署。但任何事情都有两面性,虽然微服务给我们带来了很多便利,但由于应用被拆分成多个组件,导致服务数量大幅增加,对于Kubernetest编排来说,每个组件有自己的资源文件,并且可以独立的部署与伸缩,这给采用Kubernetes做应用编排带来了诸多挑战:
而Helm恰好可以帮助我们解决上面问题。
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
本文简单介绍了Helm的用途、架构与实现。
利用Kubernetes部署一个应用,需要Kubernetes原生资源文件如deployment、replicationcontroller、service或pod 等。而对于一个复杂的应用,会有很多类似上面的资源描述文件,如果有更新或回滚应用的需求,可能要修改和维护所涉及的大量资源文件,且由于缺少对发布过的应用版本管理和控制,使Kubernetes上的应用维护和更新等面临诸多的挑战,而Helm可以帮我们解决这些问题。
Helm基本架构如下:

做为Kubernetes的一个包管理工具,Helm具有如下功能:
Helm有三个重要概念:
Helm有以下两个组成部分:
Helm Client是用户命令行工具,其主要负责如下:
Tiller Server是一个部署在Kubernetes集群内部的server,其与Helm client、Kubernetes API server进行交互。Tiller server主要负责如下:
简单的说,client管理charts,而server管理发布release。
Helm client
Helm server
说明:配置文件尽可能使用YAM格式
欢迎转载,请注明作者出处:张夏,FreeWheel Lead Engineer,Kubernetes中文社区
Kubernetes中文社区 于 2017-10-16 15:47:22 发布
【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
本文展示了Helm的Client、Server与本地Chart仓库的安装过程。
关于Helm简介请参考:简化Kubernetes应用部署工具-Helm简介
Helm Client安装过程如下:
下载 Helm 2.6.1:https://storage.googleapis.com/kubernetes-helm/helm-v2.6.1-linux-amd64.tar.gz
解包:tar -zxvf helm-v2.6.1-linux-amd64.tgz
helm二进制文件移到/usr/local/bin目录:
mv linux-amd64/helm /usr/local/bin/helm
Helm Tiller是Helm的server,Tiller有多种安装方式,比如本地安装或以pod形式部署到Kubernetes集群中。本文以pod安装为例,安装Tiller的最简单方式是helm init, 该命令会检查helm本地环境设置是否正确,helm init会连接kubectl默认连接的kubernetes集群(可以通过kubectl config view查看),一旦连接集群成功,tiller会被安装到kube-system namespace中。
执行helm init,该命令会在当前目录下创建helm文件夹即~/.helm,并且通过Kubernetes Deployment 部署tiller. 检查Tiller是否成功安装:
$ kubectl get po -n kube-systemNAME READY STATUS RESTARTS AGEtiller-deploy-1046433508-rj51m 1/1 Running 0 3m
由于 Tiller的数据存储于Kubernetes ConfigMap中,所以删除、升降级Tiller,原Helm部署的应用数据并不会丢失。
删除Tiller:
xxxxxxxxxxhelm reset
chart仓库用来存储和分享打包的chart,官方chart仓库由Kubernetes Charts维护, Helm允许我们创建私有chart仓库。
chart仓库是一个可用来存储index.yml与打包的chart文件的HTTP server,当要分享chart时,需要上传chart文件到chart仓库。任何一个能能够提供YAML与tar文件的HTTP server都可以当做chart仓库,比如Google Cloud Storage (GCS) bucket、Amazon S3 bucket、Github Pages或创建你自己的web服务器。
一个chart仓库由一个chart包与index.yaml文件组成,index.yaml记录了chart仓库中全部chart的索引,一个本地chart仓库的布局例子如下:
x/home/ts1/.helm/|-- cache| `-- archive| |-- drupal-0.9.2.tgz| `-- mariadb-1.0.3.tgz|-- plugins|-- repository| |-- cache| | |-- fantastic-charts-index.yaml| | |-- local-index.yaml -> /home/ts1/.helm/repository/local/index.yaml| | |-- mariadb-1.0.3.tgz-index.yaml| | |-- memcached-1.2.1.tgz-index.yaml| | |-- mychart_xia-0.1.0.tgz-index.yaml| | |-- mysql-0.2.8.tgz-index.yaml| | |-- stable-index.yaml| | |-- test-0.1.0.tgz-index.yaml| | `-- test-0.1.8.tgz-index.yaml| |-- local| | |-- index.yaml| | |-- mychart-0.1.0.tgz| | |-- mychart_xia-0.1.0.tgz| | |-- mysql-0.2.8.tgz| | |-- mysql-6.19.centos-29.tgz| | |-- test-0.1.0.tgz| | |-- test-0.1.8.tgz| | `-- test-0.1.9.tgz| `-- repositories.yaml`-- starters7 directories, 20 files
xxxxxxxxxxapiVersion: v1entries:mychart:- apiVersion: v1created: 2017-09-12T02:28:54.061070032Zdescription: A Helm chart for Kubernetesdigest: ae8d7138002d432014dc8638ec37202823e9207445caf08a660d154b26e936eaname: mycharturls:- http://127.0.0.1:8879/mychart-0.1.0.tgzversion: 0.1.0- apiVersion: v1created: 2017-09-12T03:08:14.02186072Zdescription: A Helm chart for Kubernetesdigest: sha256:2a05defa095d364f4efc789fd2417d07493757ebd74096e5f495c50604cf582dname: mycharturls:- http://127.0.0.1:8879/charts/mychart-0.1.0.tgzversion: 0.1.0
创建chart仓库有多种方式,本文以创建一个本地仓库为例:
xxxxxxxxxx$ helm serve –address 0.0.0.0:8879 –repo-path ./chartsRegenerating index. This may take a moment.Now serving you on 0.0.0.0:8879
上面步骤中,已经创建了一个本地的chart仓库,接下来讲述如何在chart仓库中维护chart。chart须遵循 SemVer 2 规则填写正确的版本格式。
一旦chart目录已经存在,将chart打包,并移动到的一个新建目录,通过helm repo index 命令将chart的metadata记录在index.yaml文件中。
xxxxxxxxxxhelm package mychartmkdir fantastic-chartsmv mychart-0.1.0.tgz fantastic-charts/helm repo index fantastic-charts –url http://bjo-ep-dep-039.dev.fwmrm.net:8879/charts
上传chart到chart仓库,通过helm repo add命令上传chart到chart仓库:
xxxxxxxxxx$ helm repo add fantastic-charts http://bjo-ep-dep-039.dev.fwmrm.net:8879/charts"fantastic-charts" has been added to your repositories
查看chart是否上传仓库成功:
xxxxxxxxxx$ helm repo listNAME URLchartsfantastic-charts http://bjo-ep-dep-039.dev.fwmrm.net:8879/charts
查找上传的chart:
xxxxxxxxxx$ helm search mychart -lNAME VERSION DESCRIPTIONlocal/mychart 0.1.0 A Helm chart for Kubernetes
欢迎转载,请注明作者出处:张夏,FreeWheel Lead Engineer,Kubernetes中文社区
weixin_34387468 于 2017-10-11 14:05:00 发布
【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。
随着业务容器化与向微服务架构转变,通过分解巨大的单体应用为多个服务的方式,分解了单体应用的复杂性,使每个微服务都可以独立部署和扩展,实现了敏捷开发和快速迭代和部署。但任何事情都有两面性,虽然微服务给我们带来了很多便利,但由于应用被拆分成多个组件,导致服务数量大幅增加,对于Kubernetest编排来说,每个组件有自己的资源文件,并且可以独立的部署与伸缩,这给采用Kubernetes做应用编排带来了诸多挑战:
而采用Helm,可以轻松的解决上面的问题。
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
本文的目标是展示Helm的一次发布的生命周期,包含了chart创建、更新、回滚、删除等,另外会展示helm的强大版本管理功能。
关于Helm安装、简介请参考: 简化Kubernetes应用部署工具-Helm安装 简化Kubernetes应用部署工具-Helm简介
获取版本为0.2.8的mysql并解压缩包:
xxxxxxxxxx$ helm fetch stable/mysql --version 0.2.8 --untar$ ls mysql/Chart.yaml README.md templates values.yaml
利用helm lint命令检查下载的chart是否存在问题:
xxxxxxxxxx$ helm lint mysql==> Linting mysqlLint OK1 chart(s) linted, no failures
利用helm create mychart命令创建一个mychart目录:
xxxxxxxxxx$ helm create mychartCreating mychart
生成的mychart的文件结构如下:
xxxxxxxxxxmychart/|-- charts|-- Chart.yaml|-- templates| |-- deployment.yaml| |-- _helpers.tpl| |-- ingress.yaml| |-- NOTES.txt| `-- service.yaml`-- values.yaml2 directories, 7 files
生成chart目录里有Chart.yaml, values.yaml 与 NOTES.txt等文件,下面分别对chart中几个重要文件解释: Chart.yaml 包含了chart的meta
chart安装有以下几种方式:
覆盖chart中的默认值,通过指定配置文件方式:
xxxxxxxxxxhelm install -f myvalues.yaml ./redis
或者通过–set key=value形式:
xxxxxxxxxx$ helm install --set name=prod ./redis
安装release名称为mysql例子如下,请注意NOTES中对Mysql的使用说明:
xxxxxxxxxx$ helm install -n mysql -f mysql/values.yaml --set resources.requests.memory=512Mi mysqlNAME: mysqlLAST DEPLOYED: Thu Sep 14 05:48:31 2017NAMESPACE: defaultSTATUS: DEPLOYEDRESOURCES:==> v1beta1/DeploymentNAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGEmysql-mysql 1 1 1 0 0s==> v1/SecretNAME TYPE DATA AGEmysql-mysql Opaque 2 0s==> v1/ConfigMapNAME DATA AGEmysql-configmap 1 0s==> v1/PersistentVolumeClaimNAME STATUS VOLUME CAPACITY ACCESSMODES STORAGECLASS AGEmysql-mysql Pending 0s==> v1/ServiceNAME CLUSTER-IP EXTERNAL-IP PORT(S) AGEmysql-mysql 10.98.221.43 <none> 3306/TCP 0sNOTES:MySQL can be accessed via port 3306 on the following DNS name from within your cluster:mysql-mysql.default.svc.cluster.localTo get your root password run:kubectl get secret --namespace default mysql-mysql -o jsonpath="{.data.mysql-root-password}" | base64 --decode; echoTo connect to your database:Run an Ubuntu pod that you can use as a client:kubectl run -i --tty ubuntu --image=ubuntu:16.04 --restart=Never -- bash -ilInstall the mysql client:$ apt-get update && apt-get install mysql-client -yConnect using the mysql cli, then provide your password:$ mysql -h mysql-mysql -p
通过helm status查看release状态:
xxxxxxxxxx$ helm status mysqlLAST DEPLOYED: Tue Sep 12 07:31:49 2017NAMESPACE: defaultSTATUS: DEPLOYED
或通过helm list -a查看全部的release,tag “-a”是查看全部的release,包括已部署、部署失败、正在删除、已删除release等。
xxxxxxxxxx$ helm list -a$ helm list -a | grep mysqlmysql 1 Tue Sep 12 07:31:49 2017 DEPLOYED mysql-0.2.8 default
Helm使用helm upgrade更新已安装的release:
xxxxxxxxxx$ helm upgrade mysql -f mysql/values.yaml --set resources.requests.memory=1024Mi mysql
查看指定release的历史部署版本信息:
xxxxxxxxxx$ helm hist mysqlREVISION UPDATED STATUS CHART DESCRIPTION1 Tue Sep 12 07:31:49 2017 SUPERSEDED mysql-0.2.8 Install complete2 Tue Sep 12 07:44:00 2017 DEPLOYED mysql-0.2.8 Upgrade complete
查看指定release的历史版本部署时部分配置信息,以resources.requests.memory为例,符合查看部署符合预期:即第一次部署resources.requests.memory设置为512Mi,第二次的升级resources.requests.memory设置为1024Mi:
xxxxxxxxxx$ helm get --revision 1 mysqlresources:requests:cpu: 100mmemory: 512Mi$ helm get --revision 2 mysqlresources:requests:cpu: 100mmemory: 1024Mi
回滚到第一次的版本:
xxxxxxxxxxhelm rollback --debug mysql 1[debug] Created tunnel using local port: '60303'[debug] SERVER: "localhost:60303"Rollback was a success! Happy Helming!
查看mysql release的版本信息,当前已经回滚到REVISION为1的版本:
xxxxxxxxxx$ helm hist mysqlREVISION UPDATED STATUS CHART DESCRIPTION1 Tue Sep 12 07:31:49 2017 SUPERSEDED mysql-0.2.8 Install complete2 Tue Sep 12 07:44:00 2017 SUPERSEDED mysql-0.2.8 Upgrade complete3 Tue Sep 12 08:50:48 2017 DEPLOYED mysql-0.2.8 Rollback to 1
利用helm delete命令删除一个chart:
xxxxxxxxxx$ helm delete mysqlrelease "mysql" deleted
确认chart是否删除:
xxxxxxxxxx$ helm ls -a mysqlNAME REVISION UPDATED STATUS CHART NAMESPACEmysql 3 Tue Sep 12 08:50:48 2017 DELETED mysql-0.2.8 default
即使删除的chart,其发布的历史信息还是继续被保存。
xxxxxxxxxx$ helm hist mysqlREVISION UPDATED STATUS CHART DESCRIPTION1 Tue Sep 12 07:31:49 2017 SUPERSEDED mysql-0.2.8 Install complete2 Tue Sep 12 07:44:00 2017 SUPERSEDED mysql-0.2.8 Upgrade complete3 Tue Sep 12 08:50:48 2017 DELETED mysql-0.2.8 Deletion complete
可以恢复一个已经删除的release:
xxxxxxxxxx$ helm rollback --debug mysql 2[debug] Created tunnel using local port: '37413'[debug] SERVER: "localhost:37413"Rollback was a success! Happy Helming!
如果希望彻底删除一个release,可以用如下命令:
xxxxxxxxxx$ helm delete --purge mysqlrelease "mysql" deleted
再次查看刚被删除的mysql release,提示已经无法找到,符合预期:
xxxxxxxxxx$ helm hist mysqlError: release: "mysql" not found
在上面例子中,已经展示了Helm对release的非常强大的版本管理功能,比如通过”helm list -a”查看有哪些release,通过” helm hist“查看某一个具体的release发布过的历史版本,以及通过” helm get --revision”,查看某个release的一次历史版本对应的具体应用配置信息等。即使已经被删除的release仍然有记录,并且通过Helm能够快速回滚到已删除release的某个发布过的历史版本。Helm的这些版本管理功能,Kubernetes原生并不支持。
欢迎转载,请注明作者出处:张夏,FreeWheel Lead Engineer,DockOne社区
原文发布时间为:2017-09-14
本文作者:张夏
本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。
原文标题:简化Kubernetes应用部署工具-Helm之应用部署
weixin_34310369 于 2017-10-11 14:03:00 发布
【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。
随着业务容器化与向微服务架构转变,通过分解巨大的单体应用为多个服务的方式,分解了单体应用的复杂性,使每个微服务都可以独立部署和扩展,实现了敏捷开发和快速迭代和部署。但任何事情都有两面性,虽然微服务给我们带来了很多便利,但由于应用被拆分成多个组件,导致服务数量大幅增加,对于Kubernetest编排来说,每个组件有自己的资源文件,并且可以独立的部署与伸缩,这给采用Kubernetes做应用编排带来了诸多挑战:
而采用Helm,可以轻松的解决上面的问题。
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
本文的目标是展示Helm如何做应用配置管理以及服务依赖的处理。
关于Helm安装、简介以及使用请参考: 简化Kubernetes应用部署工具-Helm安装 简化Kubernetes应用部署工具-Helm简介 简化Kubernetes应用部署工具-Helm之应用部署
前面 简化Kubernetes应用部署工具-Helm之应用部署 文章中展示了一次Helm发布的生命周期,包含了chart创建、更新、回滚、删除等。但这并不是我们使用Helm的唯一原因,我们还需要一个管理配置发布的工具。
Helm Chart模板采用go模板语言编写 Go template language,模板的值记录在values.yaml文件中。values.yaml文件中的值可以在安装chart过程中,通过参数–values YAML_FILE_PATH或–set key1=value1, key2=value2替换。
注意:模板语言中的引用数值型需要注意,不加引号,会被解释为数值。
创建自定义chart
xxxxxxxxxx$ helm create mychart
查看mychart结构:
xxxxxxxxxx|-- charts|-- Chart.yaml|-- templates| |-- deployment.yaml| |-- _helpers.tpl| |-- ingress.yaml| |-- NOTES.txt| `-- service.yaml`-- values.yaml2 directories, 7 files
生成chart目录里有Chart.yaml, values.yaml and NOTES.txt等文件,下面分别对chart中几个重要文件解释:
其中mychart/templates/的文件及其作用如下:
创建mychart/templates/configmap.yaml文件,内容如下:
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"
一个模板指令由{{}}标记。{{ .Release.Name }}会把release name插入模板。传入模板的值可被认作是namespaces对象,通过”.”来分隔namespaces元素。
对象通过模板引擎传给模板,有几种方式在模板内创建新的对象,比如后面要讲到的tuple。 模板内置对象请参见: https://docs.helm.sh/chart_tem ... jects
上面章节提到Helm模板提供了内置的对象,而Values做为4个内置对象之一,有4种来源:
说明:values.yaml默认会被引用,但其会被父chart中的values.yaml文件内容覆盖(overridden),而父chart中的values.yaml文件会被户用-f指定的文件内容覆盖,而用户用-f指定的文件会被–set参数传的值覆盖。简单的说,也就是上面4种Values来源的重要性由上到下的顺序,优先级由低到高。
如需要删除键值对中删除默认key,需要将key的值设置为null, helm也会将从覆盖的键值对中将其剔除。举例说明,期望将下面例子中的livenessProbe替换为 exec
xxxxxxxxxxlivenessProbe:httpGet:path: /user/loginport: httpinitialDelaySeconds: 120
在helm install 时,使用–set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt],结果如下:
xxxxxxxxxxlivenessProbe:httpGet:path: /user/loginport: httpexec:command:- cat- docroot/CHANGELOG.txtinitialDelaySeconds: 120
这并非我们的预期,而通过将livenessProbe.httpGet赋值为null:
xxxxxxxxxxhelm install stable/drupal --set image=my-registry/drupal:0.1.0 --set livenessProbe.exec.command=[cat,docroot/CHANGELOG.txt] --set livenessProbe.httpGet=null
前面展示的模板例子中,模板内容基本不去修改,但有一些情况下,我们希望提供给模板的数据对我们更加简单易用。例如对于 .Values对象注入模板的键值可利用模板提供的 quote功能引用。
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"drink: {{ quote .Values.favorite.drink }}food: {{ quote .Values.favorite.food }}
Helm 提供了超过60功能函数,其中一些定义在Go模板语言自身: Go template language . 这些函数是 Sprig template library的一部分。
Pipelines是模板语言的非常强大的特性之一,与Linux/Unix的pipeline类似,pipelines是把模板语言的多个命令通过 (|)的分隔形式,以描述的顺序的实现命令聚合功能。
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"drink: {{ .Values.favorite.drink | repeat 5 | quote }}food: {{ .Values.favorite.food | upper | quote }}
上面例子中,对.Values.favorite.drink | repeat 5 | quote的值coffee重复了5次后引用,而对.Values.favorite.food先做了一次大写转换然后加以引用。类似结果如下:
xxxxxxxxxxdata:myvalue: "Hello World"drink: "coffeecoffeecoffeecoffeecoffee"food: "PIZZA"
使用 DEFAULT功能
default是模板中经常使用一个功能,该功能是在模板中指定一个默认值。例如下面例子中,如果.Values.favorite.drink没有被赋值,那么模板被引用时,tea便为其默认值。
xxxxxxxxxxdrink: {{ .Values.favorite.drink | default "tea" | quote }}
对于Helm模板,类似eq, ne, lt, gt, and, or等操作符已经实现为函数,
Helm模板语言提供了如下控制结构:
除此之外,Helm还提供了一些命名模板的行为:
条件基本的控制结构如下:
xxxxxxxxxx{{ if PIPELINE }}# Do something{{ else if OTHER PIPELINE }}# Do something else{{ else }}# Default case{{ end }}
pipeline会被认为是false 如果值是下面几种类型:
下面configmap例子中,mug预期结果为true:
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"drink: {{ .Values.favorite.drink | default "tea" | quote }}food: {{ .Values.favorite.food | upper | quote }}{{ if eq .Values.favorite.drink "coffee" }}mug: true{{ end }}
执行helm install --dry-run --debug mychart命令:
xxxxxxxxxxdata:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: true
Helm模板语言对空格非常敏感,左侧有{{-(破折号后面有一个空格)表明空格需要被移除,而右侧 -}}表示空格会被消费。
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"drink: {{ .Values.favorite.drink | default "tea" | quote }}food: {{ .Values.favorite.food | upper | quote }}{{- if eq .Values.favorite.drink "coffee"}}mug: true{{- end}}
如果不加-,举例如下:
xxxxxxxxxx{{if eq .Values.favorite.drink "coffee"}}mug: true{{end}}
那么输出时会移除 {{ 与 }}而留下空格:
xxxxxxxxxxdata:myvalue: "Hello World"drink: "coffee"food: "PIZZA"mug: true
或者:
xxxxxxxxxxfood: {{ .Values.favorite.food | upper | quote }}{{- if eq .Values.favorite.drink "coffee" -}}mug: true{{- end -}}
结果如下,因为-}}已经把其所在的行移除了。
food: "PIZZA"mug:true
通过 with 与(.) 指定当前范围到某一个指定的对象,例如下面例子中 .Values.favorites,后面再引用drink与food 时,无需再指定Values.favorite
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"{{- with .Values.favorite }}drink: {{ .drink | default "tea" | quote }}food: {{ .food | upper | quote }}{{- end }}
像多数编程语言支持 for 与 foreach 等循环一样,Helm模板语言通过支持range操作符遍历一个集合。
下面例子中 values.yaml 文件部分内容如下:
xxxxxxxxxxfavorite:drink: coffeefood: pizzapizzaToppings:- mushrooms- cheese- peppers- onions
在ConfigMap中需要遍历Values.pizzaToppings的全部值,可以采用下面形式:
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmapdata:myvalue: "Hello World"{{- with .Values.favorite }}drink: {{ .drink | default "tea" | quote }}food: {{ .food | upper | quote }}{{- end }}toppings: |-{{- range .Values.pizzaToppings }}- {{ . | title | quote }}{{- end }}
其中 |-的作用是生成一个占用多行的字符串。
另外Helm提供了 tuple函数,可以在模板内建立一个list并且遍历它。例如:
xxxxxxxxxxsizes: |-{{- range tuple "small" "medium" "large" }}- {{ . }}{{- end }}
结果如下:
xxxxxxxxxxsizes: |-- small- medium- large
模板变量在 range的循环中非常有用,变量的定义格式为$name ,可通过 :=赋值。举例如下:
xxxxxxxxxxtoppings: |-{{- range $index, $topping := .Values.pizzaToppings }}{{ $index }}: {{ $topping }}{{- end }}
每循环一次 $index的值从0开始递增,并且将遍历的值赋给$topping
xxxxxxxxxxtoppings: |-0: mushrooms1: cheese2: peppers3: onions
或者,对应存在键值对的对象,可以用 range获取:
xxxxxxxxxxdata:myvalue: "Hello World"{{- range $key, $val := .Values.favorite }}{{ $key }}: {{ $val | quote }}{{- end}}
结果如下:
xxxxxxxxxxdata:myvalue: "Hello World"drink: "coffee"food: "pizza"
Helm允许我们创建一个命名模板,通过模板名称,可以在任何地方引用它。一般情况下命名模板会写在_helpers.tpl 中,并以形式 ({{/* ... */}})加上模板说明。比如下面例子中定义了一个my_labels命名模板,并且用 include通过 {{- include "my_labels" }}嵌入到configmap的metadata中。通常 include也可以用 template代替,但是 include在处理YAML文件的格式输出上会更胜一筹,另外 include可以包含一个变量的模板{{ include $mytemplate }}。
xxxxxxxxxx{{/* Generate basic labels */}}{{- define "my_labels" }}labels:generator: helmdate: {{ now | htmlDate }}{{- end }}
在configmap.yaml文件中引用该命名模板:
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmap{{- include "my_labels" . }}data:myvalue: "Hello World"{{- range $key, $val := .Values.favorite }}{{ $key }}: {{ $val | quote }}{{- end }}
需要注意的是,命名模板名称是全局的,如果存在多个同名的模板,最后被load到Tiller中的模板会被最终使用。另外模板的命名通常以chart的名字做为前缀,比如 {{ define "mychart.labels" }} 或 {{ define "mychart_labels" }}。
前面的命名模板中,并没有使用模板的内置对象。下面例子中在命名模板中使用了内置对象:
xxxxxxxxxx{{/* Generate basic labels */}}{{- define "my_labels" }}labels:generator: helmdate: {{ now | htmlDate }}chart: {{ .Chart.Name }}version: {{ .Chart.Version }}{{- end }}
在configmap中消费这个命名模板,注意在命名模板调用的末尾加上 ., indent 2表示引用的模板内容向右缩进2格。
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-configmaplabels:{{ include "mychart_app" . | indent 4 }}data:myvalue: "Hello World"{{- range $key, $val := .Values.favorite }}{{ $key }}: {{ $val | quote }}{{- end }}{{ include "mychart_app" . | indent 2 }}
上个章节中展示了几种创建和访问命名模板的方式,通过命名模板,可以很容易在一个模板中引用另外一个模板。但有的时候,我们还有导入一个普通文件内容来渲染模板的需求,而不仅仅是以模板的形式。Helm提供了一个内置 .Files对象。
Helm支持chart中存在一个普通类型的文件,这些文件也会被与其他模板文件一同打包发给给Tiller,但文件大小目前被限制在1M以内。由于安全原因,一般情况下 templates/的.Files对象不可访问,另外,chart并不会保留 UNIX mode的信息,文件层面的权限并不会影响对.Files对象的访问控制。
在 chart install 或 chart upgrade的尾部,会打印出用户帮助信息,该信息在 templates/NOTES.txt中定制。Helm并不强制提供用户帮助信息,但为了用户更加方便了解和使用所安装的应用,强烈建议在templates/NOTES.txt加上用户帮助信息。举例如下:
xxxxxxxxxxThank 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 }}
所谓subchart,指的是一个chart依赖其他chart,被依赖的chart即被称为subchart。
关于subchart的几点说明:
创建subchart的过程与普通chart基本一致,唯一需要注意的是,subchart需要创建在父chart的charts文件夹内,举例如下:
xxxxxxxxxx$ cd mychart/charts$ helm create mysubchartCreating mysubchart
为sub chart添加模板和values:
添加 values.yaml 到 mychart/charts/mysubchart :
xxxxxxxxxxdessert: cake
在 mychart/charts/mysubchart/templates/configmap.yaml 中创建ConfigMap模板:
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-cfgmap2data:dessert: {{ .Values.dessert }}
subchart可以单独安装:
xxxxxxxxxx$ helm install --dry-run --debug mychart/charts/mysubchart
父chart的values可以覆盖子chart,在mychart/values.yaml添加:
xxxxxxxxxxmysubchart:dessert: ice cream
然后执行 helm install --dry-run --debug mychart命令:
xxxxxxxxxx# Source: mychart/charts/mysubchart/templates/configmap.yamlapiVersion: v1kind: ConfigMapmetadata:name: unhinged-bee-cfgmap2data:dessert: ice cream
从结果可知,子chart的dessert的已由cake被替换为ice cream。
全部chart,包括子chart都可以访问全局chart values。一般全局chart values记录在父chart Values.global中。以mychart/values.yaml为例:
xxxxxxxxxxmysubchart:dessert: ice creamglobal:salad: caesar
那么在mysubchart/templates/configmap.yaml 中,即可以通过 .Values.global.salad 访问:
xxxxxxxxxxapiVersion: v1kind: ConfigMapmetadata:name: {{ .Release.Name }}-cfgmap2data:dessert: {{ .Values.dessert }}salad: {{ .Values.global.salad }}
Helm中父子chart之间可以共享模板,在任何一个chart中定义的块,对其他chart均可访问。
模板在Tiller server端渲染,而非Helm client端。经过Tiller server渲染的模板,最后发送给Kubernetes API server,而YAML文件除了格式问题外,可能还有其他多种因为会被Kubernetes API server拒绝。
欢迎转载,请注明作者出处:张夏,FreeWheel Lead Engineer,DockOne社区
原文发布时间为:2017-09-14
本文作者:张夏
本文来自云栖社区合作伙伴Dockerone.io,了解相关信息可以关注Dockerone.io。
原文标题:简化Kubernetes应用部署工具-Helm之Release配置
Kubernetes中文社区 于 2017-10-16 15:42:38 发布
【编者的话】微服务和容器化给复杂应用部署与管理带来了极大的挑战。Helm是目前Kubernetes服务编排领域的唯一开源子项目,做为Kubernetes应用的一个包管理工具,可理解为Kubernetes的apt-get / yum,由Deis 公司发起,该公司已经被微软收购。Helm通过软件打包的形式,支持发布的版本管理和控制,很大程度上简化了Kubernetes应用部署和管理的复杂性。
随着业务容器化与向微服务架构转变,通过分解巨大的单体应用为多个服务的方式,分解了单体应用的复杂性,使每个微服务都可以独立部署和扩展,实现了敏捷开发和快速迭代和部署。但任何事情都有两面性,虽然微服务给我们带来了很多便利,但由于应用被拆分成多个组件,导致服务数量大幅增加,对于Kubernetest编排来说,每个组件有自己的资源文件,并且可以独立的部署与伸缩,这给采用Kubernetes做应用编排带来了诸多挑战:
而Helm可以帮助我们解决这些问题。
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
本文主要对Helm Hook进行简单的介绍和使用说明。
关于Helm的安装、介绍与使用请参考:
简化Kubernetes应用部署工具-Helm安装 简化Kubernetes应用部署工具-Helm简介 简化Kubernetes应用部署工具-Helm之应用部署 简化Kubernetes应用部署工具-Helm之Release配置
在 简化Kubernetes应用部署工具-Helm之应用部署文章中,展示了采用Helm的一次应用release的生命周期过程,涵盖了发布(helm install)、更新(helm upgrade)、回滚(helm rollback)与删除(helm delete)等部分。为了允许chart开发者在应用release的生命周期中某些关键的时间点上,执行一些操作来更好的服务于release的需求,为此Helm提供了hook机制。
举例说明什么是一个Helm hook,比如ConfigMap或Secret要先于其他chart被加载,或希望在更新/回滚/删除一个release之前能够安全的关闭服务,都可以通过Helm hook实现。
Hook和普通模板文件基本相同,但其可以通过加入一些特殊的注释(annotation)与普通模板文件加以区分,下文会介绍hook的基本格式和用法。
Helm提供了如下hook供chart开发者使用:
上面已经提到,Hook允许chart开发者在release生命周期的一些时间点上可以执行一些操作。以helm install为例,默认情况下其基本生命周期如下:
如果在install的生命周期内定义pre-install与post-install 2个hook,那么install的生命周期会变成如下序列:
所谓hook就绪状态,取决于hook中定义的Kubernetes resource的类型,比如,对于Job类型的resource,就绪状态是job成功构建完成,如果job构建失败,release也失败了。而对于其他类型的resource,一旦resource加载(添加或更新)到Kubernetes,其状态被认为是就绪状态。
前面提到,一个hook可以对应多个resource,例如, secret与config map做为一个pre-install hook. 同时一个resource也可以有多个hook。
xxxxxxxxxx annotations: "helm.sh/hook": post-install,post-upgrade
Helm支持一个hook中的resource设置权重,Helm推荐通过对resource设置权重的方式,按权重大小加载resource。对于权重数值可以设为负数,权重的大小由负数到正数顺序。如果未设置权重,resource的加载是顺序执行的,但执行顺序并不会保证(Helm 2.3.0开始,相同权重的执行顺序按照字母a-z顺序执行,但未来版本可能会对相同权重的资源执行顺序有所变化)。
Hook与普通的Kubernetes声明文件一样,只是在文件metadata中加了特殊的注释(annotations)。但由于Hook文件是模板文件,所以其也具备全部的模板文件特性,包括从内置对象 .Values, .Release, and .Template获取渲染值等。
例如下面的模板中,定义了一个Job类型的Kubernetes resource,并定义了一个post-install hook,该hook的用途是当Kubernetes加载全部resource完毕后,按照Values对象设置的值sleepyTime执行sleep操作(如sleepyTime未设置,那么sleep 10秒)。
xxxxxxxxxxapiVersion: batch/v1kind: Jobmetadata: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": post-install"helm.sh/hook-weight": "-5""helm.sh/hook-delete-policy": hook-succeededspec:template:metadata:name: "{{.Release.Name}}"labels:heritage: {{.Release.Service | quote }}release: {{.Release.Name | quote }}chart: "{{.Chart.Name}}-{{.Chart.Version}}"spec:restartPolicy: Nevercontainers:- name: post-install-jobimage: "alpine:3.3"command: ["/bin/sleep","{{default "10" .Values.sleepyTime}}"]
Helm支持2种删除hook resource策略:
当使用"helm.sh/hook-delete-policy" 注释(annoation)时,删除hook resource支持2种策略:"hook-succeeded" 与 "hook-failed"。当删除策略为 "hook-succeeded"时,hook执行成功后,该hook会被Tiller删除。而删除策略为 "hook-failed"时,hook在执行过程中失败后,该hook会被Tiller删除。
Hook resource删除策略举例:
xxxxxxxxxx annotations: "helm.sh/hook-delete-policy": hook-succeeded
所谓服务依赖指的是启动一个服务,依赖于另外服务。这个时候我们就需要设置服务依赖关系来处理了。可以通过Helm hook来实现服务启动依赖的处理:
举例:serviceA服务依赖serviceB, serviceA的pre-install hook中实现
xxxxxxxxxxapiVersion: batch/v1kind: Jobmetadata:name: "{{.Release.Name}}"labels:chart: "{{.Chart.Name}}-{{.Chart.Version}}"annotations:"helm.sh/hook": pre-install"helm.sh/hook-weight": "-5"spec:template:metadata:name: "{{.Release.Name}}"labels:chart: "{{.Chart.Name}}-{{.Chart.Version}}"spec:restartPolicy: Nevercontainers:- name: pre-install-jobimage: "registry.docker.dev.fwmrm.net/busybox:latest"command: ['sh', '-c', "curl --connect-timeout 3 --max-time 5 --retry 10 --retry-delay 5 --retry-max-time 60 --retry-connrefused serviceB:portB/pathB/"]
Helm hook的是一种串行且阻塞式操作(blocking operation),所谓阻塞指的同一个chart,在同一个时刻只有一个hook执行,其他hook以及release的生命周期的其他行为活动(helm install, helm upgrade, helm rollback等)都会被阻塞(block),而串行指的是只有当一个hook成功执行完毕才会执行其他hook。
以上面的pre-install hook的例子说明,pre-install hook的job会先于helm install 执行,且在pre-install hook的job执行过程中,其他的release周期活动已经其他hook都不会被执行。当且仅当serviceB:portB/pathB/在指定时间内服务可达时,pre-install hook才会成功执行,余下的hook以及release其他操作才可以继续执行。
把被依赖的服务是否启动的逻辑判断,放在依赖服务的pre-install hook中,利用Helm hook的是一种串行且阻塞式操作(blocking operation)的特性,如果hook执行失败,那么对应的一次release也就失败了,这就达到了服务启动依赖的处理效果。
欢迎转载,请注明作者出处:张夏,FreeWheel Lead Engineer,Kubernetes中文社区
原文:简化Kubernetes应用部署工具-Helm之Hook
更新时间:2025-04-22 GMT+08:00
随着Helm v2 发布最终版本Helm 2.17.0,Helm v3 现在已是 Helm 开发者社区支持的唯一标准。为便于管理,建议用户尽快将模板切换至Helm v3格式。
当前社区从Helm v2演进到Helm v3,主要有以下变化:
移除tiller
Helm v3 使用更加简单和灵活的架构,移除了 tiller,直接通过kubeconfig连接apiserver,简化安全模块,降低了用户的使用壁垒。
改进了升级策略,采用三路策略合并补丁
Helm v2 使用双路策略合并补丁。在升级过程中,会对比最近一次发布的chart manifest和本次发布的chart manifest的差异,来决定哪些更改会应用到Kubernetes资源中。如果更改是集群外带的(比如通过kubectl edit),则修改不会被Helm识别和考虑。结果就是资源不会回滚到之前的状态。
Helm v3 使用三路策略来合并补丁,Helm在生成一个补丁时,会考虑之前原来的manifest的活动状态。因此,Helm在使用原来的chart manifest生成新补丁时会考虑当前活动状态,并将其与之前原来的 manifest 进行比对,并再比对新的 manifest 是否有改动,并进行自动补全,以此来生成最终的更新补丁。
详情及示例请见Helm官方文档:https://v3.helm.sh/docs/faq/changes_since_helm2
默认存储驱动程序更改为secrets
Helm v2 默认情况下使用 ConfigMaps 存储发行信息,而在 Helm v3 中默认使用 Secrets。
发布名称限制在namespace范围内
Helm v2 只使用tiller 的namespace 作为release信息的存储,这样全集群的release名字都不能重复。Helm v3只会在release安装的所在namespace记录对应的信息,这样release名称可在不同命名空间重用。应用和release命名空间一致。
校验方式改变
Helm v3 对模板格式的校验更加严格,如Helm v3 将chart.yaml的apiVersion从v1切换到v2,针对Helm v2的chart.yaml,强要求指定apiVersion为v1。可安装Helm v3客户端后,通过执行helm lint命令校验模板格式是否符合v3规范。
适配方案:根据Helm官方文档 https://helm.sh/docs/topics/charts/适配Helm v3模板,apiVersion字段必填。
废弃crd-install
Helm v3删除了crd-install hook, 并用chart中的crds目录替换。需要注意的是,crds目录中的资源只有在release安装时会部署,升级时不会更新,删除时不会卸载crds目录中的资源。若crd已存在,则重复安装不会报错。
适配方案:根据Helm官方文档 https://helm.sh/docs/chart_best_practices/custom_resource_definitions/, 当前可使用crds目录或者将crd定义单独放入chart。考虑到目前不支持使用Helm升级或删除CRD,推荐分隔chart,将CRD定义放入chart中,然后将所有使用该CRD的资源放到另一个 chart中进行管理。
未通过helm创建的资源不强制update,release默认不强制升级
Helm v3强制升级逻辑变化,不再是升级失败后走删除重建,而是直接走put更新逻辑。因此当前CCE release升级默认使用非强制更新逻辑,无法通过Patch更新的资源将导致release升级失败。若环境存在同名资源且无Helm V3的归属标记app.kubernetes.io/managed-by: Helm,则会提示资源冲突。
适配方案:删除相关资源,并通过Helm创建。
Release history数量限制更新
为避免release 历史版本无限增加,当前release升级默认只保留最近10个历史版本。
更多变化和详细说明请参见Helm官方文档