Contents
Helm的高级功能¶
1. 模板和试运行¶
当Helm安装一个发行版时,程序会经历几个阶段。它加载chart,解析传递给程序的值,读取chart元数据,等等。大约在这个过程的中间,Helm编译chart中的所有模板(一次完成),然后通过传递值来呈现它们(就像我们在上一章中看到的那样)。
在这个中间部分,它执行所有的模板指令。一旦模板被呈现到YAML中,Helm通过将其解析为Kubernetes对象来验证YAML的结构。最后,Helm序列化这些对象并将它们发送到kubernetes API服务器。
过程如下:
加载整个chart,包括其依赖项。
解析值。
执行模板,生成YAML。
将YAML解析为Kubernetes对象以验证数据。
将它发送给Kubernetes。
1.1 –dry-run标志¶
helm install和helm upgrade等命令提供了一个名为–dry-run的标志。当在命令行中添加此标志时,将导致Helm逐步完成前四个阶段(加载chart、确定值、渲染模板、格式化为YAML)。
但是当第四阶段结束时,Helm会将大量信息转储到标准输出,包括所有渲染的模板。然后它将退出,而不将对象发送给Kubernetes,也不创建任何发布记录。
例如,这里是以前的Drupal安装的一个版本,附加了–dry run标志:
$ helm install mysite bitnami/drupal --values values.yaml --set drupalEmail="hujinali@oschin.cn" --dry-run
在输出的最前面,它将打印有关此发布版本的信息:
NAME: mysite
LAST DEPLOYED: Sat May 7 02:14:28 2022
NAMESPACE: default
STATUS: pending-install
REVISION: 1
TEST SUITE: None
HOOKS:
MANIFEST:
接下来,在信息块之后,所有YAML格式的Kubernetes清单的模板都进行了渲染然后被转储到标准输出。
在试运行输出的最后,Helm打印面向用户的发行版本说明:
CHART NAME: drupal
CHART VERSION: 12.0.1
APP VERSION: 9.3.12** Please be patient while the chart is being deployed **
1. Get the Drupal URL:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace default -w mysite-drupal'
....
1.2 helm template命令¶
虽然–dry-run是为调试而设计的,但helm template是为了将Helm的模板渲染过程与安装或升级逻辑隔离开来。
$ helm template mysite bitnami/drupal --values values.yaml --set drupalEmail="hujinali@oschin.cn"
前面是一个大大简化了的输出版本,只显示了命令、开始数据和结束数据的示例。
不过,需要重点注意的是,默认情况下只打印YAML格式的Kubernetes清单。
因为Helm在helm template运行期间不联系Kubernetes集群,所以它不会对输出进行完全验证。在这种情况下,Helm可能不会发现一些错误。
如果你想要这种行为,可以选择使用–validate标志,但是在这种情况下,Helm需要一个有效的kubeconfig文件,其中包含集群的凭据。
helm template命令有大量的标志,这些标志对应于helm install中的标志。因此,在许多情况下,你可以像执行helm install一样执行helm template命令,随后捕获YAML并将其与其他工具一起使用。
使用后期渲染而不是Helm模板
有时你需要截取YAML,用自己的工具修改它,然后将其加载到Kubernetes中。Helm提供了一种执行这个外部工具的方法,而不必使用helm template。install、upgrade、rollback和template上的–post-renderer标记会导致Helm将YAML数据发送到命令,然后将结果读回Helm。这是使用Kustomize等工具的好方法。
总而言之,helm template是一个用于将Helm chart渲染到YAML中的工具,–dry-run标志是一个用于调试安装和升级命令,而无须将数据加载到Kubernetes中的工具。
2. 了解发布版本信息¶
2.1 发布记录¶
每次升级mysite安装时,都会创建一个新的Secret来跟踪每个版本。换句话说,发布记录跟踪安装的每个修订版:
$ kubectl get secret
2.2 列出发布版本¶
$ helm ls
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
mysite default 2 2022-05-07 02:23:59.050699352 -0400 EDT deployed drupal-12.0.1 9.3.12
REVISION的值为2。
2.3 使用helm get查找发布的详细信息¶
虽然helm list提供了安装的摘要视图,但helm get命令集提供了有关特定发布版本的更深入的信息。
helm get有5个子命令(hooks、manifests、notes、values和all)。每个子命令都会检索某个版本的Helm跟踪信息的某些部分。
1.使用helm get notes¶
$ helm get notes mysite
NOTES:
CHART NAME: drupal
CHART VERSION: 12.0.1
APP VERSION: 9.3.12** Please be patient while the chart is being deployed **
1. Get the Drupal URL:
NOTE: It may take a few minutes for the LoadBalancer IP to be available.
Watch the status with: 'kubectl get svc --namespace default -w mysite-drupal'
export SERVICE_IP=$(kubectl get svc --namespace default mysite-drupal --template "{{ range (index .status.loadBalancer.ingress 0) }}{{ . }}{{ end }}")
echo "Drupal URL: http://$SERVICE_IP/"
2. Get your Drupal login credentials by running:
echo Username: admin
echo Password: $(kubectl get secret --namespace default mysite-drupal -o jsonpath="{.data.drupal-password}" | base64 --decode)
2.使用helm get values¶
查看使用的values配置
$ helm get values mysite
USER-SUPPLIED VALUES:
affinity: {}
allowEmptyPassword: true
args: []
certificates:
args: []
command: []
customCAs: []
customCertificate:
certificateLocation: /etc/ssl/certs/ssl-cert-snakeoil.pem
certificateSecret: ""
chainLocation: /etc/ssl/certs/mychain.pem
chainSecret:
key: secret-key
name: secret-name
keyLocation: /etc/ssl/private/ssl-cert-snakeoil.key
extraEnvVars: []
extraEnvVarsCM: ""
.....
查看默认值配置
$ helm inspect values bitnami/drupal|grep -v "#"|grep -v "^$"
global:
imageRegistry: ""
imagePullSecrets: []
storageClass: ""
kubeVersion: ""
nameOverride: ""
fullnameOverride: ""
commonAnnotations: {}
commonLabels: {}
extraDeploy: []
image:
registry: docker.io
repository: bitnami/drupal
tag: 9.3.12-debian-10-r1
pullPolicy: IfNotPresent
pullSecrets: []
debug: false
replicaCount: 1
drupalProfile: standard
drupalSkipInstall: false
drupalUsername: user
drupalPassword: ""
drupalEmail: user@example.com
allowEmptyPasswo
.....
3.使用helm get manifest¶
此子命令获取Helm使用Chart模板生成的确切YAML清单:
$ helm get manifest mysite
---
# Source: drupal/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-11.0.0
app.kubernetes.io/instance: mysite
app.kubernetes.io/managed-by: Helm
annotations:
automountServiceAccountToken: false
---
# Source: drupal/charts/mariadb/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysite-mariadb
namespace: "default"
labels:
app.kubernetes.io/name: mariadb
helm.sh/chart: mariadb-11.0.0
app.kubernetes.io/instance: mysite
app.kubernetes.io/managed-by: Helm
type: Opaque
data:
mariadb-root-password: b3NjaGluYQ==
mariadb-password: b3NjaGluYQ==
---
# Source: drupal/templates/secrets.yaml
apiVersion: v1
kind: Secret
metadata:
name: mysite-drupal
labels:
app.kubernetes.io/name: drupal
.....
关于这个命令的一个重要细节是,它不会返回所有资源的当前状态。它返回从模板生成的清单。
有了helm get,我们可以仔细检查一个单独的发布版本。
3. 历史记录和回滚¶
$ helm list
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
mysite default 2 2022-05-07 02:23:59.050699352 -0400 EDT deployed drupal-12.0.1 9.3.12
$ helm history mysite
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sat May 7 02:23:42 2022 superseded drupal-12.0.1 9.3.12 Install complete
2 Sat May 7 02:23:59 2022 deployed drupal-12.0.1 9.3.12 Upgrade complete
$ helm upgrade mysite bitnami/drupal --version 11.0.32 --values values.yaml
$ helm history mysite
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sat May 7 02:23:42 2022 superseded drupal-12.0.1 9.3.12 Install complete
2 Sat May 7 02:23:59 2022 superseded drupal-12.0.1 9.3.12 Upgrade complete
3 Sat May 7 02:40:21 2022 deployed drupal-11.0.32 9.3.11 Upgrade complete
superseded(已取代)
pending-install(挂起-安装)
deployed(已部署)
pending-rollback(挂起-回滚)
uninstalling(正在卸载)
uninstalled(已卸载)
failed(失败)
helm rollback的用途:
$ helm rollback mysite 2
Rollback was a success! Happy Helming!
这个命令告诉Helm获取wordpress version 2版本,并将清单重新提交给Kubernetes。回滚不会还原到集群的上一个快照。Helm没有追踪足够的信息来做到这一点。它会重新提交以前的配置,而Kubernetes尝试重置资源以匹配。
$ helm history mysite
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sat May 7 02:23:42 2022 superseded drupal-12.0.1 9.3.12 Install complete
2 Sat May 7 02:23:59 2022 superseded drupal-12.0.1 9.3.12 Upgrade complete
3 Sat May 7 02:40:21 2022 superseded drupal-11.0.32 9.3.11 Upgrade complete
4 Sat May 7 02:43:17 2022 deployed drupal-12.0.1 9.3.12 Rollback to 2
回滚操作创建了一个新版本(4)。由于回滚是成功的(并且Kubernetes接受了修改),所以这个版本被标记为deployed。
因为Helm保存了历史记录,所以在回滚到已知的良好配置之后,仍然可以检查失败的版本。
在大多数情况下,helm rollback是从灾难中恢复过来的良好方法。
但是,如果手工编辑由Helm管理的资源,可能会出现一个有趣的问题。回滚有时会导致一些意外的行为,特别是在Kubernetes资源已经被用户手工编辑的情况下。如果这些手工编辑的内容与回滚不冲突,Helm和Kubernetes将尝试保留它们。
从本质上讲,回滚将在资源的当前状态、失败的Helm版本和回滚到的Helm版本之间产生一个三向差异。在某些情况下,生成的差异可能导致回滚手工编辑的内容,而在其他情况下,这些差异将被合并。在最坏的情况下,某些手工编辑的内容可能会被覆盖,而其他相关的编辑内容则会被合并,从而导致配置不一致。这是Helm核心维护人员建议不要手工编辑资源的众多原因之一。
如果所有的编辑都是通过Helm进行的,那么你就可以有效地使用Helm工具,而无须猜测。
3.1 保留历史和回滚¶
在上一章中,我们看到helm uninstall命令有一个名为–keep-history的标志。通常,删除事件将销毁与该安装相关联的所有发布记录。但是当指定–keep-history时,即使删除了安装,你也可以看到它的历史记录:
$ helm uninstall mysite --keep-history
release "mysite" uninstalled
$ helm history mysite
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sat May 7 02:23:42 2022 superseded drupal-12.0.1 9.3.12 Install complete
2 Sat May 7 02:23:59 2022 superseded drupal-12.0.1 9.3.12 Upgrade complete
3 Sat May 7 02:40:21 2022 superseded drupal-11.0.32 9.3.11 Upgrade complete
4 Sat May 7 02:43:17 2022 uninstalled drupal-12.0.1 9.3.12 Uninstallation complete
注意,最后一个版本现在标记为已卸载(uninstalled)。当历史记录被保留时,你可以回滚已删除的安装:
$ helm rollback mysite 4
Rollback was a success! Happy Helming!
现在我们可以看到新部署的版本5:
$ helm history mysite
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION
1 Sat May 7 02:23:42 2022 superseded drupal-12.0.1 9.3.12 Install complete
2 Sat May 7 02:23:59 2022 superseded drupal-12.0.1 9.3.12 Upgrade complete
3 Sat May 7 02:40:21 2022 superseded drupal-11.0.32 9.3.11 Upgrade complete
4 Sat May 7 02:43:17 2022 uninstalled drupal-12.0.1 9.3.12 Uninstallation complete
5 Sat May 7 02:48:21 2022 deployed drupal-12.0.1 9.3.12 Rollback to 4
如果没有–keep-history标志,这将不起作用。
4.深入了解安装和升级¶
4.1 –generate-name和–name-template标志¶
Kubernetes的工作方式有一个与命名有关的微妙危险。Kubernetes假设名称将具有某些唯一性属性。例如,Deployment对象的命名空间中必须具有唯一的名称。也就是说,在命名空间mynamespace中不能有两个名为myapp的Deployment。但可以有一个Deployment和一个Pod,它们都叫myapp。
这使得某些任务变得更加复杂。例如,自动部署内容的CI系统必须确保这些内容的名称在命名空间中是唯一的。处理这个问题的一种方法是Helm提供一个工具来生成唯一的名称。
1.使用默认名称+随机数¶
Helm为helm install提供–generate name标志:
$ helm install bitnami/drupal --values values.yaml --generate-name
NAME: drupal-1651906366
LAST DEPLOYED: Sat May 7 02:52:50 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: drupal
....
使用–generate name标志,我们不再需要提供名称作为helm install的第一个参数。Helm根据chart名称和时间戳的组合生成名称。在前面的输出中,我们可以看到生成的名称:drupal-1651906366。
2. 使用自定义名称¶
还有一个额外的标志允许你指定命名模板。–name-template标志允许你执行以下操作:
$ helm install bitnami/drupal --values values.yaml --generate-name --name-template "mysite-{{ randAlpha 9 | lower }}"
NAME: mysite-lbrmruxpa
LAST DEPLOYED: Sat May 7 03:03:21 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
在该模板中,我们调用randAlpha函数,从a-z、A-Z字符范围中请求一个9个字符的随机字符串。然后我们通过第二个函数(lower)将结果“管道化”,该函数将所有内容都小写化。
4.2 –create-namespace标志¶
Helm确实允许你通过显式地声明要创建命名空间来覆盖此考虑:
$ helm install mysite bitnami/drupal --values values.yaml -n first-test --create-namespace
NAME: mysite
LAST DEPLOYED: Sat May 7 03:06:34 2022
NAMESPACE: first-test
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: drupal
$ helm list -n first-test
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION
mysite first-test 1 2022-05-07 03:06:34.978329723 -0400 EDT deployed drupal-12.0.1 9.3.12
在helm uninstall上没有类似的–delete-namespace。原因在于Helm对全局对象的防御性。创建命名空间后,可以将任意数量的对象放入其中,而它们不一定全都是由Helm管理的。当一个命名空间被删除时,该命名空间内的所有对象也都被删除。所以Helm不会自动删除用–create-namespace创建的命名空间。
要删除命名空间,请使用kubectl delete namespace(当然,在确保该命名空间中不存在重要对象之后再删除)。
$ helm uninstall mysite -n first-test
$ kubectl delete ns first-test
4.3 使用helm upgrade–install¶
这样的系统通常在无状态平台上运行基本脚本,而无状态平台没有查询Kubernetes的方法。
这类系统的用户要求Helm提供一个特性,允许在一个命令中支持“安装或升级”。
为了方便这种行为,Helm维护人员在helm upgrade命令中添加了–install标志。
helm upgrade–install命令将安装一个尚不存在的版本,或者升级一个以该名称命名的版本。在底层,它通过查询Kubernetes以获得具有给定名称的发布版。
如果该版本不存在,它将从升级逻辑切换到安装逻辑。
例如,我们可以使用完全相同的命令依次运行安装和升级:
$ helm upgrade --install mysite bitnami/drupal --values values.yaml
Release "mysite" does not exist. Installing it now.
NAME: mysite
LAST DEPLOYED: Sat May 7 03:11:18 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: drupal
CHART VERSION: 12.0.1
不过,这个命令确实带来了一些危险。Helm无法确定你提供给helm upgrade–install的安装名称是属于你要升级的发布版本,还是恰好与你要安装的名称相同。不小心使用此命令可能会导致用另一个安装覆盖某个安装。这就是它不是Helm的默认行为的原因。
4.4 –wait和–atomic标志¶
# 通过设置–wait参数,将等待所有Pod、PVC和Service以及Deployment、StatefulSet和ReplicaSet的最小Pod数都处于就绪状态后,然后才将Release标记为deployed状态,然后install命令行返回成功。等待–timeout时间,–timeout缺省为5m0s。
$ helm install myweb bitnami/tomcat \
--wait \
--set service.type=NodePort \
--set persistence.enabled=false
# 设置–timeout参数,缺省为5m0s。如果超过–timeout还没有就绪,Release状态将被标记为failed,命令行返回值为1,但并不会回退提交给Kubernetes的资源,所以安装不一定失败。如下载镜像时间过长,Release的状态被置为failed,但Kubernetes仍在会继续下载镜像,所以安装最终会成功,但Release不会被重置为deployed。没有找到修改Release状态的命令。
#设置–atomic参数,如果安装失败,会自动清除Chart,相当于如果状态为failed时会回退所有操作,保持安装的原子性。当设置–atomic参数时,–wait参数会自动配置。
$ helm install myweb bitnami/tomcat \
--atomic --timeout=1m \
--set service.type=NodePort \
--set persistence.enabled=false
4.5 使用–force和–cleanup-on-fail升级¶
我们下面看到的最后两个标志修改了Helm处理升级的细微差别的方式。
–force标志在升级用于管理pod(如Pod、Deployment和StatefulSet)的资源时修改Helm的行为。
通常,当Kubernetes收到修改此类对象的请求时,它会确定是否需要重新启动此资源管理的pod。
例如,某个Deployment可以运行一个pod的五个副本。但是,如果Kubernetes接收到Deployment对象的更新,它只会在某些字段被修改时重新启动这些pod。
不过,有时Helm用户希望确保pod重启。这时就用到了–force标记。它将删除并重新创建Deployment,而不是修改Deployment(或类似对象)。这迫使Kubernetes删除旧pod并创建新pod。
根据设计,使用–force会导致停机(通常只有几秒钟的停机时间)。建议仅在明确需要的情况使用–force,而不是作为默认选项。
例如,核心维护人员不建议在部署到生产环境的CI管道中使用–force。
修改升级行为的另一种方法是使用–cleanup on fail标志。类似于–force,这个标志指示Helm做额外的工作。
考虑这样一种情况:安装一个创建Kubernetes Secret的chart。一个新版本的chart被创建,它创建了第二个Secret。
但在安装过程中,Helm遇到了一个错误,并将发布标记为失败。第二个Secret有可能被挂起。如果使用–wait或–atomic,则更可能出现这种情况,因为在Kubernetes接受清单并创建资源之后,这些操作可能会失败。
–cleanup-on-fail标志将尝试修复此情况。如果失败,它将请求删除升级期间新创建的每个对象。使用它可能会使调试变得更加困难(特别是如果失败是由新创建的对象造成的),但是如果你不想冒险在失败后挂起未使用的对象,那么它是很有用的。