【51CTO.com快译】Helm 是 Kubernetes 的包管理器。由于其模板方法和可重用和生产就绪包(也称为 Helm charts))的丰富生态系统,它减少了部署复杂应用程序的工作量。有了Helm可以将打包的应用程序部署为一组版本化、预配置的 Kubernetes 资源。

假设你正在使用 Kubernetes 部署一个数据库,包括多个部署、容器、服务等。Helm 允许你使用单个命令和一组值安装相同的数据库。其声明性和幂等性命令使 Helm 成为持续交付 (CD) 的理想工具。

随着最新版本的Helm 3的发布,它与Kubernetes的生态系统融合得更加紧密。

本文介绍了创建Helm Chart来管理在Kubernetes中运行的应用程序的13个实践案例。

1.充分利用Helm生态系统

Helm为你提供了丰富的社区专业知识——这可能是该工具最大的好处。它从世界各地的开发人员那里收集图表,然后通过图表库进行共享。你可以将官方稳定图表库添加到本地,设置如下:

$ helm repo add stable https://charts.helm.sh/stable "stable" has been added to your repositories Then you can search for charts, for example, MySQL: $ helm search hub mysql URL CHART VERSION APP VERSION DESCRIPTION https://hub.helm.sh/charts/bitnami/mysql 8.2.3 8.0.22 Chart to create a Highly available MySQL cluster https://hub.helm.sh/charts/t3n/mysql 0.1.0 8.0.22 Fast, reliable, scalable, and easy to use open-...

你会看到一长串的结果列表,可以看得出Helm图表的生态系统有多大。

2. 使用子图来管理你的依赖

由于部署到Kubernetes的应用程序由细粒度的、相互依赖的部分组成,因此它们的Helm图表具有各种资源模板和依赖项。例如,假设后端依赖于数据库和消息队列。数据库和消息队列已经是独立的应用(如PostgreSQL和RabbitMQ)。因此,建议为独立应用程序创建或使用单独的图表,并将它们添加到父图表中。依赖的应用程序在这里被命名为子图表。

创建和配置子图表有三个基本要素:

  • 文件夹结构的顺序如下:

backend-chart - Chart.yaml - charts - message-queue - Chart.yaml - templates - values.yaml - database - Chart.yaml - templates - values.yaml - values.yaml
  • Chart.yaml

另外Chart.yaml在父图表中应该列出任何依赖关系和条件:

apiVersion: v2 name: backend-chart description: A Helm chart for backend ... dependencies: - name: message-queue condition: message-queue.enabled - name: database condition: database.enabled
  • values.yaml


最后,你可以使用以下 values.yaml 文件设置或覆盖父图表中子图表的值:

message-queue: enabled: true image: repository: acme/rabbitmq tag: latest database: enabled: false

创建和使用子图表在父应用程序和依赖程序之间建立了一个抽象层。这些单独的图表使Kubernetes中的应用程序易于部署、调试和更新,这些应用程序具有各自的值和升级生命周期。你可以在像bitnami/wordpress这样的示例图表中浏览文件夹结构、依赖项和值文件。

3.使用标签轻松找到资源

标签对于Kubernetes的内部运营和Kubernetes运营商的日常工作至关重要。Kubernetes中的几乎每个资源都为不同的目的提供了标签,例如分组、资源分配、负载平衡或调度。

一个Helm命令将允许你安装多个资源。但重要的是要知道这些资源的来源。标签可以让你快速找到由Helm版本创建的资源。

最常用的方法是在 中定义标签`helpers.tpl`,如下所示:

{{/* Common labels */}} {{- define "common.labels" -}} app.kubernetes.io/instance: {{ .Release.Name }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end -}}

然后你需要在资源模板中使用带标签的" include "函数:

apiVersion: apps/v1 kind: Deployment metadata: name: my-queue labels: {{ include "labels" . | indent 4 }} ...

现在你应该能够使用标签选择器列出所有资源。例如,您可以使用该`kubectl get pods -l app.kubernetes.io/instance=[Name of the Helm Release]`命令列出 my-queue 部署的所有 pod 。这一步对于定位和调试 Helm 管理的资源至关重要。

4. 记录你的图表

文档对于确保可维护的 Helm 图表至关重要。在资源模板和 README 中添加注释可帮助团队开发和使用 Helm 图表。

你应该使用以下三个选项来记录你的图表:

  • 注释:模板和值文件是 YAML 文件。你可以添加注释,并提供有关YAML文件中的字段的有用信息。

  • README:图表的README是一个解释如何使用图表的标记文件。你可以使用以下命令检查 README 文件的内容:`helm show readme [Name of the Chart]`

  • NOTES.txt:这是一个位于`templates/NOTES.txt` 中的特殊文件,提供有关版本部署的有用信息。`NOTES.txt`文件的内容也可以使用类似于资源模板的函数和值进行模板化: 

You have deployed the following release: {{ .Release.Name }}. To get further information, you can run the commands: $ helm status {{ .Release.Name }} $ helm get all {{ .Release.Name }}

在 helm install 或 helm upgrade 命令结束时,Helm 会打印出 NOTES.txt 的内容,如下所示:

RESOURCES: ==> v1/Secret NAME TYPE DATA AGE my-secret Opaque 1 0s  ==> v1/ConfigMap NAME DATA AGE db-configmap 3 0s  NOTES: You have deployed the following release: precious-db. To get further information, you can run the commands: $ helm status precious-db $ helm get all precious-db

5. 测试你的 Charts

Helm charts 由多个要部署到集群的资源组成。必须检查是否在集群中创建的所有资源都具有正确的值。例如,在部署数据库时,你应该检查数据库密码设置是否正确。

幸运的是,Helm提供了一个测试功能,可以在集群中运行一些容器,以验证应用程序。例如,注解的资源模板`"helm.sh/hook": test-success`由 Helm 作为测试用例运行。

让我们假设你正在部署带有MariaDB数据库的WordPress。Bitnami维护的Helm图表有一个pod来验证数据库连接,定义如下:

  1. ... 

  2. apiVersion: v1 

  3. kind: Pod 

  4. metadata: 

  5.   name: "{{ .Release.Name }}-credentials-test" 

  6.   annotations: 

  7.     "helm.sh/hook": test-success 

  8. ... 

  9.       env: 

  10.         - name: MARIADB\_HOST 

  11.           value: {{ include "wordpress.databaseHost" . | quote }} 

  12.         - name: MARIADB\_PORT 

  13.           value: "3306" 

  14.         - name: WORDPRESS\_DATABASE\_NAME 

  15.           value: {{ default "" .Values.mariadb.auth.database | quote }} 

  16.         - name: WORDPRESS\_DATABASE\_USER 

  17.           value: {{ default "" .Values.mariadb.auth.username | quote }} 

  18.         - name: WORDPRESS\_DATABASE\_PASSWORD 

  19.           valueFrom: 

  20.             secretKeyRef: 

  21.               name: {{ include "wordpress.databaseSecretName" . }} 

  22.               key: mariadb-password 

  23.       command: 

  24.         - /bin/bash 

  25.         - -ec 

  26.         - | 

  27.           mysql --host=$MARIADB\_HOST --port=$MARIADB\_PORT --user=$WORDPRESS\_DATABASE\_USER --password=$WORDPRESS\_DATABASE\_PASSWORD 

  28.   restartPolicy: Never 

  29. {{- end }} 

  30. ... 


建议为你的图表编写测试并在安装后运行它们。例如,你可以使用 helm test`<RELEASE_NAME>`命令运行测试。这些测试对于验证和发现与Helm安装的应用程序中的问题是很有价值的资产。

6.确保你的秘密安全

敏感数据,如密钥或密码,在Kubernetes中作为机密存储。尽管在Kubernetes方面保护机密是可能的,但它们大多存储为文本文件,作为Helm模板和值的一部分。

helm-secrets插件为您的关键信息提供秘密管理和保护。它将秘密加密委托给Mozilla sop,后者支持AWS KMS、GCP上的Cloud KMS、Azure Key Vault和PGP。

假设你已将敏感数据收集在名为 secrets.yaml 的文件中,如下所示:

postgresql: postgresqlUsername: postgres postgresqlPassword: WoZpCAlBsg postgresqlDatabase: wp

你可以使用插件加密文件:

$ helm secrets enc secrets.yamlEncrypting secrets.yamlEncrypted secrets.yaml

现在,文件将被更新并且所有值都将被加密:

postgresql: postgresqlUsername: ENC\[AES256\_GCM,data:D14/CcA3WjY=,iv...==,type:str\] postgresqlPassword: ENC\[AES256\_GCM,data:Wd7VEKSoqV...,type:str\] postgresqlDatabase: ENC\[AES256\_GCM,data:8ur9pqDxUA==,iv:R...,type:str\]sops: ...

上面secrets.yaml 中的数据并不安全,helm-secrets 解决了将敏感数据存储为Helm charts 的一部分问题。

7.使用模板函数使图表可重用

Helm支持超过60个函数,可以在模板中使用。这些函数在Go模板语言和Sprig模板库中定义。模板文件中的函数显著简化了Helm操作。

让我们以下面的模板文件为例:

apiVersion: v1 kind: ConfigMap metadata:   name: {{ .Release.Name }}-configmap data:   environment: {{ .Values.environment | default "dev" | quote }}   region: {{ .Values.region | upper | quote }}

当没有提供环境值时,模板函数会默认。当检查区域字段时,你会看到模板中没有定义默认值。但是,该字段有另一个名为 upper 的函数,用于将提供的值转换为大写。

另一个重要且有用的功能是`required`. 它使您能够根据模板渲染的需要设置一个值。例如,假设你需要使用以下模板为 ConfigMap 命名:

...metadata: name: {{ required "Name is required" .Values.configName }}...

如果该条目为空,则模板渲染将失败并显示错误 Name is required。创建 Helm 图表时,模板函数非常有用。它们可以改进模板、减少代码重复,并可用于在将应用程序部署到 Kubernetes 之前验证值。

8.当 ConfigMaps 或 Secrets 改变时更新你的部署

将 ConfigMaps 或 Secrets 安装到容器是很常见的。尽管部署和容器映像会随着新版本而变化,但 ConfigMap 或机密不会经常更改。以下注释可以在 ConfigMap 更改时推出新部署:

kind: Deployment spec:   template:     metadata:       annotations:         checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }} ...

ConfigMap 中的任何更改都将计算`sha256sum`新的部署版本并创建新版本。这确保部署中的容器将使用新的 ConfigMap 重新启动。

9. 使用资源策略选择退出资源删除

在典型的设置中,安装 Helm chart 后,Helm 将在集群中创建多个资源。然后,您可以通过更改值以及添加或删除资源来升级它。一旦您不再需要该应用程序,您可以将其删除,这会从集群中移除所有资源。

但是,即使在运行 Helm 卸载之后,某些资源也应保留在集群中。假设您已经使用 PersistentVolumeClaim 部署了一个数据库,并且即使您要删除数据库版本也希望存储卷。对于此类资源,您需要使用资源策略注释,如下所示:

kind: Secretmetadata: annotations: "helm.sh/resource-policy": keep...

Helm 命令(例如卸载、升级或回滚)会导致删除上述机密。但是通过使用如上所示的资源策略,Helm 将跳过秘密的删除并允许它成为孤立的。因此,应该非常小心地使用注释,并且仅用于在 Helm Releases 被删除后所需的资源。

10. 调试 Helm Chart 的有用命令

Helm 模板文件带有许多不同的功能和用于创建 Kubernetes 资源的多个值来源。了解部署到集群的内容是用户的基本职责。因此,你需要学习如何调试模板和验证图表。有四个基本命令可用于调试:

  • helm lint:linter 工具进行一系列测试以确保您的图表正确形成。

  • helm install —dry-run — debug:此函数呈现模板并显示生成的资源清单。您还可以在部署之前检查所有资源,并确保设置了值并且模板功能按预期工作。

  • helm get manifest:此命令检索安装到集群的资源的清单。如果发布未按预期运行,这应该是您用来找出集群中正在运行的内容的第一个命令。

  • helm get values:此命令用于检索安装到集群的版本值。如果您对计算值或默认值有任何疑问,这绝对应该在您的工具带中。

11.使用查找功能避免秘密再生

Helm 函数用于生成随机数据,例如密码、密钥和证书。随机生成会在每次部署和升级时创建新的任意值并更新集群中的资源。例如,它可以在每次版本升级时替换集群中的数据库密码。这会导致客户端在更改密码后无法连接到数据库。

为了解决这个问题,建议随机生成值并覆盖集群中已有的值。例如:

{{- $rootPasswordValue := (randAlpha 16) | b64enc | quote }} {{- $secret := (lookup "v1" "Secret" .Release.Namespace "db-keys") }} {{- if $secret }} {{- $rootPasswordValue = index $secret.data "root-password" }} {{- end -}} apiVersion: v1 kind: Secret metadata:   name: db-keys   namespace: {{ .Release.Namespace }} type: Opaque data:   root-password: {{ $rootPasswordValue}}

上面的模板首先创建一个 16 个字符的 randAlpha 值,然后检查集群中的秘密及其对应的字段。如果找到,它会覆盖并重用 rootPasswordValue 作为 root-password。

12. 迁移到 Helm 3 以获得更简单、更安全的 Kubernetes 应用程序

最新的Helm版本Helm 3提供了许多新功能,使其成为一个更轻、更精简的工具。Helm v3由于其增强的安全性和简单性而推荐使用。这包括:

  • 删除 Tiller:Tiller 是 Helm 服务器端组件,但由于在早期版本中对集群进行更改所需的详尽权限已从 v3 中删除。这也造成了安全风险,因为任何获得 Tiller 访问权限的人都会对您的集群拥有过多的权限。

  • 改进的图表升级策略:Helm v2 依赖于双向策略合并补丁。它将新版本与 ConfigMap 存储中的版本进行比较并应用更改。相反,Helm v3 比较旧清单、集群中的状态和新版本。因此,在升级 Helm 版本时,您的手动更改不会丢失。这简化了升级过程并增强了应用程序的可靠性。

有一个helm-2to3插件,你可以用以下命令安装:

$ helm3 plugin install https://github.com/helm/helm-2to3

它是一个小但有用的插件,带有清理、转换和移动命令,帮助你迁移和清理v2配置,并创建v3版本。

13. 保持持续交付管道的幂等性

Kubernetes 资源是声明性的,因为它们的规范和状态存储在集群中。同样,Helm 需要创建声明性模板和发布。因此,你需要在使用 Helm 时将持续交付和发布管理设计为幂等的。幂等操作是您可以多次应用而不会改变第一次运行后的结果的操作。

有两个基本规则需要遵循:

  • 始终使用该`helm upgrade --install`命令。如果图表尚未安装,它会安装图表。如果它们已经安装,它会升级它们。

  • 使用`--atomic`标志在 helm 升级期间操作失败时回滚更改。这确保 Helm 版本不会停留在失败状态。

概括

Helm 是将应用程序部署到 Kubernetes 集群不可或缺的工具。但是,只有遵循最佳实践,您才能真正获得 Helm 的好处。

本文中介绍的实践将帮助你和你的团队创建、操作和升级生产级分布式应用程序。从开发的角度来看,你的 Helm 图表将更易于维护和保护。在操作方面,你将享受自动更新的部署、从删除中节省资源,并学习如何测试和调试。

Helm的官方指南是检查Helm命令和理解其设计理念的另一个很好的资源。有了这些资源以及本文中概述的最佳实践和示例,就已经准备好创建和管理在Kubernetes上运行的生产级Helm应用程序了。

【51CTO译稿,合作站点转载请注明原文译者和出处为51CTO.com】