建议看原文。
本指南将带您了解如何创建 Helm 图表,包括结构、组件及最佳实践。如果您想学习 Helm 图表的基础知识,并亲自动手操作 Helm 图表,您会喜欢这篇指南的。
准备工作
- 一个已经在运行中的kubernetes集群。没有的话可以使用kubeasz或者k3s快速拉起一个kubernetes集群
- 已经安装了helm命令行工具。如果还没有安装赶紧去helm官网去下载安装吧
- 连接到集群的有效
kubeconfig
文件 - 对 Kubernetes 和 YAML 有一定的了解
什么是 Helm Chart?
为了说明 Helm Chart的概念,我们选择一个简单的示例:在 Kubernetes 上使用 Nginx 部署前端网页。
假设你的项目中有四个不同的环境。开发环境(Dev)、质量保证环境(QA)、预生产环境(Staging)和生产环境(Prod)。每个环境对于 Nginx 的部署都有不同的参数,例如:
- 开发和 QA 环境可能只需要一个副本
- 预生产和生产环境会有更多的副本,并带有 Pod 自动伸缩功能
- 每个环境的 Ingress 路由规则都不同
- 每个环境的配置(ConfigMap)和保密字典(Secret)也不同
由于每个环境的配置和部署参数发生变化,您需要为每个环境维护不同的 Nginx 部署文件。或者,您会有一个单一的部署文件,并需要编写自定义的 Shell 或 Python 脚本来根据环境替换相应的值。然而,这种方法不够可扩展。这就是 Helm Chart发挥作用的地方。

Helm 图表是由 Kubernetes YAML 清单模板和特定于 Helm 的文件组成的组合。您可以将其视为 Helm 包。因为 Kubernetes YAML 清单可以被模板化,所以您不必为不同的环境维护多个 Helm Chart。Helm 使用 Go 模板引擎来实现模板化功能。
您只需拥有一个单一的 Helm Chart,并可以通过更改单一的 values
文件来修改每个环境的部署参数。Helm 会负责将值应用到模板中。我们将在接下来的部分中实际操作更多内容。
从高层次上看,Helm 图表通过单一模板减少了每个环境 (开发、UAT、CUG、生产) 的复杂性和 Kubernetes 清单的冗余。
Helm Chart结构
为了理解 Helm 图表,我们以 Nginx 的部署为例。要在 Kubernetes 上部署 Nginx,通常会包含以下 YAML 文件:
nginx-deployment
├── configmap.yaml
├── deployment.yaml
├── ingress.yaml
└── service.yaml
如果我们为上述 Nginx 部署创建一个 Helm 图表,它将具有以下目录结构:
nginx-chart/
|-- Chart.yaml
|-- charts
|-- templates
| |-- NOTES.txt
| |-- _helpers.tpl
| |-- deployment.yaml
| |-- configmap.yaml
| |-- ingress.yaml
| |-- service.yaml
| `-- tests
| `-- test-connection.yaml
`-- values.yaml
如您所见,部署 YAML 文件是模板目录的一部分(以粗体突出显示),并且还有特定于 Helm 的文件和文件夹。让我们查看 Helm Chart中的每个文件和目录及其重要性。
-
.helmignore: 用于定义不想包含在 Helm 图表中的所有文件。它的作用类似于
.gitignore
文件。 -
Chart.yaml: 包含有关 Helm 图表的信息,如版本、名称、描述等。
-
values.yaml: 在此文件中定义 YAML 模板的值。例如,镜像名称、副本数量、HPA 值等。正如前面所述,仅
values.yaml
文件会在每个环境中发生变化。此外,您还可以动态地覆盖这些值或在安装图表时使用--values
或--set
命令覆盖它们。 -
charts: 如果我们的主要图表依赖于其他图表,我们可以在这个目录内添加其他图表的结构。默认情况下,此目录为空。
-
templates: 此目录包含构成应用程序的所有 Kubernetes 清单文件。这些清单文件可以被模板化以访问
values.yaml
文件中的值。Helm 为 Kubernetes 对象(如deployment.yaml
、service.yaml
等)创建一些默认模板,可以直接使用、修改或用我们的文件覆盖它们。 -
templates/NOTES.txt: 这是一个纯文本文件,在成功部署图表后会被打印出来。
-
templates/_helpers.tpl: 该文件包含几种方法和子模板。这些文件不会渲染为 Kubernetes 对象定义,但在其他图表模板中可供使用。
-
templates/tests/: 我们可以在图表中定义测试以验证图表在安装时是否按预期工作。
Helm Chart教程GitHub仓库
本 Helm 图表教程中使用的示例 Helm 图表和清单托管在 Helm 图表 GitHub 仓库中。您可以克隆它并使用它来跟随指南一起操作。
git clone https://github.com/techiescamp/helm-tutorial.git
从零开始创建 Helm Chart
为了亲自动手创建 Helm 图表,让我们从零开始创建一个 Nginx Helm Chart。
执行以下命令来创建图表骨架。它会创建一个名为 nginx-chart
的Chart,并带有默认的文件和文件夹。
helm create nginx-chart
它将包含以下文件和目录:
nginx-chart
│ ├── Chart.yaml
│ ├── charts
│ ├── templates
│ │ ├── NOTES.txt
│ │ ├── _helpers.tpl
│ │ ├── deployment.yaml
│ │ ├── hpa.yaml
│ │ ├── ingress.yaml
│ │ ├── service.yaml
│ │ ├── serviceaccount.yaml
│ │ └── tests
│ │ └── test-connection.yaml
│ └── values.yaml
让我们进入生成的图表目录。
cd nginx-chart
我们将根据部署需求逐一编辑文件。
Chart.yaml
如上所述,我们在 Chart.yaml
文件中放置图表的详细信息。用以下内容替换 chart.yaml
的默认内容。
- apiVersion : Chart API 版本。v2 适用于 Helm 3,v1 适用于以前的版本。
- name : Chart的名称
- description : Helm Chart的描述
- Type :Chart类型可以是“application”或“library”。Application Chart是在 Kubernetes 上部署的。Library Chart是可以与其他Chart一起使用的可重用Chart。类似于编程中的库。
- Version :Chart版本
- appVersion :我们应用程序 (Nginx) 的版本号
- maintainers :Chart所有者的信息
apiVersion: v2
name: nginx-chart
description: My First Helm Chart
type: application
version: 0.1.0
appVersion: "1.0.0"
maintainers:
- email: [email protected]
name: devopscube
每次修改应用程序时,我们都应递增 version
和 appVersion
。还有一些其他字段,如依赖项、图标等。
templates
Helm 在 templates
目录中创建了多个文件。在本例中,我们将处理简单的 Kubernetes Nginx 部署。
让我们删除 templates
目录中的所有默认文件。
rm -rf templates/*
我们将添加 Nginx YAML 文件,并将其更改为模板以更好地理解。
创建一个 deployment.yaml
文件,并复制以下内容。
apiVersion: apps/v1
kind: Deployment
metadata:
name: release-name-nginx
labels:
app: nginx
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx-chart
image: "nginx:1.16.0"
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: nginx-index-file
mountPath: /usr/share/nginx/html/
volumes:
- name: nginx-index-file
configMap:
name: index-html-configmap
如果你查看上面的 YAML 文件,会发现其中的值是静态的。Helm Chart的理念是对 YAML 文件进行模板化处理,这样我们就可以通过动态分配值来重复使用它们。
要模板化一个值,您只需要将对象参数添加到大括号中,如下面所示。这被称为模板指令,语法是特定于 Go 模板的。
首先,让我们了解什么是“对象(Object)”。以下是本例中使用的三个对象(Object)。
- Release: 每个 Helm Chart部署的时候都会指定一个应用名(Release name)。如果您想在模板中使用这个名字或者在程序中访问它,可以使用这个Release Object。
- Chart: 如果您想使用在
chart.yaml
中提到的任何值,可以使用chart
对象 - Values:
values.yaml
文件中的所有参数都可以通过Values
对象访问。
了解有关支持的对象的更多信息,请查看 Helm 内置对象文档。
以下图像显示了内置对象在模板中是如何被替换的。

首先,您需要确定哪些值可能会改变,或者您想要模板化哪些值。我选择了 name
, replicas
, container name
, image
,imagePullPolicy
,configMap Name
,我在 YAML 文件中以粗体标出了这些内容。
-
name: {{ .Release.Name }}-nginx
:我们需要每次更改部署名称,因为 Helm 不允许使用相同名称安装发布。因此,我们将使用发布名称模板化部署名称,并在其后插补-nginx
。现在,如果我们使用名称frontend
创建一个发布,部署名称将是frontend-nginx
。这样,我们就能保证名称唯一。 -
container name: {{ .Chart.Name }}
:对于容器名称,我们将使用Chart
对象,并使用chart.yaml
中的Chart名称作为容器名称。 -
Replicas: {{ .Values.replicaCount }}
:我们将从values.yaml
文件中访问副本数量的值。 -
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
:在这里,我们正在单行中使用多个模板指令,并从 Values 文件中的 image字段获取镜像仓库和镜像标签信息。 -
configMap Name: {{ .Release.Name }}-index-html-configmap
:在这里,我们正在将应用名称添加到ConfigMap中。
我们已经完成了 deployment.yaml
文件的模板化。下面是最终的 deployment.yaml
文件,其中模板化部分已加粗显示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-nginx
labels:
app: nginx
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: 80
protocol: TCP
volumeMounts:
- name: nginx-index-file
mountPath: /usr/share/nginx/html/
volumes:
- name: nginx-index-file
configMap:
name: {{ .Release.Name }}-index-html-configmap
应用模板化后的 service.yaml
文件
在 protocol
模板指令中,可以看到管道符 (|
)。它用于定义协议的默认值为 TCP。这意味着,如果我们不在 values.yaml
文件中定义协议值或留空,则默认采用 TCP 协议。
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}-service
spec:
selector:
app.kubernetes.io/instance: {{ .Release.Name }}
type: {{ .Values.service.type }}
ports:
- protocol: {{ .Values.service.protocol | default "TCP" }}
port: {{ .Values.service.port }}
targetPort: {{ .Values.service.targetPort }}
应用模板化后的 configmap.yaml
文件
这里我们替换了默认的 Nginx index.html
页面,并且在 HTML 中添加了一个模板指令来替换环境名称。
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-index-html-configmap
namespace: default
data:
index.html: |
<html>
<h1>Welcome</h1>
</br>
<h1>Hi! I got deployed in {{ .Values.env.name }} Environment using Helm Chart </h1>
</html
values.yaml
更新 values.yaml
文件以包含所有需要替换的值。下面是我们更新后的 values.yaml
文件:
replicaCount: 2
image:
repository: nginx
tag: "1.16.0"
pullPolicy: IfNotPresent
service:
name: nginx-service
type: ClusterIP
port: 80
targetPort: 9000
env:
name: dev
最终 Helm 图表结构
此时,我们已经准备好了 Nginx Helm 图表,其最终结构如下:
nginx-chart
├── Chart.yaml
├── charts
├── templates
│ ├── configmap.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── values.yaml
验证 Helm Chart
现在要确保我们的Chart有效,并且所有缩进都正常,我们可以运行以下命令。请确保您在Chart目录内。
helm lint .
如果你从 nginx-chart
目录外执行它,请提供完整的路径
helm lint /path/to/nginx-chart
如果没有错误或问题,您将看到类似以下的结果:
==> Linting ./nginx
[INFO] Chart.yaml: icon is recommended
1 chart(s) linted, 0 chart(s) failed
为了验证值是否正确替换到了模板中,可以使用以下命令渲染模板化的 YAML 文件以及值。
helm template .
我们也可以使用 --dry-run
命令来检查。这会假装安装图表到集群中,如果有任何问题,它将显示错误。
helm install --dry-run my-release nginx-chart
如果一切正常,那么您将看到将部署到集群中的清单输出。
部署 Helm Chart
现在我们准备安装Chart。
确保在 Helm Chart目录之外运行 Helm 命令。
执行以下命令,其中 frontend
是发布名称,nginx-chart
是Chart名称。这会在默认命名空间中安装 nginx-chart
。
helm install frontend nginx-chart
NAME: frontend
LAST DEPLOYED: Wed Jun 19 11:12:20 2024
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
您可以使用以下命令检查发布列表:您也可以使用 ls
代替 list
helm list
使用 kubectl
命令检查Deployment、Service、ConfigMaps和Pod。
kubectl get deployment
kubectl get services
kubectl get configmap
kubectl get pods
我们可以看到部署 frontend-nginx
, nginx-service
和 pods 已经启动并正在运行,如下所示。

我们讨论了如何使用不同的 values.yaml
文件将单一的 helm Chart用于多个环境。要使用外部 values.yaml
文件安装 helm Chart,可以使用以下命令并带上 --values
标志和值文件的路径。
helm install frontend nginx-chart --values env/prod-values.yaml
当你在 CI/CD 流水线中使用 Helm 时,你可以编写自定义逻辑来根据环境传递所需的值文件。
Helm 升级与回滚
假设您想要修改Chart并安装更新后的版本,可以使用以下命令:
helm upgrade frontend nginx-chart
例如,我们将副本数量从 2 改为 1。你可以看到修订版本号是 2,且只有 1 个 Pod 在运行。

要撤销刚刚所做的更改并重新部署之前的版本,可以使用回滚命令来完成。
helm rollback frontend
上述命令将 Helm 发布回滚到上一个版本。

回滚后,我们可以看到又有 2 个 Pod 在运行。请注意,Helm 将回滚视为一个新的修订版本,这就是为什么我们的修订版本会变成 3 的原因。
如果我们想要回滚到特定版本,可以这样输入修订编号。
helm rollback <release-name> <revision-number>
例如:
helm rollback frontend 2
卸载Helm应用
要卸载 helm 发布版本,请使用卸载命令。它将删除与该图表最后一次发布相关的所有资源。
helm uninstall frontend
如果你已在特定的命名空间中部署了发布,可以根据以下的卸载命令传递命名空间标志。
helm uninstall <release-name> --namespace <namespace>
打包 Helm Chart
我们可以将图表打包并部署到 Github、S3 或任何CHart仓库。
执行以下命令来打包 nginx-chart
。请注意,这里的 nginx-chart
需要根据实际情况进行替换。
helm package chart-name/
例如:
helm package nginx-chart
Successfully packaged chart and saved it to: /home/vagrant/helm-tutorial/nginx-chart-0.1.0.tgz
当你进行打包时,它遵循 semver 2 版本指南。
调试 Helm Chart
我们可以使用以下命令来调试 helm charts 和模板。
-
helm lint
:此命令接收一个指向Chart的路径,并运行一系列测试以验证该Chart结构是否正确 -
helm get values
:此命令将输出已安装到集群的应用的value值 -
helm install --dry-run
:使用此功能,我们可以检查所有资源清单,并确保所有模板都能正常工作 -
helm get manifest
:此命令将输出在集群中运行的资源清单 -
helm diff
:输出两个修订版之间的差异
Helm Chart可能遇到的错误
如果你尝试安装已存在的 Helm 包,你会收到以下错误。
Error: INSTALLATION FAILED: cannot re-use a name that is still in use
要更新或升级版本,你需要运行升级命令。
如果你尝试从不同位置安装图表,而没有给出图表的绝对路径,你会收到以下错误。
Error: non-absolute URLs should be in form of repo_name/path_to_chart
要纠正此问题,您应该从包含图表的目录执行 helm 命令,或者提供图表目录的绝对路径或相对路径。
Helm Chart最佳实践
以下是开发 Helm Chart时应遵循的一些最佳实践:
-
通过添加注释和 README 文件来记录你的图表,因为文档对于确保可维护的 Helm Chart至关重要。
-
应该按照对象的类型(例如Deployment、Service、Secret、Ingress等)来命名 Kubernetes 清单文件。
-
将Chart名称全部转换为小写,如果名称由多个单词组成,则用连字符(-)分隔。
-
values.yaml
文件中的字段名应全为小写。 -
总是在字符串值周围加上引号。
-
使用 Helm v3 以获得更简单且更安全的发布。详情请参考此文档。
总结
综上所述:
- 我们详细讨论了 Helm Chart 及其结构。
- 我们从零开始创建了一个 Helm Chart并进行了部署。
- 我们还学习了如何升级、回滚和卸载 Helm Chart。
Helm 是 Kubernetes 的一个非常有用的包管理器。当你有不同的环境和自定义部署需求时,Helm 提供了一种很好的方式来根据需求模板化 Kubernetes 清单。
Helm 特有的功能,如Chart依赖关系和Chart可重用性,使其成为优秀的 Kubernetes 工具之一。
此外,如果你正在准备 CKAD 认证,Helm 是考试中的一个重要主题。
Helm 的替代方案是 Kustomize。它不使用模板,而是采用覆盖的概念。请参阅 Kustomize 教程以了解更多信息。
此外,如果您查看我们的 Kubernetes 学习指南,我们已经将 Helm 作为 Kubernetes 包管理的必备学习工具提及。