kubernetes中helm的安装和部署
一、Helm介绍
helm是基于kubernetes 的包管理器。它之于 kubernetes 就如 yum 之于 centos,pip 之于 python,npm 之于 javascript
那 helm 的引入对于管理集群有哪些帮助呢?
- 更方便地部署基础设施,如
gitlab,postgres,prometheus,grafana等 - 更方便地部署自己的应用,为公司内部的项目配置 Chart,使用
helm结合 CI,在 k8s 中部署应用一行命令般简单
1、Helm用途
Helm把Kubernetes资源(比如deployments、services或 ingress等) 打包到一个chart中,而chart被保存到chart仓库。通过chart仓库可用来存储和分享chart。Helm使发布可配置,支持发布应用配置的版本管理,简化了Kubernetes部署应用的版本控制、打包、发布、删除、更新等操作。
做为Kubernetes的一个包管理工具,用来管理charts--预先配置好的安装包资源,有点类似于Ubuntu的APT和CentOS中的yum。
Helm具有如下功能:
- 创建新的chart
- chart打包成tgz格式
- 上传chart到chart仓库或从仓库中下载chart
- 在Kubernetes集群中安装或卸载chart
- 管理用Helm安装的chart的发布周期
使用Helm可以完成以下事情:
- 管理Kubernetes manifest files
- 管理Helm安装包charts
- 基于chart的Kubernetes应用分发
2、Helm组件及相关术语
开始接触Helm时遇到的一个常见问题就是Helm中的一些概念和术语非常让人迷惑,我开始学习Helm就遇到这个问题。
因此我们先了解一下Helm的这些相关概念和术语。
包管理工具:
Helm: Kubernetes的应用打包工具,也是命令行工具的名称。
Helm CLI:是 Helm 客户端,可以在本地执行
Tiller: Helm的服务端,部署在Kubernetes集群中,用于处理Helm的相关命令。
helm的作用:像centos7中的yum命令一样,管理软件包,只不过helm这儿管理的是在k8s上安装的各种容器。
tiller的作用:像centos7的软件仓库一样,简单说类似于/etc/yum.repos.d目录下的xxx.repo。
Repoistory: Helm的软件仓库,repository本质上是一个web服务器,该服务器保存了chart软件包以供下载,并有提供一个该repository的chart包的清单文件以供查询。在使用时,Helm可以对接多个不同的Repository。
Charts:是一个Helm的程序包,它包含了运行一个kubernetes应用程序所需要的镜像、依赖关系和资源定义等。
Release:应用程序运行Charts之后,得到的一个实例。
需要特别注意的是, Helm中提到的Release和我们通常概念中的版本有所不同,这里的Release可以理解为Helm使用Chart包部署的一个应用实例。
其实Helm中的Release叫做Deployment更合适。估计因为Deployment这个概念已经被Kubernetes使用了,因此Helm才采用了Release这个术语。
命令介绍
http://hub.kubeapps.com/completion # 为指定的shell生成自动完成脚本(bash或zsh)create # 创建一个具有给定名称的新 chartdelete # 从 Kubernetes 删除指定名称的 releasedependency # 管理 chart 的依赖关系fetch # 从存储库下载 chart 并(可选)将其解压缩到本地目录中get # 下载一个命名 releasehelp # 列出所有帮助信息history # 获取 release 历史home # 显示 HELM_HOME 的位置init # 在客户端和服务器上初始化Helminspect # 检查 chart 详细信息install # 安装 chart 存档lint # 对 chart 进行语法检查list # releases 列表package # 将 chart 目录打包成 chart 档案plugin # 添加列表或删除 helm 插件repo # 添加列表删除更新和索引 chart 存储库reset # 从集群中卸载 Tillerrollback # 将版本回滚到以前的版本search # 在 chart 存储库中搜索关键字serve # 启动本地http网络服务器status # 显示指定 release 的状态template # 本地渲染模板test # 测试一个 releaseupgrade # 升级一个 releaseverify # 验证给定路径上的 chart 是否已签名且有效version # 打印客户端/服务器版本信息dep # 分析 Chart 并下载依赖3、组件架构

Helm Client 是用户命令行工具,其主要负责如下:
- 本地 chart 开发
- 仓库管理
- 与 Tiller sever 交互
- 发送预安装的 chart
- 查询 release 信息
- 要求升级或卸载已存在的 release
Tiller Server是一个部署在Kubernetes集群内部的 server,其与 Helm client、Kubernetes API server 进行交互。Tiller server 主要负责如下:
- 监听来自 Helm client 的请求
- 通过 chart 及其配置构建一次发布
- 安装 chart 到
Kubernetes集群,并跟踪随后的发布 - 通过与
Kubernetes交互升级或卸载 chart - 简单的说,client 管理 charts,而 server 管理发布 release
helm客户端
helm客户端是一个命令行工具,负责管理charts、reprepository和release。它通过gPRC API(使用kubectl port-forward将tiller的端口映射到本地,然后再通过映射后的端口跟tiller通信)向tiller发送请求,并由tiller来管理对应的Kubernetes资源。
tiller服务端
tiller接收来自helm客户端的请求,并把相关资源的操作发送到Kubernetes,负责管理(安装、查询、升级或删除等)和跟踪Kubernetes资源。为了方便管理,tiller把release的相关信息保存在kubernetes的ConfigMap中。
tiller对外暴露gRPC API,供helm客户端调用。
4、工作原理
Chart Install 过程:
- Helm从指定的目录或者tgz文件中解析出Chart结构信息
- Helm将指定的Chart结构和Values信息通过gRPC传递给Tiller
- Tiller根据Chart和Values生成一个Release
- Tiller将Release发送给Kubernetes运行。
Chart Update过程:
- Helm从指定的目录或者tgz文件中解析出Chart结构信息
- Helm将要更新的Release的名称和Chart结构,Values信息传递给Tiller
- Tiller生成Release并更新指定名称的Release的History
- Tiller将Release发送给Kubernetes运行
Chart Rollback
- helm将会滚的release名称传递给tiller
- tiller根据release名称查找history
- tiller从history中获取到上一个release
- tiller将上一个release发送给kubernetes用于替换当前release
Chart处理依赖
Tiller 在处理 Chart 时,直接将 Chart 以及其依赖的所有 Charts 合并为一个 Release,同时传递给 Kubernetes。因此 Tiller 并不负责管理依赖之间的启动顺序。Chart 中的应用需要能够自行处理依赖关系。
二、安装部署helm工具(客户端)

前提要求
- Kubernetes1.5以上版本
- 集群可访问到的镜像仓库
- 执行helm命令的主机可以访问到kubernetes集群
(1)下载helm的包
[root@master ~]#docker pull gcr.io/kubernetes-helm/tiller:v2.14.3[root@master ~]# wget https://get.helm.sh/helm-v2.14.3-linux-amd64.tar.gz(2)把helm包的命令,复制到本地
[root@master helm]# mv linux-amd64/helm /usr/local/bin///移动命令目录到/usr/local/bin/[root@master helm]# chmod +x /usr/local/bin/helm //给予执行权限[root@master helm]# helm help//验证是否安装成功(3)设置命令自动补全
[root@master helm]# echo 'source <(helm completion bash)' >> /etc/profile[root@master helm]# . /etc/profile//刷新一下2、安装Tiller server(服务端,需要创建授权用户)
[root@master ~]# vim tiller-rbac.yaml #创建授权用户apiVersion: v1kind: ServiceAccountmetadata: name: tiller namespace: kube-system---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: tillerroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: cluster-adminsubjects: - kind: ServiceAccount name: tiller namespace: kube-system执行一下
[root@master ~]# kubectl apply -f tiller-rbac.yaml (1)Tiller server的环境初始化
[root@master helm]# helm init --service-account=tiller//helm的服务端就是Tiller(因为是访问外国的网站,可能需要多次执行)查看一下
[root@master helm]# kubectl get deployment. -n kube-system 现在发现没有开启,那是因为默认下载的Google的镜像,下载不下来
(2)设置镜像源改为阿里云的
[root@master helm]# helm repo add stable https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts查看一下
[root@master helm]# helm version3、部署一个实例helm install + charts -n Release名称。
1、关于这个Release的描述。
2、关于这个Release资源的描述。
3、怎么使用这个Release。
(1)Helm部署安装一个Mysql服务。
[root@master ~]# helm search mysql//查看关于mysqk的Charts包[root@master ~]# helm install stable/mysql -n mysql //基于stable/mysql包安装一个名为MySQL的服务查看一下
[root@master ~]# helm list(2)Charts包解压过后的目录:
[root@master ~]# cd .helm/cache/archive//查看helm缓存[root@master archive]# ls[root@master mysql]# helm fetch stable/mysql//直接下载stable/mysql的chart包[root@master archive]# tar -zxf mysql-0.3.5.tgz //解压一下MySQL包[root@master archive]# tree -C mysql //树状图查看解压出来的mysql目录,-C:显示颜色Chart.yaml:这个chart包的概要信息。(name和version 这两是必填项,其他可选。)
README md:是这个chart包的一个使用帮助文档。
templates:chart包内各种资源对象的模板。
deployment.yaml:deployment 控制器的 Go 模板文件
helpers.tpl:以 开头的文件不会部署到 k8s 上,可用于定制通用信息
NOTES.txt:Chart 部署到集群后的一些信息
service.yaml:service 的 Go 模板文件
values.yaml:是这个chart包的默认的值,可以被templet内的yaml文件使用。
(3)Helm部署安装-个Mysql服务。
[root@master ~]# docker pull mysql:5.7.14[root@master ~]# docker pull mysql:5.7.15[root@master ~]# docker pull busybox:1.25.0下载所需的mysql镜像[root@master ~]# helm delete mysql --purge //删除之前的MySQL服务并清除缓存(4)设置共享目录
[root@master ~]# yum -y install rpcbind nfs-utils//安装nfs[root@master ~]# mkdir /data//创建共享目录[root@master ~]# vim /etc/exports/data *(rw,sync,no_root_squash)//设置共享目录权限[root@master ~]# systemctl restart rpcbind[root@master ~]# systemctl restart nfs-server//重启nfs服务测试一下[root@master ~]# showmount -e(5)创建pv
[root@master xgp]# vim nfs-pv1.yml apiVersion: v1kind: PersistentVolumemetadata: name: mysqlpvspec: capacity: storage: 8Gi accessModes: - ReadWriteOnce persistentVolumeReclaimPolicy: Recycle nfs: path: /data/mysqlpv server: 192.168.1.21[root@master xgp]# mkdir /data/mysqlpv//创建所需目录执行一下
[root@master xgp]# kubectl apply -f nfs-pv1.yml查看一下
[root@master xgp]# kubectl get pv(6)创建一个mysql服务
[root@master xgp]# helm install stable/mysql -n bdqn-mysql --set mysqlRootPassword=123.com查看一下
[root@master xgp]# kubectl get pod(7)进入pod并查看一下
[root@master xgp]# kubectl exec -it bdqn-mysql-mysql-7b89c7b99-8ff2r -- mysql -u root -p123.commysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys |+--------------------+4 rows in set (0.01 sec)4、mysql服务的升级与回滚
(1)mysql服务的升级
[root@master mysql]# helm upgrade --set imageTag=5.7.15 bdqn-mysql stable/mysql -f values.yaml 查看一下
[root@master mysql]# kubectl get deployments. -o wide(2)mysql服务的回滚
[root@master mysql]# helm history bdqn-mysql//查看历史版本回滚到版本一
[root@master mysql]# helm rollback bdqn-mysql 1 查看一下
[root@master mysql]# kubectl get deployments. -o wide三、小实验
在部署mysql的时候,如何开启storageclass,以及如何将service资源对象的类型更改为NodePort, 如何使用?
将上述部署的实例进行升级回滚操作。升级的时候镜像改为: mysql:5.7.15版本。回滚到最初的版本。
1、基于NFS服务,创建NFS服务。
下载nfs所需安装包
[root@node02 ~]# yum -y install nfs-utils rpcbind创建共享目录
[root@master ~]# mkdir -p /xgp/wsd创建共享目录的权限
[root@master ~]# vim /etc/exports/xgp *(rw,sync,no_root_squash)开启nfs和rpcbind(三台都要)
[root@master ~]# systemctl start nfs-server.service [root@master ~]# systemctl start rpcbind测试一下
[root@master ~]# showmount -e2、创建StorageClass资源对象。
(1)创建rbac权限。
[root@master yaml]# vim rbac.yaml apiVersion: v1kind: ServiceAccountmetadata: name: nfs-provisioner namespace: default---apiVersion: rbac.authorization.k8s.io/v1kind: ClusterRolemetadata: name: nfs-provisioner-runner namespace: defaultrules: - apiGroups: [""] resources: ["persistentvolumes"] verbs: ["get", "list", "watch", "create", "delete"] - apiGroups: [""] resources: ["persistentvolumeclaims"] verbs: ["get", "list", "watch", "update"] - apiGroups: ["storage.k8s.io"] resources: ["storageclasses"] verbs: ["get", "list", "watch"] - apiGroups: [""] resources: ["events"] verbs: ["watch", "create", "update", "patch"] - apiGroups: [""] resources: ["services", "endpoints"] verbs: ["get","create","list", "watch","update"] - apiGroups: ["extensions"] resources: ["podsecuritypolicies"] resourceNames: ["nfs-provisioner"] verbs: ["use"]---kind: ClusterRoleBindingapiVersion: rbac.authorization.k8s.io/v1metadata: name: run-nfs-provisionersubjects: - kind: ServiceAccount name: nfs-provisioner namespace: default #必写字段roleRef: kind: ClusterRole name: nfs-provisioner-runner apiGroup: rbac.authorization.k8s.io执行一下
[root@master yaml]# kubectl apply -f rbac.yaml (2)创建Deployment资源对象,用Pod代替 真正的NFS服务。
[root@master yaml]# vim nfs-deployment.yaml apiVersion: extensions/v1beta1kind: Deploymentmetadata: name: nfs-client-provisionerspec: replicas: 1 strategy: type: Recreate template: metadata: labels: app: nfs-client-provisioner spec: serviceAccount: nfs-provisioner containers: - name: nfs-client-provisioner image: registry.cn-hangzhou.aliyuncs.com/open-ali/nfs-client-provisioner volumeMounts: - name: nfs-client-root mountPath: /persistentvolumes env: - name: PROVISIONER_NAME value: xgp - name: NFS_SERVER value: 192.168.1.21 - name: NFS_PATH value: /xgp/wsd volumes: - name: nfs-client-root nfs: server: 192.168.1.21 path: /xgp/wsd执行一下
[root@master yaml]# kubectl apply -f nfs-deployment.yaml 查看一下
[root@master yaml]# kubectl get pod(3)创建storageclass的yaml文件
[root@master yaml]# vim xgp-storageclass.yaml apiVersion: storage.k8s.io/v1kind: StorageClassmetadata: name: xgp-nfsprovisioner: xgp #通过provisioner字段关联到上述DeployreclaimPolicy: Retain执行一下
[root@master yaml]# kubectl apply -f test-storageclass.yaml查看一下
[root@master yaml]# kubectl get sc3、创建一个mysql服务
[root@master ~]# docker pull mysql:5.7.14[root@master ~]# docker pull mysql:5.7.15[root@master ~]# docker pull busybox:1.25.0//下载所需镜像[root@master yaml]# helm fetch stable/mysql//直接下载stable/mysql的chart包[root@master yaml]# tar -zxf mysql-0.3.5.tgz //解压mysql包[root@master yaml]# cd mysql/[root@master mysql]# vim values.yaml //修改values.yaml文件,添加storageClass存储卷和更改svc的模式为NodePort[root@master mysql]# helm install stable/mysql -n xgp-mysql --set mysqlRootPassword=123.com -f values.yaml //基于values.yaml和stable/mysql开启一个密码为123.com的mysqlpod查看一下
[root@master mysql]# kubectl get svc[root@master mysql]# kubectl get pod -o wide4、进入pod并查看一下
[root@master mysql]# kubectl exec -it xgp-mysql-mysql-67c6fb5f9-dn7s2 -- mysql -u root -p123.commysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys |+--------------------+4 rows in set (0.01 sec)5、mysql服务的升级与回滚
(1)mysql服务的升级
[root@master mysql]# helm upgrade --set imageTag=5.7.15 xgp-mysql stable/mysql -f values.yaml 查看一下
[root@master mysql]# kubectl get deployments. -o wide(2)服务的回滚
[root@master mysql]# helm history xgp-mysql//查看历史版本回滚到版本一
[root@master mysql]# helm rollback xgp-mysql 1 查看一下
[root@master mysql]# kubectl get deployments. -o wide6、进入pod并查看一下
[root@master mysql]# kubectl exec -it xgp-mysql-mysql-67c6fb5f9-dn7s2 -- mysql -u root -p123.commysql> show databases;+--------------------+| Database |+--------------------+| information_schema || mysql || performance_schema || sys |+--------------------+4 rows in set (0.01 sec)四、总结
Helm作为kubernetes应用的包管理以及部署工具,提供了应用打包,发布,版本管理以及部署,升级,回退等功能。Helm以Chart软件包的形式简化Kubernetes的应用管理,提高了对用户的友好性。
使用心得
helm 客户端的功能非常简单,直接参考官网文档即可。
列一下相关使用心得:
- Helm 的所有功能都是围绕着 chart、release 和 repository 的;
- 仅初始化客户端相关配置且仅建立本地仓库,可执行
helm init --client-only --skip-refresh; - 查找 chart 的方式是通过 HELM_HOME(默认是 ~/.helm 目录)下的 repositories 目录进行的,几个重要文件或目录为 cache、repositories/cache;
- 修改 chart index.yaml 的 url,可执行
helm serve --url http://demo.com来重新 reindex; - 依赖关系管理,requirements定义,子 chart 值定义;
- install 、 update 的方式管理不方便,这样需要维护 chart 的版本关系,集成 install 和 update ,组成类似 k8s 中的 apply 命令;
- package 命令 -u 可以更新依赖,建议推到 repositiories 前先 package ,否则后期可能出现依赖检测不全的错误;
- release 相关的信息存储在 k8s 的 configmap 中,命名形式为 release_name.v1 的格式。 rollback 相关功能就是通过存储在 configmap 中的信息进行回滚的;
- Helm 客户端与 k8s 中的 TillerServer 是通过 k8s 提供的 port-forward 来实现的,而 port-forward 需要在指定节点上部署 socat;
- TillerServer 可以不部署在 k8s 中, 此时 Helm 客户端需要通过 HELM_HOST 环境变量来指定 TillerServer 的地址和端口;
- 建议 TillerServer 部署在 k8s 中,既然 Helm 为 CNCF 的一员,那么就尽量把云原生做到极致吧;
- 写 chart 时多参考官方最佳实践,The Chart Best Practices Guide;
不足
Helm 虽然提供了 install、update 命令来安装或更新对应的 release,但这给使用者带来了需要维护 release 状态的压力。举个例子,在还没安装 release 之前,release 是不存在的,update 操作是会失败的。反之已经存在的 release,install 操作也会失败。其实大部分情况下我是不需要知道 release 的状态的,不管它存在还是不存在,我执行的命令就是我希望的意图,我希望 release 能成为我执行命令后的状态。这一点上 k8s 的 apply 命令就非常好,不需要用户来维护资源的状态。