认识Helm


Helm3架构图如下:

上面的架构图中,核心是Helm Client(helm命令)和Helm Chart包。helm命令可以从Chart Repository中下载Helm Chart包,读取kubeconfig文件,并构建kube-apiserver REST API接口的HTTP请求。通过调用Kubernetes提供的REST API接口,将Chart包中包含的所有以YAML格式定义的Kubernetes资源,在Kubernetes集群中创建。

这些资源以Release的形式存在于Kubernetes集群中,每个Release又包含多个Kubernetes资源,例如Deployment、Pod、Service等。

Helm中的三大基本概念

要学习和使用Helm,一定要了解Helm中的三大基本概念,Helm的所有操作基本都是围绕着这些概念来进行的。

  • Chart:代表一个Helm包。它包含了在Kubernetes集群中运行应用程序、工具或服务所需的所有YAML格式的资源定义文件。
  • Repository(仓库):它是用来存放和共享Helm Chart的地方,类似于存放源码的Github的Repository,以及存放镜像的Dokcer的Repository。
  • Release:它是运行在Kubernetets集群中的Chart的实例。一个Chart通常可以在同一个集群中安装多次。每一次安装都会创建一个新的Release。

为什么要使用Helm?

先看一下传统的应用部署模式:

我们有测试环境、预发环境和现网环境三个环境,每个环境中部署一个应用A,应用A中包含了多个服务,每个服务又包含了自己的配置,不同服务之间的配置有些是共享的,例如配置A

每个服务由一个复杂的Kubernetes YAML格式的文件来定义并创建,可以看到如果靠传统的方式,去维护这些YAML格式文件,并在不同环境下使用不同的配置去创建应用,是一件非常复杂的工作,并且后期YAML文件和Kubernetes集群中部署应用的维护都很复杂。

随着微服务规模越来越大,会面临以下挑战:

  • 微服务化服务数量急剧增多,给服务管理带来了极大的挑战
  • 服务数量急剧增多,增加了管理难度,对运维部署是一种挑战
  • 服务数量的增多,对服务配置管理也提出了更高的要求
  • 随着服务数量增加,服务依赖关系也变得更加复杂,服务依赖关系的管理难度增大
  • 在环境信息管理方面,在新环境快速部署一个复杂应用变得更加困难。

所以,我们需要一种更好的方式,来维护和管理这些YAML文件和Kubernetes中部署的应用。Helm可以帮我们解决上述这些问题。解决方案如下:

在Helm中,可以理解为主要包含两类文件:模板文件和配置文件。模板文件通常由多个,配置文件通常有一个。Helm的模板文件基于text/template模板文件,提供了更加强大的模板渲染能力。Helm可以将配置文件中的值渲染进模板文件中,最终生成一个可以部署的Kubernetes YAML格式的资源定义文件。所以在Helm中,部署一个应用可以简化为Chart模板(多个服务)+ Chart配置 -->应用

Helm基本操作实战

前置条件

在开始之前,搭建一个可使用的K8S集群。

安装Helm

Helm提供了多种安装方式,在能连通外网的情况下,可以通过脚本来安装,安装命令如下:

$ mkdir -p $HOME/bin
$ wget https://get.helm.sh/helm-v3.6.3-linux-amd64.tar.gz
$ tar -xvzf helm-v3.6.3-linux-amd64.tar.gz
$ mv linux-amd64/helm $HOME/bin
$ chmod +x $HOME/bin/helm
$ helm version
version.BuildInfo{Version:"v3.6.3", GitCommit:"d506314abfb5d21419df8c7e7e68012379db2354", GitTreeState:"clean", GoVersion:"go1.16.5"}

如果执行helm version可以成功打印出helm命令的版本号,说明helm安装成功。

安装完helm命令后,可以安装helm命令的自动补全脚本。假如用的shell是bash,安装方法如下:

$ helm completion bash > $HOME/.helm-completion.bash
$ echo 'source $HOME/.helm-completion.bash' >> ~/.bashrc
$ bash

执行helm comp,就会自动补全为helm completion。

Helm快速入门

第一步,初始化一个Helm Chart仓库

安装完Helm之后,就可以使用helm命令添加一个Chart仓库。类似于用来托管Docker镜像的DockerHub、用来托管代码的GitHub,Chart包也有一个托管平台,当前比较流行的Chart包托管平台是Artifact Hub。

Artifact Hub 上有很多 Chart 仓库,我们可以添加需要的 Chart 仓库,这里我们添加 BitNami 提供的 Chart 仓库:

$ helm repo add bitnami https://charts.bitnami.com/bitnami # 添加 Chart Repository
$ helm repo list # 查看添加的 Repository 列表

添加完成后,我们可以通过helm search命令,来查询需要的Chart包。helm search支持两种不同的查询方式:

  • helm search repo:从你使用的helm repo add添加到本地Helm客户端中的仓库里查找。该命令基于本地数据进行搜索,无需连接外网
  • helm search hub:从Artifact Hub中查找并列出Helm Charts。Artifact Hub中存放了大量的仓库

Helm搜索使用模糊字符串匹配算法,所以你可以只输入名字的一部分。示例如下:

$ helm search repo bitnami
NAME                                          CHART VERSION  APP VERSION    DESCRIPTION
bitnami/bitnami-common                        0.0.9          0.0.9          DEPRECATED Chart with custom templates used in ...
bitnami/airflow                               10.2.8         2.1.2          Apache Airflow is a platform to programmaticall...
bitnami/apache                                8.6.1          2.4.48         Chart for Apache HTTP Server
bitnami/argo-cd                               1.0.2          2.0.5          Declarative, GitOps continuous delivery tool fo...
bitnami/aspnet-core                           1.3.14         3.1.18         ASP.NET Core is an open-source framework create...
bitnami/cassandra                             8.0.2          4.0.0          Apache Cassandra is a free and open-source dist...
bitnami/cert-manager                          0.1.15         1.5.1          Cert Manager is a Kubernetes add-on to automate...
# ... and many more

第二步,安装一个示例Chart

查询到自己需要的Helm Chart后,就可以用过helm install命令来安装一个Chart。helm install支持从多种源进行安装

  • Chart的Respository
  • 本地的Chart Archive,例如helm install foo foo-1.0.0.tgz
  • 一个未打包的Chart路径,例如helm install foo path/to/foo
  • 一个完整的URL,例如helm install foo https://example.com/charts/foo-1.0.0.tgz

这里,我们选择通过bitnami/mysql Chart包来安装一个Mysql应用。你可以执行helm show chart bitnami/mysql命令,来简单了解这个Chart的基本信息。也可以执行helm show all bitnami/mysql,获取关于该Chart的所有信息。

接下来,使用helm install命令来安装这个Chart包。安装命令如下:

$ helm repo update              # Make sure we get the latest list of charts
$ helm install bitnami/mysql --generate-name
NAME: mysql-1654070740
LAST DEPLOYED: Wed Jun  1 16:05:53 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: mysql
CHART VERSION: 9.1.2
APP VERSION: 8.0.29

上述例子中,通过安装bitnami/mysql这个Chart,创建了一个mysql-1654070740 Release。--generate-name参数告诉Helm自动为这个Release命名。

在安装过程中,Helm客户端会打印一些有用的信息,包括哪些资源已经被创建,Release当前状态,以及你是否还需要执行额外的配置步骤。比如,从上述例子的输出中,可以获取到数据库的Root密码、登陆方式、更新方式等信息。

安装完成之后,可以使用helm status来追踪Release的状态。

每当执行helm install的时候,都会创建一个新的发布版本。所以一个Chart在同一个集群里面可以被安装多次,每一个都可以被独立的管理和升级。

helm install命令会将templates渲染成最终的Kubernetes能够识别的YAML格式,然后安装到Kubernetes集群中。

第三步,安装前自定义Chart

上一步的安装方式只会使用Chart的默认配置选项,很多时候我们需要自定义Chart来指定我们想要的配置。使用helm show values可以查看Chart中的可配置选项:

$ helm show values bitnami/mysql # 为了方便展示,我删除了 `helm show values`输出中的`#`注释
# ... and many more
architecture: standalone
auth:
  rootPassword: ""
  database: my_database
  username: ""
  password: ""
  replicationUser: replicator
  replicationPassword: ""
  existingSecret: ""
  forcePassword: false
  usePasswordFiles: false
  customPasswordFiles: {}
initdbScripts: {}
# ... and many more

然后,可以使用YAML格式的文件,覆盖上述任意配置项,并在安装过程中使用该文件

$ echo '{auth.database: iam, auth.username: iam, auth.password: iam59!z$}' > values.yaml
$ helm install bitnami/mysql -f values.yaml --generate-name

上述命令将为Mysql创建一个名为iam的默认用于,密码为iam59!z$},并且授予该用户访问新建的iam数据库的权限。Chart中的其他默认配置保持不变。

安装过程中,有两种传递配置数据的方式:

  • -f,--values:使用YAML文件覆盖配置。可以指定多次,优先使用最右边的文件
  • --set:通过命令行的方式对指定配置项进行覆盖

如果同时使用两种方式,则--set中的值会被合并到--values中,但是--set中的值优先级更高。在--set中覆盖的内容会被保存在ConfigMap中。可以通过helm get vaules 来查看指定Release中--set设置的值,也可以通过运行helm upgrade并指定--reset-values字段,来清楚--set中设置的值。

--set的格式和限制

--set选项使用0或多个key-value键值对。最简单的用法类似于--set name=value,等价于下面的YAML格式:

name: value

多个值之间使用逗号分割,因此--set a=b,c=d的YAML格式是:

a: b
c: d

--set还支持更复杂的表达式。例如,--set outer.inner=value,被转换成了:

outer:
  inner: value

列表使用花括号{}来标识。例如,--set name={a,b,c},被转换成了:

name:
  - a
  - b
  - c

从 2.5.0 版本开始,我们可以使用数组下标的语法来访问列表中的元素了。例如 --set servers[0].port=80 就变成了:

servers:
  - port: 80

多个值也可以通过这种方式来设置。--set servers[0] [0].host=``marmotedu变成了:

servers:
  - port: 80
    host: marmotedu

如果需要在 --set 中使用特殊字符,你可以使用反斜线来进行转义,比如--set name=value1,value2 就变成了:

name: "value1,value2"

第四步,查看当前集群安装了哪些Release

通过helm list可以查看当前集群、当前Namespace下安装的Release列表:

$ helm list
NAME                    NAMESPACE       REVISION        UPDATED                                 STATUS          CHART           APP VERSION
mysql-1654070740        default         1               2022-06-01 16:05:53.200810946 +0800 CST deployed        mysql-9.1.2     8.0.29     
mysql-1654072514        default         1               2022-06-01 16:35:26.217259198 +0800 CST deployed        mysql-9.1.2     8.0.29     

可以看到,我们创建了两个Release,这些Release位于default命名空间中。上述命令,也列出了Release的更新时间、状态、Chart的版本等

第五步,升级Release,并且在失败时恢复

部署完应用之后,后续还可能升级应用,可以通过helm upgrade命令来升级应用。升级操作会基于已有的Release,根据提供的信息进行升级。Helm在更新时,只会变更有更改的内容。

例如,这里升级mysql-1654070740 ,变更它的Root密码

$ helm upgrade mysql-1654070740 bitnami/mysql --set auth.rootPassword='iam59!z$'

上述例子中,mysql-1654070740这个Release使用响应的Chart进行升级,但使用了一个新的rootPassword配置。

使用helm get values命令,来看看配置值是否真的生效了

$ helm get values mysql-1654070740
USER-SUPPLIED VALUES:
auth:
  rootPassword: iam59!z$

可以看到rootPassword 的新值已经被部署到集群中了。

假如发布失败,我们也可以通过helm rollback [RELEASE] [REVISION]命令,回滚到之前的发布版本。

$ helm rollback mysql-1654070740 1

上述这条命令将我们的mysql-1654070740回滚到了它最初的版本。Release版本其实是一个增量修订(revision)。每当发生了一次安装,升级或回滚操作,revision的值就会加1。第一次revision的值永远是1.

可以使用helm history [RELEASE]命令来查看一个特定Release的修订版本号

$ helm history mysql-1654070740
REVISION        UPDATED                         STATUS          CHART           APP VERSION     DESCRIPTION     
1               Wed Jun  1 16:05:53 2022        superseded      mysql-9.1.2     8.0.29          Install complete
2               Wed Jun  1 16:39:29 2022        deployed        mysql-9.1.2     8.0.29          Upgrade complete

还可以指定一些其他的选项,来自定义Helm在安装、升级、回滚期间的行为。以下是一些常用的参数:

  • --timeout:一个Go duration类型的值,用来表示等待Kubernetes命令完成的超时时间,默认值是5min
  • --no-hooks:不运行当前命令的钩子
  • --wait:表示必须要等到所有的Pods都处于ready状态,PVC都被绑定、Deployments处于ready状态的Pods个数达到最小值(Desired减去maxUnavailable),才会标记该Release为成功。最长等待时间由--timeout值指定。如果达到超时时间,Release将被标记为FAILED。

注意:当Deployment的replicas被设置为1,但其滚动升级策略中的maxUnavailable没有被设置为0时,--wait将返回就绪,因为已经满足了最小ready Pod数

第六步,卸载Release

可使用helm uninstall命令卸载一个Release:

$ helm uninstall mysql-1654072514 
release "mysql-1654072514" uninstalled

上述命令会从Kubernetes卸载mysql-1654072514,它将删除和该版本关联的所有资源(Sevice、Deployment、Pod、ComfigMap等),包含了该Release的所有版本历史。

如果在执行helm uninstall的时候提供--keep-history选项,Helm将会保存版本历史。此时,可以通过helm history命令查看该版本的信息。因为--keep-history选项会让Helm跟踪你的版本(即便已经卸载),所以可以用于审计集群历史,甚至使用helm rollback回滚版本。

Helm命令

上面介绍了Helm的一些命令的用法,如果想查看Helm提供的所有命令,可以执行helm help命令;或者 helm -h来查看某个子命令的用法,如:

$ helm get -h

This command consists of multiple subcommands which can be used to
get extended information about the release, including:

- The values used to generate the release
- The generated manifest file
- The notes provided by the chart of the release
- The hooks associated with the release

Usage:
  helm get [command]
# ... and many more

常用命令如下;

命令 描述
completion 生成指定Shell的自动补全脚本,如bash、zsh等
create 创建一个Chart并指定名字
dependency 管理Chart依赖
env 打印Helm客户端的环境变量信息,例如:HELM_CACHE_HOME、HELM_NAMESPACE、HELM_REPOSITORY_CONFIG等
get 下载一个Release的相关信息。可用子命令:all、hooks、manifest、notes、values
help 打印helm命令的帮助信息
history 获取Release历史
install 安装一个Chart
lint 检查一个Chart包,并打印潜在的问题
list 列出Release
package 将Chart目录打包到Chart存储文件中
plugin 安装(install)、列出(list)、卸载(uninstall)Helm插件
pull 从远程仓库中下载Chart并解压到本地,例如helm pull stable/redis --untar
repo 添加(add)、列出(list)、移除(remove)、更新(update)和索引(index)Chart仓库
rollback 从之前版本回滚
search 根据关键字搜索Charts、可用子命令:hub、repo
show 查看Chart详细信息,可用子命令:all、chart、readme、values
status 显示已命名版本的状态
template 本地呈现模板
test 在Release中运行Helm中的预定义测试
uninstall 卸载一个Release
ungrade 更新一个Release
verify 验证给定路径的Chart是否已被签名且有效
version 查看Helm客户端版本