在操作系统当中,用户通常通过软件包管理工具来安装或者卸载软件,例如RPM、YUM以及Apt等。通过这些软件包管理工具,可以非常方便地对当前系统中的软件包进行管理。Kubernetes也提供了相应的软件包管理功能,即Helm。本章将对Helm的使用方法进行介绍。
本章涉及的知识点有:
Helm是Kubernetes生态系统中的一个软件包管理工具。本节将介绍Helm中的相关概念和基本工作原理,并通过一个具体的示例学习如何使用Helm打包、分发、安装、升级及回退Kubernetes应用。
Kubernetes是一个提供基于容器的应用集群管理解决方案,Kubernetes为容器化应用提供了部署运行、资源调度、服务发现和动态伸缩等一系列完整功能。
Kubernetes的核心设计理念是,用户定义要部署的应用程序的规则,而Kubernetes则负责按照定义的规则部署并运行应用程序。如果应用程序出现问题导致偏离了定义的规格,Kubernetes负责对其进行修正。例如,用户定义的应用规则要求部署两个Pod,如果在运行过程中,其中一个Pod异常终止了,Kubernetes会检查到并重新启动一个新的Pod实例。
用户通过使用Kubernetes API对象来描述应用程序规则,包括Pod、Service、Volume、Namespace、ReplicaSet、Deployment以及Job等。通常情况下,管理员在定义这些资源对象的时候,需要编辑一系列的YAML配置文件,然后通过Kubernetes命令行工具kubectl调用Kubernetes API进行部署。
以一个典型的三层应用Wordpress为例,该应用程序就涉及多个Kubernetes API对象,而要描述这些Kubernetes API对象,就可能要同时维护多个YAML文件。
因此,在进行Kubernetes软件部署时,管理员面临下述几个问题:
Helm的出现就是为了很好地解决上面这些问题。
Helm是一个用于Kubernetes应用的软件包管理工具,主要用来管理Charts。有点类似于Ubuntu中的APT或CentOS中的YUM。
对于应用发布者而言,可以通过Helm打包应用、管理应用依赖关系、管理应用版本,并发布应用到软件仓库。
对于使用者而言,使用Helm后就不用再编写复杂的YAML应用部署文件,可以以简单的方式在Kubernetes上查找、安装、升级、回滚、卸载应用程序。
简单地讲,Helm是一个命令行的客户端工具,主要用于Kubernetes应用程序的创建、打包、发布以及创建和管理本地和远程的软件仓库。
Tiller是Helm的服务端,部署在Kubernetes集群中。Tiller用于接收Helm的请求,并根据Chart生成Kubernetes的部署文件,即后面将要介绍的Release,然后提交给Kubernetes创建应用。Tiller还提供了Release的升级、删除、回滚等一系列功能。
Chart即Helm所管理的软件包,采用TAR格式,类似于APT的DEB包或者YUM的RPM包,其包含了一组定义Kubernetes资源相关的YAML配置文件,可以在部署应用的时候自定义应用程序的一些元数据,以便于应用程序的分发。
Helm的软件存储库称为Repository。Repository本质上是一个Web服务器,该服务器保存了一系列的Chart软件包以供用户下载,并且提供了一个该Repository所包含的Chart包的清单文件以供查询。Helm可以同时管理多个不同的Repository。
使用helm install命令在Kubernetes集群中部署的Chart称为Release。Release实际上是Helm为某个Chart创建的实例。
Helm的安装方式很多,对于初学者来说,二进制软件包的方式最为简单。本节将介绍如何采用二进制的方式安装。更多安装方法可以参考Helm的官方帮助文档。
用户可以通过两种方式来安装Helm客户端,其中一种方式是通过官方提供的脚本一键式安装,另外一种方式是手动下载二进制文件。下面分别介绍这两种安装方式。
(1)首先介绍通过脚本一键式安装Helm客户端。Helm在其官方的GitHub上面提供了一个名为get的Shell脚本文件,其网址如下:
https://github.com/helm/helm/blob/master/scripts/get
RAW格式代码的网址如下:
https://raw.githubusercontent.com/helm/helm/master/scripts/get
用户可以通过以下命令将其代码下载到本地:
[root@localhost ~]# curl https://raw.githubusercontent.com/helm/helm/
master/scripts/get > get_helm.sh
其中curl命令是一个非常强大的HTTP客户端命令,大于号为Shell的重定向运算符,其功能是将curl命令的输出结果保存为get_helm.sh文件。下载完成后,修改get_helm.sh文件的权限,使其可以执行,命令如下:
[root@localhost ~]# chmod 700 get_helm.sh
最后执行该脚本文件,安装Helm客户端:
[root@localhost ~]# ./get_helm.sh
(2)接下来介绍通过手动下载预编译的二进制文件安装Helm客户端。Helm二进制包的网址为:
https://github.com/helm/helm/releases/latest
Helm为多种平台发布了预先编译好的二进制文件,如图7-1所示。
用户可以根据自己的实际环境下载所需要的版本。在本例中,我们采用的是64位的CentOS,所以所需要的软件包的网址如下:
https://storage.googleapis.com/kubernetes-helm/helm-v3.4.2-linux-amd64.tar.gz
找到所需要的软件包之后,使用以下命令将其下载到本地:
[root@localhost ~]# wget https://storage.googleapis.com/kubernetes-helm/
helm-v3.4.2-linux-amd64.tar.gz

图7-1 Helm的二进制软件包
然后使用以下命令将其解压:
[root@localhost ~]# tar -zxvf helm-v3.4.2-linux-amd64.tar.gz
解压得到的目录名为linux-amd64,查看其内容,如下所示:

在上面的文件列表中,helm即我们所需要的客户端,tiller为Helm的服务器端。
为了便于使用,可以将helm文件复制到系统目录/usr/local/bin目录中,命令如下:
[root@localhost ~]# cp linux-amd64/helm /usr/local/bin/
Helm的服务端Tiller是以Deployment方式部署在Kubernetes集群中的。通常情况下,管理员只需使用以下指令便可简单地完成安装:
[root@localhost ~]# helm init
但是由于在国内无法访问到Helm默认的服务器去下载镜像,故而不能直接使用以上命令。Helm命令提供了一个-i选项,用来指定自己的镜像服务器。
首先执行以下命令创建helm客户端相关配置文件以及$HELM_HOME环境变量:

增加一个国内的阿里云的软件仓库,命令如下:

创建Helm服务端,通过-i选项指定国内Docker镜像服务器:

启用TLS认证,命令如下:

由于Kubernetes以及Docker的很多资源都没有办法通过官方网站直接获得,因此在上面的命令中,我们使用-i选项指定国内的阿里云的镜像服务器。
实际上Tiller是部署在Kubernetes集群中的kube-system命名空间下的Deployment,它会去通过调用kube-api,在Kubernetes集群里创建和删除应用。
而从Kubernetes 1.6版本开始,API Server启用了RBAC授权。目前的Tiller部署时默认没有定义授权的ServiceAccount,这会导致访问API Server时被拒绝。所以我们需要明确为Tiller部署添加授权,命令如下:

使用以下命令为Tiller设置ServiceAccount:

由于Tiller是以Pod的形式运行的,因此用户可以使用kubectl命令查看其状态,如下所示:

由结果可以得知,Tiller已经处于运行状态,表示已经安装成功。
此时,用户可以通过以下命令查看Helm的客户端和服务器的版本:

Helm使用称为Chart的软件包格式。Chart是描述一组相关的Kubernetes资源的文件集合。通过Chart,管理员可以很方便地在Kubernetes中部署应用。本节将介绍Chart的结构。
从本质上讲,Chart软件包实际上就是一个tar归档文件。为了研究Chart包的具体结构,用户可以从软件仓库上面下载一个已经打包好的Chart。Helm提供一个helm fetch命令,将Chart包从远程软件仓库上下载到本地。例如,下面的命令将Wordpress下载到本地计算机中:
[root@localhost ~]# helm fetch stable/wordpress
下载完成后,查看下载到的文件信息,如下所示:

从上面的输出可知,通过helm fetch命令下载到的Chart包,其名称为wordpress-0.8.8.tgz,其中,.tgz表示该文件是经过tar和gzip压缩后的文件。
用户可以通过tar命令将其解压缩出来,如下所示:
[root@localhost ~]# tar -zxvf wordpress-0.8.8.tgz
解压缩之后得到的目录名为wordpress,其结构如下:

从上面的输出结果可知,一个Chart包的内容主要包括Chart.yaml和requirements.yaml等配置文件,以及charts和templates等目录。
Helm的使用包括软件仓库管理、查找Chart、安装Chart、查看已安装Chart以及删除Chart等操作,下面分别介绍这些操作的使用方法。
默认情况下,Helm已经提供了两个软件仓库,一个名为stable,其网址如下:
https://kubernetes-charts.storage.googleapis.com
另外一个名为local,其网址如下:
http://127.0.0.1:8879/charts
第一个网址无法访问,管理员通常需要更换默认的软件仓库的网址。
删除软件仓库需要使用helm repo remove命令,例如以下命令删除名为stable的软件仓库:
[root@localhost ~]# helm repo remove stable
添加软件仓库可以使用helm repo add命令,该命令接受2个参数,第1个为软件仓库的名称,第2个为软件仓库的地址。例如,下面的命令添加国内的阿里云镜像为默认的stable软件仓库:
[root@localhost ~]# helm repo add stable
https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
修改完软件仓库的配置之后,需要更新软件仓库的内容,如下所示:

搜索远程软件仓库中的Chart需要使用search命令,如果没有提供命令参数,则会列出所有的Chart包,如下所示:

helm search命令也支持关键字查询,例如,下面的命令查找名称中包含mysql的Chart包:

在上面的输出列表中,NAME为Chart的路径名,斜线前面为软件仓库的名称,后面为Chart的包名。CHART VERSION为Chart包的版本号,APP VERSION为Chart包的软件版本。例如,incubator/mysqlha的Chart包版本为0.3.0,该Chart包中的MySQL的版本号为5.7.13。
对于某个具体的Chart包,用户可以通过helm inspect命令查看其详细信息,如下所示:

Chart包的安装需要使用helm install命令,该命令的基本语法如下:
helm install [chart] [flags]
其中,chart为要安装的Chart包的名称,flags为一系列的选项。常用的选项有:
例如,下面的命令安装stable仓储中的mysql:


在上面的命令中,通过--set选项将新建的Pod的persistence.storageClass指定为前面创建的managed-nfs-storage,这样的话,就可以动态为Pod提供存储资源了。
接下来,我们验证一下Kubernetes的各种资源是否已经自动创建。
首先是检查Service是否被创建,如下所示:

从上面的输出结果可知,当前集群中已经自动创建了一个名为mysql-mysql的Service,并且其SELECTOR为mysql-mysql。
然后再查看一下Deployment的情况,如下所示:

从上面的输出可知,一个名为mysql-mysql的Deployment已经被自动创建,并且其SELECTOR定义为mysql-mysql,这个标签选择器的名称正与前面的Service中选择器的名称一致。
然后再查看一下Pod的创建情况,如下所示:

在上面的输出结果中,名为mysql-mysql-549d644d4-lmvzl的Pod就是刚才自动创建的Pod。
最后检查一下持久化存储卷请求是否被自动创建,如下所示:

通过上面的介绍可以看到,通过Helm,用户可以非常方便地部署一个MySQL的应用,并且不需要编辑和管理众多的YAML配置。
Helm通过helm ls命令查看当前系统中已经安装的Chart列表,也就是Release的列表。如果没有使用选项,该命令默认列出已经成功部署或者失败的Release,如下所示:

如果想要查看所有的Release,则可以使用-a选项。通过该选项,可以列出所有状态的Release,包括被删除的Release。

在上面的输出结果中,可以发现第1行的STATUS为DELETED,表示该Release已经被删除。
对于不再需要的Release,管理员可以将其删除,删除命令为helm delete,语法如下:
helm delete [flags] release_name
具体的示例命令如下所示:
[root@localhost ~]# helm delete ill-rottweiler release "ill-rottweiler" deleted
执行以上命令之后,Release的状态就变成了DELETED。但是,该Release仍然存在于Kubernetes系统中,Release的名称仍然不能被新的Release所使用。如果想要彻底将其删除,可以使用--purge选项,如下所示:
[root@localhost ~]# helm delete ill-rottweiler --purge release "ill-rottweiler" deleted