3 Helm 的高级功能
在上一章中,我们研究了最常用的 Helm 命令。在本章中,我们将探讨 Helm 工具提供的其他功能。我们将深入研究提供有关发布、测试、安装和跟踪历史等信息的命令。最后,我们将重新讨论安装和升级,这次将讨论高级案例。
我们还将开始使用一些有助于故障排除和调试的工具。
3.1 模板和试运行
当 Helm 安装一个发行版时,程序会经历几个阶段。它加载 chart ,解析传递给程序的值,读取 chart 元数据,等等。大约在这个过程的中间,Helm 编译 chart 中的所有模板(一次完成),然后通过传递值来呈现它们(就像我们在上一章中看到的那样)。在这个中间部分,它执行所有的模板指令。一旦模板被呈现到 YAML 中,Helm 通过将其解析为 Kubernetes 对象来验证 YAML 的结构。最后,Helm 序列化这些对象并将它们发送到 kubernetes API 服务器。
过程如下:
- 加载整个 chart ,包括其依赖项。
-
解析值。
-
执行模板,生成 YAML。
-
将 YAML 解析为 Kubernetes 对象以验证数据。
-
将它发送给 Kubernetes。
例如,让我们看看上一章中发出的如下命令:
1 这个是在安装 mysite 的时候设置了 wordpressUsername
的值
root@master:~# helm install mysite bitnami/wordpress --set wordpressUsername=admin
执行该命令会有以下几个阶段
- 第一阶段:
Helm 将定位名为 bitnami/wordpress 的 chart 并加载该 chart 。如果 chart 是存放在本机的,它将从磁盘中读取。如果给定了一个 URL,它将从远程位置获取(可能使用插件来帮助获取 chart )。然后它将把
--set wordpressUsername=admin
转换为一个可以注入模板的值。此值将与 chart 的 values.yaml 文件中的默认值合并。Helm 根据数据做了一些基本检查。如果它在解析用户输入时遇到问题,或者默认值已损坏,它将退出并返回一个错误。否则,它将构建一个大值对象,模板引擎可以使用该对象进行替换。生成的值对象通过以下三个步骤来创建:- 加载 chart 文件的所有值;
- 用从文件加载的任何值(即,使用 -f 参数)覆盖;
- 使用 –set 参数设置的任何值覆盖。换句话说,–set 值覆盖传入的值文件中的设置,而传入的值文件又覆盖 chart 的默认 values.yaml 文件中的任何内容。
- 第二个阶段:
此时,Helm 将读取 wordpressChart 中的所有模板并执行这些模板,然后将合并的值传递给模板引擎。格式错误的模板将导致错误。但也有很多其他情况可能会导致失败。例如,如果缺少必需的值,则在此阶段返回错误。需要注意的是,在执行时,一些 Helm 模板需要关于 Kubernetes 的信息。因此,在模板渲染期间,Helm 可能会联系 Kubernetes API 服务器。这是我们稍后将讨论的一个重要主题。
然后将前面步骤的输出从 YAML 解析为 Kubernetes 对象。 Helm 将在此时执行一些模式级验证,确保对象的格式良好。然后将它们序列化为 Kubernetes 的最终YAML 格式。
-
最后一个阶段:
Helm 将 YAML 数据发送到 Kubernetes API 服务器。这是 kubectl 和其他 Kubernetes 工具与之交互的服务器。API 服务器将对提交的 YAML 运行一系列检查。如果 Kubernetes 接受 YAML 数据,Helm 将认为部署成功。但是如果 Kubernetes 拒绝了 YAML ,Helm将以一个错误退出。
接下来将详细讨论将对象发送到 Kubernetes 之后会发生什么。将介绍 Helm 如何将前面描述的过程与安装和修改相关联。但是现在,我们有足够的关于工作流的信息来理解两个相关的
Helm特性:--dry-run
参数和 helm template
命令。
3.1.1 –dry-run 参数
helm install
和 helm upgrade
等命令提供了一个名为 --dry-run
的参数。当在命令行中添加此参数时,将导致 Helm 逐步完成前四个阶段(加载 chart 、确定值、渲染模板、格式化为 YAML )。但是当第四阶段结束时,Helm 会将大量信息转储到标准输出,包括所有渲染的模板。
然后它将退出,而不将对象发送给 Kubernetes ,也不创建任何发布记录。
例如:
1 这里是以前的 wordpress 安装的一个版本,附加了 --dry-run
参数:
root@master:~# helm install mysite bitnami/wordpress --values values.yaml --set wordpressEmail=zgy@example.com --dry-run
NAME: mysite
LAST DEPLOYED: Thu Apr 21 15:05:34 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
---
# Source: wordpress/charts/mariadb/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: mysite-mariadb
namespace: "default"
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-10.5.1
app.kubernetes.io/instance: mysite
app.kubernetes.io/managed-by: Helm
annotations:
automountServiceAccountToken: false
......省略......
# 前面的内容显示了安装的名称、上次的部署时间(在本例中是当前日期和时间)、它将部署到哪个命名空间、它处于版本的哪个阶段(pending-install)以及版本号。因为这是一个安装,所以修订版本是1。升级时,它将是2或更大的数字。
2 查看并没有创建对应的 helm 应用
root@master:~# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
这个试运行(dry-run)参数特性为 Helm 用户提供了一种在 chart 把输出发送到 Kubernetes 之前调试它的方法。通过渲染所有模板并输出至终端,你可以准确地检查提交给集群的内容。通过发布版本数据,你可以验证是否按照预期创建了发布版本。
--dry-run
参数的主要目的是让用户有机会在将输出发送到 Kubernetes
之前检查和调试输出。但在它被引入后不久,Helm 官方就注意到了用户中的一种趋势:人们希望使用 --dry-run
将 Helm 用作模板引擎,然后使用其他工具(如 kubectl )将渲染的输出发送到 Kubernetes。
注意:
但是使用 --dry-run
时需要考虑以下问题:
--dry-run
将非YAML
信息与渲染的模板混合。这意味着在将数据发送到 `kubectl 等工具之前,必须对其进行清理。--dry-run
在升级时可能会产生与其安装时不同的 YAML 输出,这可能会让人困惑。- 它会联系
Kubernetes API
服务器进行验证,这意味着 Helm 必须拥有Kubernetes
凭据,即使它只是用来试运行一个发行版本。 -
它还将特定于集群的信息插入模板引擎。因此,某些渲染过程的输出可能是特定于集群的。为了解决这些问题,Helm 官方引入了一个完全独立的命令:
helm template
。
3.1.2 helm template 命令
虽然 --dry-run
参数是为调试而设计的,但 helm template
是为了将 Helm 的模板渲染过程与安装或升级逻辑隔离开来。
之前,我们研究了 Helm 安装或升级的 5 个阶段。template 命令执行前 4 个阶段(加载chart、解析值、渲染模板、格式化为YAML)。但它也有一些额外的注意事项:
- 在
helm template
执行期间,Helm 从不链接 Kubernetes 服务器。 - template 命令的作用始终类似于安装。
- 通常需要链接
Kubernetes
服务器的模板函数和指令将只返回默认数据。 - chart 只能访问默认的 Kubernetes 类型
关于最后一项,helm template
做了一个显著的简化假设。
Kubernetes 服务器支持内置资源类型(Pod、Service、ConfigMap等)以及由 CRD 生成的自定义资源类型。当运行安装或升级时,Helm 在处理 chart 之前会从 Kubernetes 服务器上获取这些资源类型。
但是,helm template 执行此步骤的方式不同。在编译 Helm 时,它是针对 Kubernetes 的特定版本编译的。Kubernetes 库包含该版本的内置资源类型列表。Helm 使用这个内置列表,而不是它从 API 服务器获取的列表。因此,Helm 在 helm template 运行期间不能访问任何 CRD,因为 CRD 安装在集群上,并且不包含在 Kubernetes 库中。
如果针对使用新类型或新版本的 chart 运行旧版本的 Helm,会在 helm template 运行期间产生错误,因为 Helm 不会把最新类型或版本编译进去。
作为这些决策的结果,helm template 在运行之后生成一致的输出。更重要的是,它可以在不能访问 Kubernetes 集群的环境中运行,比如持续集成(CI)管道。输出也不同于 --dry-run
。下面是一个命令示例:
1 运行helm template
预生成对应的 yaml 模板
root@master:~# helm template mysite bitnami/wordpress --values values.yaml --set wordpressEmail=zgy@example.com
---
# Source: wordpress/charts/mariadb/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: mysite-mariadb
namespace: "default"
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-10.5.1
app.kubernetes.io/instance: mysite
app.kubernetes.io/managed-by: Helm
annotations:
automountServiceAccountToken: false
......省略.......
通过上面的演示可以看到使用 helm template
大大简化了输出的结果,只显示了命令、开始数据和结束数据的示例。不过,需要重点注意的是,默认情况下只打印 YAML 格式的 Kubernetes 清单。
2 通过 helm list
查看当前并没有对应 chart 应用
root@master:~# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
因为 Helm 在 helm template 运行期间不会请求 Kubernetes 集群,所以它不会对输出进行完全验证。在这种情况下,Helm 可能不会发现一些错误。如果你想要这种行为,可以选择使用 --validate
参数,但是在这种情况下,Helm 需要一个有效的 kubeconfig
文件,其中包含集群的访问凭据。
helm template 命令有大量的参数,这些参数对应于 helm install 中的参数。因此,在许多情况下,你可以像执行 helm install
一样执行 helm template
命令,随后捕获 YAML
并将其与其他工具一起使用
比如有时候我们想使用 helm template
渲染输出的信息
这时就需要截取 YAML ,用自己的工具修改它,然后将其加载到 Kubernetes 中。Helm 提供了一种执行这个外部工具的方法,而不必使用 helm template
。install、upgrade、rollback
和 template
上的 --post-renderer
标记会导致 Helm 将 YAML 数据发送到命令,然后将结果读回 Helm 。这是使用Kustomize (https://github.com/kubernetes-sigs/kustomize) 等工具的好方法。
总结:
helm template
是一个用于将 Helm chart 输出为 YAML 的参数,–dry-run 参数是一个用于调试安装和升级命令,而无须将数据加载到 Kubernetes 中的工具
3.2 了解发布版本信息
在上一章中,我们看到了 helm get
命令。本节将更深入地研究该命令以及其他可以提供有关 Helm 发布版本信息的命令。
首先回顾上一节中的 5 个 Helm 安装阶段:
- 加载chart。
-
解析值。
-
执行模板。
-
渲染 YAML。
-
把它发送到 Kubernetes。
前 4 个阶段主要涉及数据的局部表示。即,Helm 在运行 helm 命令的同一台计算机上执行所有处理。
不过,在最后一个阶段,Helm 将数据发送给 Kubernetes 。然后二者“来回沟通”,直到发布版本被接受或拒绝。
在第 5 阶段,Helm 必须监控发布状态。此外,由于许多人可能正在处理该特定应用程序安装的同一副本,因此 Helm 需要以多个用户可以看到该信息的方式监控状态。
Helm 为这个特性提供了发布记录。
3.2.1 发布记录
当我们(使用 helm install
)安装一个 Helm chart
时,新的安装将在指定的命名空间或默认命名空间中创建(在第2章中讨论过)。在第2章的结尾,我们还看到了 helm install
如何创建一种特殊类型的 Kubernetes Secret
来保存发布信息。我们看到了如何与 kubectl 一起检查这些 Secret:
1 安装一个 wordpress chart
root@master:~# helm install mysite bitnami/wordpress
2 查看对应 secret
root@master:~# kubectl get secrets
NAME TYPE DATA AGE
default-token-v424k kubernetes.io/service-account-token 3 28h
mysite-mariadb Opaque 2 11s
mysite-mariadb-token-pctbg kubernetes.io/service-account-token 3 11s
mysite-wordpress Opaque 1 11s
sh.helm.release.v1.mysite.v1 helm.sh/release.v1 1 11s
特别值得注意的是最后一个 Secret,即 sh.helm.release.v1.mysite.v1
注意:
它使用了一个特殊类型(helm.sh/release.v1
)来表示这是一个 Helm Secret。由 Helm 自动生成这个 Secret 来跟踪 mysite 安装的版本 1(这是一个 wordpress 站点)。每次升级 mysite 安装时,都会创建一个新的 Secret 来跟踪每个版本。换句话说,发布记录跟踪安装的每个修订版:
3 对 mysite 进行升级
# 升级第一次
root@master:~# helm upgrade mysite bitnami/wordpress
# 升级第二次
root@master:~# helm upgrade mysite bitnami/wordpress
# 查看 secret
root@master:~# kubectl get secrets
NAME TYPE DATA AGE
default-token-v424k kubernetes.io/service-account-token 3 28h
mysite-mariadb Opaque 2 95s
mysite-mariadb-token-pctbg kubernetes.io/service-account-token 3 95s
mysite-wordpress Opaque 1 95s
sh.helm.release.v1.mysite.v1 helm.sh/release.v1 1 95s
sh.helm.release.v1.mysite.v2 helm.sh/release.v1 1 7s
sh.helm.release.v1.mysite.v3 helm.sh/release.v1 1 14s
在上面的例子中,我们已经升级了几次,现在是 mysite 的 v3 。默认情况下,Helm 最多跟踪每个安装的 10 个修订版。一旦安装超过 10 个发布版本,Helm 将删除最早的发布记录,直到剩余的数量不超过最大允许值。
每个发布记录都包含足够的信息,可以为该修订版重新创建 Kubernetes 对象(这对于 helm rollback
来说很重要)。它还包含有关发布的元数据
4 如果我们使用 kubectl 查看此发布版本,会看到如下内容:
root@master:~# kubectl get secrets sh.helm.release.v1.mysite.v1 -oyaml
apiVersion: v1
data:
release:
......省略大量 base64......
kind: Secret
metadata:
creationTimestamp: "2022-04-21T08:37:30Z"
labels:
modifiedAt: "1650530250"
name: mysite
owner: helm
status: deployed
version: "3"
name: sh.helm.release.v1.mysite.v3
namespace: default
resourceVersion: "33447"
uid: f891ce37-5828-4802-baf9-04c3825fb826
type: helm.sh/release.v1上面示例中,该 blob 包含 chart 和版本的 gzip 表示。但重要的是,Kubernetes 元数据的 labels 部分包含有关此版本的信息。
我们可以看到,这个数据描述了名为 mysite 的版本,它的当前修订号是 3 ,这个版本被标记为 deployed
。如果我们看第 2 版,会看到发布状态(status)是superseded,这意味着它已经被更新的 3 版本所取代。
简而言之,这个 Secret 存储在 Kubernetes 中,以便同一集群的不同用户可以访问相同的发布信息。
在某个发布版的生命周期中,它可以经历几个不同的状态。在这里,大致顺序为:
pending-install
(挂起-安装)在将清单发送给 Kubernetes 之前,Helm 通过创建一个状态设置为
pending-install
的版本(标记为 version 1)来声明安装。-
deployed
(已部署)一旦 Kubernetes 接受 Helm 的清单,Helm 就会更新发布记录,将其标记为已部署(deployed)。
-
pending-upgrad
(挂起-升级)当 Helm 升级开始时,会为安装创建一个新的发布版本(例如 v2 ),其状态设置为 pending-upgrade。
-
superseded
(已取代)在运行升级时,将更新上次部署的发布版本,并将状态标记为已取代(superseded),新升级的版本将从 pending-upgrade 更改为
deployed。
-
pending-rollback
(挂起-回滚)如果创建了回滚,则会创建一个新的发布版本(例如v3),其状态设置为 pending-rollback ,直到 Kubernetes 接受该发布版本清单。然后将它标记为deployed,而前一个发布版本被标记为 superseded。
-
uninstalling
(正在卸载)执行
helm uninstall
时,将读取最新发布版本,然后将其状态更改为uninstalling
。 -
uninstalled
(已卸载)如果在删除过程中保留了历史记录,那么当 helm uninstall 完成时,前一个发布版本的状态将更改为 uninstalled。
-
failed(失败)
最后,如果在任何操作中,Kubernetes 拒绝了 Helm 提交的清单,Helm 都会将该发布版本标记为 failed。
3.2.2 列出发布版本
状态信息在许多 Helm 命令中都会显示。我们已经看到了 pending-install 是如何在一个 –dry-run 中出现的。在本节和下一节中,我们将看到更多这种情况。
在上一章中,我们使用 helm list 查看安装的 chart。鉴于我们对各种状态的知识,值得再回顾一下 helm list 。list 命令是快速检查版本状态的最佳工具
例如,假设我们有一个同时安装了 drupal 和 wordpress chart 的应用。
1 以下是 helm list 的输出:
root@master:~# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
drupal default 1 2022-04-21 17:19:48.048202384 +0800 CST deployed drupal-11.0.31 9.3.11
mysite default 3 2022-04-21 16:37:29.98244282 +0800 CST deployed wordpress-13.3.1 5.9.3
2 不过,为了显示失败的结果,我们可以运行下面的一个升级命令
root@master:~# helm upgrade mysite bitnami/wordpress --set image.pullPolicy=NoSuchPolicy
Error: UPGRADE FAILED: cannot patch "mysite-wordpress" with kind Deployment: Deployment.apps "mysite-wordpress" is invalid: spec.template.spec.containers[0].imagePullPolicy: Unsupported value: "NoSuchPolicy": supported values: "Always", "IfNotPresent", "Never"
# 如上所示直接报错拉取(pull)策略不能设置为NoSuchPolicy。
这个错误来自 Kubernetes API 服务器,这意味着 Helm 提交了清单,而 Kubernetes 拒绝了它。所以我们的发布版本应该是失败的。
3 再次运行helm ls来验证这一点
root@master:~# helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
drupal default 1 2022-04-21 17:19:48.048202384 +0800 CST deployed drupal-11.0.31 9.3.11
mysite default 4 2022-04-21 17:23:45.646618377 +0800 CST failed wordpress-13.3.1 5.9.3
值得注意的是,最近升级失败的 wordpress 的 REVISION 字段已经从 3 增加到了 4 。即使是失败的版本也附带了修订号。我们将在 3.3 节中了解为什么这很重要。
3.2.3 使用 helm get 查找发布的详细信息
虽然 helm list
提供了安装的摘要视图,但 helm get
命令集提供了有关特定发布版本的更深入的信息。
helm get 有 5 个子命令(hooks、manifests、notes、values 和 all)。每个子命令都会检索某个版本的 Helm 跟踪信息的某些部分。
3.2.3.1 使用 helm get notes
# 打印发布说明
root@master:~# helm get notes mysite
NOTES:
CHART NAME: wordpress
CHART VERSION: 13.3.1
APP VERSION: 5.9.3
** Please be patient while the chart is being deployed **
1. Get the WordPress URL by running these commands:(运行下面的命令来获取 word press 的 URL)
'kubectl get svc --namespace default -w mysite-wordpress'
......省略......
# 这个输出看起来比较熟悉,因为 helm install 和 helm upgrade 都会在成功操作结束时打印发布说明。但是 helm get notes 提供了一种方便的方式来按需获取这些说明。如果你忘记了 wordpress 站点的 URL 是什么,使用这种方法就特别有用
3.2.3.2 使用 helm get values
该子命令用于查看上一个版本提供了哪些参数,如在上一节中,我们升级了 mysite 但是失败了。那么就可以使用 helm get values
来查看是什么参数导致它失败:
# 这里查看 mysite 应用最近的一次状态参数
root@master:~# helm get values mysite
USER-SUPPLIED VALUES:
image:
pullPolicy: NoSuchPolicy
我们知道第三次修订是成功的,但是第四次修订失败了。所以可以看看前面的值有什么变化:
root@master:~# helm get values mysite --revision 3
USER-SUPPLIED VALUES:
null
# 提示我们在升级第 3 版本的时候值为空,因为我们并没有在第三版升级的时候添加任何参数
此命令对于了解版本配置的总体状态也很有用。可以使用 helm get values
来查看当前为该版本设置的所有值。为此,我们使用 --all
参数查看所有版本的设置:
root@master:~# helm get values mysite --all
affinity: {}
allowEmptyPassword: true
allowOverrideNone: false
apacheConfiguration: ""
args: []
autoscaling:
enabled: false
maxReplicas: 11
minReplicas: 1
......省略......
# 当指定 -- all标志时,Helm 将获得按字母顺序排序的完整版本数据。这是一个很好的工具,可以查看发行版的确切配置状态。
3.2.3.3 使用 helm get manifest
helm get manifest
此子命令获取 Helm 使用 Chart 模板生成的确切 YAML 清单
root@master:~# helm get manifest mysite
---
# Source: wordpress/charts/mariadb/templates/serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: mysite-mariadb
namespace: "default"
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-10.5.1
app.kubernetes.io/instance: mysite
app.kubernetes.io/managed-by: Helm
annotations:
automountServiceAccountToken: false
......省略......
关于该命令的一个重要细节是,它不会返回所有资源的当前状态。它返回从模板生成的清单。在前面的示例中,我们看到了一个名为 mysite-mariadb
的Secret。
1 如果我们使用 kubectl 查询这个 Secret
root@master:~# kubectl get secrets | grep mariadb
mysite-mariadb Opaque 2 67m
mysite-mariadb-token-pctbg kubernetes.io/service-account-token 3 67m
2 查看元数据部分:
root@master:~# kubectl get secrets mysite-mariadb -o yaml
apiVersion: v1
data:
mariadb-password: M1J4NWJ2N0VhNQ==
mariadb-root-password: T3lUUVR2Z2VrMQ==
kind: Secret
metadata:
annotations:
meta.helm.sh/release-name: mysite
meta.helm.sh/release-namespace: default
creationTimestamp: "2022-04-21T08:35:35Z"
labels:
app.kubernetes.io/instance: mysite
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-10.5.1
name: mysite-mariadb
namespace: default
resourceVersion: "33239"
uid: 17167d8b-1e36-42dc-9117-df072c98413c
type: Opaque
kubectl 的输出包含当前存在于 Kubernetes 中的记录。来自模板输出后添加了几个字段。一些(如注解)则是由 Helm 自己管理,而另一些(如 managedFields 和creationTimestamp )由 Kubernetes 管理。
Helm 再次提供了简化调试的工具。在 helm get manifest 和 kubectl get 之间,有一些工具可以用来比较 Kubernetes 认为当前的对象是什么,以及 chart 产生了什么。
而原本当应该由 Helm 管理的资源则现在确在 Helm 外部(例如,使用kubectl edit)手动编辑时,这尤其有用。
有了 helm get,我们可以仔细检查一个单独的发布版本。但我们将介绍的下一个工具提供了一个有关发布进程的视图。在下一节中,我们将了解 helm history 和helm rollback 。这两个工具的作用就在于历史记录和回滚