git clone https://github.com/techiescamp/helm-tutorial.git
### **从头开始创建 Helm 图表**
为了亲身体验 helm chart 的创建,让我们从头开始**创建一个 Nginx helm chart**。
执行以下命令以创建图表样板。它创建一个具有默认文件和文件夹名称的图表。`nginx-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 进入生成的图表目录。
cd nginx-chart
我们将根据部署要求**逐个编辑文件**。
#### Chart.yaml
如上所述,我们将图表的详细信息存档。将 的默认内容替换为以下内容。`Chart.yaml``chart.yaml`
apiVersion: v2
name: nginx-chart
description: My First Helm Chart
type: application
version: 0.1.0
appVersion: “1.0.0”
maintainers:
- email: contact@devopscube.com
name: devopscube
1. **apiVersion**:这表示图表 API 版本。v2 用于 Helm 3,v1 用于以前的版本。
2. **name:**表示图表的名称。
3. **description:**表示 helm 图表的描述。
4. **Type**:图表**类型**可以是“**应用程序**”或“**库**”。应用程序图表是您在 Kubernetes 上部署的内容。库图表是可重复使用的图表,可与其他图表一起使用。编程中类似的库概念。
5. version:图表**版本**。
6. **appVersion**:这表示我们应用程序(Nginx)的版本号。
7. maintainers**:**有关图表所有者的信息。
每次对应用程序进行更改时,`version``appVersion`应该递增。还有一些其他字段,如dependencies,icons 等。
#### templates
Helm 创建的目录中有多个文件。在我们的例子中,我们将进行简单的 Kubernetes Nginx 部署。`templates`
从模板目录中删除所有默认文件。
rm -rf templates/*
我们将添加我们的 Nginx YAML 文件并将它们更改为模板,以便更好地理解。
创建一个文件并复制以下内容。`deployment.yaml`
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: “nginx:1.16.0”
imagePullPolicy: IfNotPresent
ports:
- name: http
containerPort: 80
protocol: TCP
上面的 YAML 文件,则值是静态的。helm chart 的想法是将 YAML 文件模板化,以便我们可以通过动态地为它们分配值来在多个环境中重用它们。
要对值进行模板化,只需在大括号内添加 **object 参数**,如下所示。它被称为**模板指令**,语法特定于 **Go 模板**
{{ .Object.Parameter }}
首先,让我们了解什么是对象。以下是我们将在此示例中使用的三个对象。
1. **发布**:每个 helm 图表都将使用发布名称进行部署。如果要使用发布名称或访问模板中与发布**相关的动态值**,可以使用发布对象。
2. **图表**:如果要使用 **chart.yaml** 中提到的任何值,可以使用图表对象。
3. **值**:**values.yaml** 文件中的所有参数都可以使用 Values 对象进行访问。
要了解有关支持的对象的更多信息,请查看 [Helm 内置对象]( )文档。
下图显示了如何在模板中替换内置对象。
[](https://devopscube.com/wp-content/uploads/2022/12/helm-template.png)
首先,您需要弄清楚哪些值可以更改或要模板化哪些值。我正在选择名称、副本、**容器名称、图像**和 **imagePullPolicy**,我在 YAML 文件中以粗体突出显示了它们。
1. **name: :**我们每次都需要更改部署名称,因为 Helm 不允许我们安装具有相同名称的版本。因此,我们将使用发布名称模板化部署名称,并随之插值 **-nginx**。现在,如果我们使用名称 **frontend** 创建发布,则部署名称将为 **frontend-nginx**。这样,我们将有保证的唯一名称。`name: {{ .Release.Name }}-nginx`
2. **container name**: :对于容器名称,我们将使用 Chart 对象,并使用 **chart.yaml** 中的图表名称作为容器名称。`{{ .Chart.Name }}`
3. **Replicas:**我们将从 **values.yaml**文件中访问副本值。`{{ .Values.replicaCount }}`
4. **image:** 在这里,我们在一行中使用多个模板指令,并从 Values 文件中访问映像键下的存储库和标记信息。`"{{ .Values.image.repository }}:{{ .Values.image.tag }}"`
同样,您可以在 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
创建文件并复制以下内容。`**service.yaml**`
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 }}
在**协议模板指令**中,您可以看到一个管道。它用于将协议的默认值定义为 TCP。因此,这意味着我们不会在 **`values.yaml`**文件中定义协议值,或者如果它为空,它将采用 TCP 作为协议的值。`( | )`
创建一个**`configmap.yaml`**,并在其中添加以下内容。在这里,我们将默认的 Nginx **index.html** 页面替换为自定义 HTML 页面。此外,我们还添加了一个模板指令来替换 HTML 中的环境名称。
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}-index-html-configmap
namespace: default
data:
index.html: |
Welcome
Hi! I got deployed in {{ .Values.env.name }} Environment using Helm Chart
</html
#### values.yaml
该文件包含我们在模板中使用的模板指令中需要替换的所有值。例如,template 包含一个模板指令,用于从 **`values.yaml`** 文件中获取映像存储库、标记和 pullPolicy。如果检查以下 **`values.yaml`** 文件,则在映像键下嵌套了 repository、tag 和 pullPolicy 键值对。这就是我们使用 **`Values.image.repository`** 的原因`values.yaml``deployment.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
现在我们已经准备好了 Nginx helm chart,最终的 helm chart 结构如下所示。
nginx-chart
├── Chart.yaml
├── charts
├── templates
│ ├── configmap.yaml
│ ├── deployment.yaml
│ └── service.yaml
└── values.yaml
### **验证 Helm Chart**
现在,为了确保我们的图表有效并且所有缩进都很好,我们可以运行以下命令。确保您位于图表目录中。
helm lint .
如果您从 nginx-chart 目录外部执行它,请提供 **`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**
部署图表时,Helm 将从文件中读取图表和配置值,并生成清单文件。然后它会将这些文件发送到 Kubernetes API 服务器,Kubernetes 将在集群中创建请求的资源。`values.yaml`
现在我们准备安装图表了。
执行以下命令,其中 is release name 和 is the chart name。它将 **`nginx-chart`** 安装在默认命名空间中
helm install frontend nginx-chart
您将看到如下所示的输出。
NAME: frontend
LAST DEPLOYED: Tue Dec 13 10:15:56 2022
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
现在,您可以使用以下命令检查版本列表:
helm list
执行kubectl命令,查看部署、服务和Pod。
kubectl get deployment
kubectl get services
kubectl get configmap
kubectl get pods
我们可以看到部署 **`frontend-nginx、nginx-service`** 和 pod 已启动并运行,如下所示。
[](https://devopscube.com/wp-content/uploads/2022/12/image-7.png)
我们讨论了如何使用不同的 **`values.yaml`**文件将单个 helm 图表用于多个环境。若要使用外部文件安装 helm 图表,可以将以下命令与值文件的标志和路径一起使用。`**values.yaml**``--values`
helm install frontend nginx-chart --values env/prod-values.yaml
将 Helm 作为 CI/CD 管道的一部分时,可以编写自定义逻辑,以根据环境传递所需的值文件。
### **Helm 升级和回滚**
现在假设您要修改图表并安装更新版本,我们可以使用以下命令:
helm upgrade frontend nginx-chart
例如,我们将副本从 2 更改为 1。您可以看到修订号为 2,并且只有 1 个 pod 在运行。
[](https://devopscube.com/wp-content/uploads/2022/12/image-8.png)
现在,如果我们想回滚刚刚完成的更改并再次部署上一个更改,我们可以使用 rollback 命令来执行此操作。
helm rollback frontend
上面的命令会将 helm 版本回滚到上一个版本。
[](https://devopscube.com/wp-content/uploads/2022/12/image-10.png)
回滚后,我们可以看到 2 个 pod 再次运行。请注意,Helm 将回滚作为新修订版,这就是我们将修订版作为 3 的原因。
如果我们想回滚到特定版本,我们可以像这样输入修订号。
helm rollback
例如
helm rollback frontend 2
### **卸载 Helm 版本**
要卸载 helm 版本,请使用 uninstall 命令。它将删除与图表的上一个版本关联的所有资源。
helm uninstall frontend
我们可以将图表打包并部署到 Github、S3 或任何其他平台。
helm package frontend
### **调试 Helm Chart**
我们可以使用以下命令来调试 helm chart 和模板。
1. **`helm lint:`**此命令采用图表的路径,并运行一系列测试以验证图表的格式是否正确。
2. **`helm get values:`**此命令将输出安装到群集的发布值。
3. **`helm install --dry-run:`**使用此函数,我们可以检查所有资源清单并确保所有模板都正常工作。
4. **`helm get manifest:`**此命令将输出群集中运行的清单。
5. **`helm diff:`**它将输出两个修订版本之间的差异。
helm diff revision nginx-chart 1 2
### **Helm Chart 可能的错误**
如果尝试安装现有的 Helm 包,将出现以下错误。
Error: INSTALLATION FAILED: cannot re-use a name that is still in use
要更新或升级版本,您需要运行 upgrade 命令。
如果您尝试从其他位置安装图表,而没有给出图表的绝对路径,则会出现以下错误。
Error: non-absolute URLs should be in form of repo_name/path_to_chart
要解决此问题,您应该从拥有图表的目录执行 helm 命令,或者提供图表目录的绝对路径或相对路径。
### **Helm Charts 最佳实践**