Kubernetes 入门教程之七

大纲

Kubernetes 核心技术

Helm

Helm 的引入

在 Kubernetes 中,应用由特定的资源对象组成,如 Deployment、Service、Ingress 等。通常,这些资源的配置会分别保存在多个独立的 YAML 资源文件中,或集中写入一个 YAML 资源文件中,然后通过 kubectl apply -f 命令进行部署。对于只包含一个或少数几个服务的简单应用,这种方式已经足够。但对于复杂应用(例如微服务架构的系统),往往由十几个甚至数十个服务组成。如果需要更新或回滚应用,就必须修改和维护大量的 YAML 资源文件,这种分散式的管理方式显得十分低效。此外,由于缺乏对应用整体的版本管理与控制,Kubernetes 在应用的维护与更新方面面临以下主要问题:

  • (1) YAML 资源文件难以实现高效复用;
  • (2) YAML 资源文件不支持应用级别的版本管理与回滚;
  • (3) 难以将多个服务作为一个整体进行统一管理。

为此,Kubernetes 引入了 Helm 来解决上述问题。

Helm 的概念

Helm 是 Kubernetes 的包管理工具,类似于 Linux 下的包管理器(如 yumapt),可以方便地将预先打包好的 YAML 资源文件部署到 Kubernetes 集群中。Helm 主要包含以下三个核心概念:

  • (1) Helm:命令行客户端工具,用于创建、打包、发布和管理 Kubernetes 应用的 Chart。
  • (2) Chart:应用的描述包,由一组用于定义 Kubernetes 资源的 YAML 资源文件组成。
  • (3) Release:基于 Chart 的部署实体。每当通过 Helm 部署一个 Chart 时,都会在 Kubernetes 集群中自动生成一个对应的 Release,用于表示实际运行的资源对象。

值得注意的是,在 Chart 安装后,Helm 会自动创建一个对应的 Release 对象,并根据 Chart 模板文件创建相应的 Kubernetes 资源对象(如 Deployment、Service、Ingress 等),随后由控制器(Controller)自动拉起并运行相应的 Pod。

Helm 的版本变化

2019 年 11 月 13 日,Helm 团队发布 Helm v3 的第一个稳定版本。该版本的主要变化如下:

  • (1) 最明显的变化是 Tiller 的删除
  • (2) Release 名称可以在不同命名空间中重用
  • (3) 支持将 Chart 推送至 Docker 镜像仓库中
  • (4) 使用 JSONSchema 验证 Chart Values
  • (5) 其他变化

Helm v2v3 版本的整体架构对比如下图所示:

Helm 客户端安装

特别注意

  • Helm 不同版本的客户端可以从 GitHub Releases 下载得到。
  • 通常只需要在 Kubernetes 集群的 Master 节点上安装 Helm,其他 Worker 节点不需要安装 Helm。

Helm 客户端的安装

1
2
3
4
5
6
7
8
9
10
11
# 下载压缩包
wget https://get.helm.sh/helm-v3.2.1-linux-amd64.tar.gz

# 解压压缩包
tar -zxvf helm-v3.2.1-linux-amd64.tar.gz

# 移动文件
sudo mv linux-amd64/helm /usr/bin/

# 查看版本
helm version

Helm 客户端配置国内 Chart 仓库(存储库)

  • 微软仓库:

    • 仓库地址:http://mirror.azure.cn/kubernetes/charts
    • 这个 Chart 仓库推荐使用,基本上 Kubernetes 官方仓库有的 Chart 它都有。
  • 阿里云仓库:

    • 仓库地址:https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts
    • 这个 Chart 仓库国内可以正常访问。
  • 官方仓库:

    • 仓库地址:https://hub.kubeapps.com/charts/incubator
    • Kubernetes 官方的 Chart 仓库,国内可能无法正常访问。

  • 添加新的仓库
1
2
3
4
5
6
7
8
# 添加微软仓库
helm repo add stable http://mirror.azure.cn/kubernetes/charts

# 添加阿里云仓库
helm repo add aliyun https://kubernetes.oss-cn-hangzhou.aliyuncs.com/charts

# 更新本地仓库索引
helm repo update
  • 查看已有的存储库
1
2
3
4
5
# 查看已添加的仓库列表
helm repo list

# 在本地仓库中搜索名称包含 stable 的 Chart
helm search repo stable
  • 删除已有的存储库
1
2
3
4
5
# 删除名称为 aliyun 的仓库  
helm repo remove aliyun

# 更新本地仓库索引
helm repo update

Helm 的常用命令

Chart 的三个核心命令

  • chart install:安装一个新的 Chart,并在集群中创建对应的应用实例。
  • chart upgrade:升级已安装的 Chart 到新版本或更新其配置。
  • chart rollback:将已部署的 Chart 回滚到指定的历史版本。

Chart 的常用命令列表

命令描述
create创建一个 Chart 并指定名称
dependency管理 Chart 依赖
get下载一个 Release,可用于命令:allhooksmanifestnotesvalues
history获取 Release 历史
install安装一个 Chart
list列出 Release
package将 Chart 目录打包到 Chart 存档文件中
pull从远程仓库中下载 Chart 并解压到本地
repo添加、列出、移除、更新和索引 Chart 仓库,可用于命令:addindexlistremoveupdate
rollback从之前版本回滚
search根据关键字搜索 Chart,可用于命令:hubrepo
show查看 Chart 的详细信息,可用于命令:allchartreadmevalues
status显示已命名版本的状态
template本地呈现模板
uninstall卸载一个 Release
upgrade更新一个 Release
version查看 Helm 客户端的版本

Helm 的使用案例

创建管理员用户

提示

本节将演示如何在 Kubernetes 集群中创建管理员用户,否则在后续使用 Helm 时,可能无法正常访问 Kubernetes 资源,比如执行 helm install 命令会出现错误:Error: Kubernetes cluster unreachable

  • 通过 YAML 文件(比如 admin-user-sa.yaml)创建管理员用户 admin-user
1
2
3
4
5
apiVersion: v1
kind: ServiceAccount
metadata:
name: admin-user
namespace: kube-system
1
kubectl apply -f admin-user-sa.yaml
  • 通过 YAML 文件(比如 admin-user-rolebinding.yaml)给管理员用户 admin-user 授权
1
2
3
4
5
6
7
8
9
10
11
12
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: admin-user-binding
subjects:
- kind: ServiceAccount
name: admin-user
namespace: kube-system
roleRef:
kind: ClusterRole
name: cluster-admin
apiGroup: rbac.authorization.k8s.io
1
kubectl apply -f admin-user-rolebinding.yaml
  • 获取管理员用户 admin-user 的 Token
1
2
3
SECRET_NAME=$(kubectl get sa admin-user -n kube-system -o jsonpath="{.secrets[0].name}")

kubectl get secret $SECRET_NAME -n kube-system -o jsonpath="{.data.token}" | base64 --decode
  • 获取 Kubernetes 集群 CA 证书的 Base64 编码(请自行更改 CA 证书的路径
1
cat /opt/kubernetes/ssl/ca.pem | base64 -w 0
  • 创建一个 kubeconfig 文件(比如 admin-user.kubeconfig
1
2
3
4
5
# 创建配置目录(可自定义)
mkdir -p /opt/kubernetes/cfg

# 创建并编辑文件,写入以下 YAML 配置内容
vim /opt/kubernetes/cfg/admin-user.kubeconfig
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: v1
kind: Config
clusters:
- cluster:
server: https://<IP>:6443 # 填写 API Server 的 IP 地址和端口
certificate-authority-data: <CA_CERT_BASE64> # 填写 K8s 集群 CA 证书的 Base64 编码
name: kubernetes
contexts:
- context:
cluster: kubernetes
namespace: default
user: admin-user
name: admin-context
current-context: admin-context
users:
- name: admin-user
user:
token: <TOKEN> # 填写管理员用户的 Token
  • 验证 kubeconfig 文件(比如 admin-user.kubeconfig)是否可以正常使用
1
kubectl get svc --kubeconfig=/opt/kubernetes/cfg/admin-user.kubeconfig
  • 添加系统环境变量 KUBECONFIG(可选步骤)
1
2
3
4
5
# 添加系统环境变量
export KUBECONFIG=/opt/kubernetes/cfg/admin-user.kubeconfig

# 之后就可以直接访问 K8s 资源了,不再需要通过 "--kubeconfig" 参数指定 kubeconfig 文件
kubectl get svc
通过 Chart 部署应用

提示

  • 本节将演示如何使用 Chart 快速部署应用(比如 Weave,这是 Kubernetes 集群可视化与监控工具)。

注意

  • 如果 helm 命令执行失败,并提示错误信息 Error: Kubernetes cluster unreachable,可以参考以下任意一种方案来解决:
  • (1) 尝试往 helm 命令的末尾添加参数 --kubeconfig=/opt/kubernetes/cfg/admin-user.kubeconfig
  • (2) 通过 export KUBECONFIG=/opt/kubernetes/cfg/admin-user.kubeconfig 命令添加对应的环境变量。
  • 搜索指定的 Chart
1
helm search repo weave
1
2
3
4
5
NAME              	CHART VERSION	APP VERSION	DESCRIPTION                                       
aliyun/weave-cloud 0.1.2 Weave Cloud is a add-on to Kubernetes which pro...
aliyun/weave-scope 0.9.2 1.6.5 A Helm chart for the Weave Scope cluster visual...
stable/weave-cloud 0.3.9 1.4.0 DEPRECATED - Weave Cloud is a add-on to Kuberne...
stable/weave-scope 1.1.12 1.12.0 DEPRECATED - A Helm chart for the Weave Scope c...
  • 查看指定 Chart 的详细信息
1
helm show chart stable/weave-scope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
appVersion: 1.12.0
deprecated: true
description: DEPRECATED - A Helm chart for the Weave Scope cluster visualizer.
home: https://www.weave.works/oss/scope/
icon: https://avatars1.githubusercontent.com/u/9976052?s=64
keywords:
- containers
- dashboard
- monitoring
name: weave-scope
sources:
- https://github.com/weaveworks/scope
version: 1.1.12
  • 安装指定的 Chart
1
helm install ui stable/weave-scope
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NAME: ui
LAST DEPLOYED: Tue Oct 28 20:17:33 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
You should now be able to access the Scope frontend in your web browser, by
using kubectl port-forward:

kubectl -n default port-forward $(kubectl -n default get endpoints \
ui-weave-scope -o jsonpath='{.subsets[0].addresses[0].targetRef.name}') 8080:4040

then browsing to http://localhost:8080/.
For more details on using Weave Scope, see the Weave Scope documentation:

https://www.weave.works/docs/scope/latest/introducing/
  • 查看发布(Release)的列表
1
helm list
1
2
NAME	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART             	APP VERSION
ui default 1 2025-10-28 20:17:33.899483553 +0800 CST deployed weave-scope-1.1.12 1.12.0
  • 查看指定发布(Release)的详细信息
1
helm status ui
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
NAME: ui
LAST DEPLOYED: Tue Oct 28 20:17:33 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
NOTES:
You should now be able to access the Scope frontend in your web browser, by
using kubectl port-forward:

kubectl -n default port-forward $(kubectl -n default get endpoints \
ui-weave-scope -o jsonpath='{.subsets[0].addresses[0].targetRef.name}') 8080:4040

then browsing to http://localhost:8080/.
For more details on using Weave Scope, see the Weave Scope documentation:

https://www.weave.works/docs/scope/latest/introducing/
  • 查看所有 Pod 的运行状态
1
kubectl get pods
1
2
3
4
5
6
7
NAME                                            READY   STATUS    RESTARTS   AGE
weave-scope-agent-ui-lw2lf 1/1 Running 0 35s
weave-scope-agent-ui-nn4vs 1/1 Running 0 35s
weave-scope-agent-ui-pzqgk 1/1 Running 0 35s
weave-scope-agent-ui-qbcvm 1/1 Running 0 35s
weave-scope-cluster-agent-ui-5cbc84db49-4wvvt 1/1 Running 0 35s
weave-scope-frontend-ui-6698fd5545-4lpl9 1/1 Running 0 35s
  • 查看所有 Service
1
kubectl get svc
1
2
3
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 86d
ui-weave-scope ClusterIP 10.0.0.64 <none> 80/TCP 78s
  • 若希望在 Kubernetes 集群外部访问 Weave,可以更改 Service 的类型
1
2
# 编辑 Service 的配置,更改 type 参数,保存退出后自动生效
kubectl edit svc ui-weave-scope
1
2
3
4
5
6
7
8
9
10
11
12
13
spec:
clusterIP: 10.0.0.64
ports:
- name: http
port: 80
protocol: TCP
targetPort: http
selector:
app: weave-scope
component: frontend
release: ui
sessionAffinity: None
type: NodePort # 将 Service 的类型更改为 NodePort
1
2
# 查看所有 Service,获取节点暴露的端口
kubectl get svc
1
2
3
NAME             TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 86d
ui-weave-scope NodePort 10.0.0.64 <none> 80:31764/TCP 6m4s
1
最后通过任意一个集群节点的 IP 与 Service 对外暴露的端口(比如 `http://192.168.2.191:31764`),就可以在 Kubernetes 集群外部通过浏览器访问 Weave 的 Web 控制台页面
  • 若希望卸载前面所安装的 Chart,可以执行以下命令
1
2
3
4
5
# 直接删除 Chart,默认不会删除关联的 PVC(数据卷)
helm uninstall ui

# 如果需要删除 Chart 关联的 PVC(数据卷),可以执行以下命令
kubectl delete pvc -l release=ui
自定义 Chart 配置信息

提示

本节将演示如何在安装 Chart 之前,自定义 Chart 的配置信息,目的是覆盖 Chart 的默认配置信息。

注意

  • 如果 helm 命令执行失败,并提示错误信息 Error: Kubernetes cluster unreachable,可以参考以下任意一种方案来解决:
  • (1) 尝试往 helm 命令的末尾添加参数 --kubeconfig=/opt/kubernetes/cfg/admin-user.kubeconfig
  • (2) 通过 export KUBECONFIG=/opt/kubernetes/cfg/admin-user.kubeconfig 命令添加对应的环境变量。

自定义 Chart 配置信息的原因在于,Chart 仓库中并非所有 Chart 都能在默认配置下成功运行,有时需要根据环境提供额外依赖,例如 PVC(数据卷)。因此,需要在安装 Chart 前自定义配置信息,主要有以下两种配置信息传递方式:

  • --values-f

    • 指定一个包含覆盖配置信息的 YAML 文件。
    • 可以指定多个 YAML 文件,右边的 YAML 文件优先级更高。
  • --set

    • 直接在命令行中指定覆盖配置信息。
    • 当同时使用 --values--set 时,--set 的优先级更高。
    • YAML 与 --set 配置格式的对比请看 这里

  • 查看指定 Chart 的默认配置信息
1
helm show values stable/mysql
  • 创建 YAML 配置文件,用于覆盖 Chart 的默认配置信息
1
vim mysql-server-config.yaml
1
2
3
4
5
persistence:
enabled: false # 关闭持久化存储
mysqlUser: "k8s" # 自定义 MySQL 用户名
mysqlPassword: "123456" # 自定义 MySQL 密码
mysqlDatabase: "k8s" # 自定义创建的数据库名称
  • 安装指定的 Chart,并覆盖默认配置
1
helm install mysql-server -f mysql-server-config.yaml stable/mysql
  • 查看所有 Pod 的运行状态
1
kubectl get pods
1
2
NAME                           READY   STATUS    RESTARTS   AGE
mysql-server-9c7558dc8-rb89z 0/1 Running 0 15s
  • 查看所有 Service
1
kubectl get svc
1
2
3
NAME           TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)    AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 86d
mysql-server ClusterIP 10.0.0.4 <none> 3306/TCP 88s
  • 验证 Chart 的安装
1
2
3
4
5
# 启动一个临时容器并连接进去,--rm 参数表示退出后会自动销毁容器
kubectl run -it mysql-client --rm --restart=Never --image=mysql:5.7 -- bash

# 在临时容器的内部登录 MySQL(可以通过 Service 的名称直接访问 MySQL Server,前提是在同一个命名空间,且安装了 CoreDNS)
mysql -hmysql-server -uk8s -p123456

Helm 构建自定义的 Chart

提示

本节将演示如何构建一个自己的 Chart(比如,用于部署 Nginx 的 Chart),并将其安装和打包。

三大核心构建步骤

Kubernetes 支持用户构建(开发)自己的 Chart,核心的构建步骤如下:

  • (1) 创建 Chart 基础模板

    • 使用 helm create <chart-name> 命令创建基础模板。
  • (2) 更改 Chart 配置文件

    • 编辑 Chart.yaml 文件,填写应用名称、版本、描述等信息。
    • 编辑 values.yaml 文件,添加常用变量和默认值,用于自定义配置。
  • (3) 创建 Chart 模板文件

    • 在自动生成的 templates 目录下,创建或编辑部署应用所需的 YAML 文件(如 Deployment、Service、Ingress 等)。
    • 在 YAML 文件中,可以使用变量引用经常变化的字段,支持从 values.yaml 文件中获取动态值,比如 replicas: {{ .Values.replicas }}
Chart 的构建安装

(1) 构建自定义的 Chart

  • 创建一个 Chart,自动生成 Chart 的模板文件(YAML 配置文件)
1
helm create nginx
  • 查看自动生成的目录结构
1
tree nginx/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
nginx/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│   └── test-connection.yaml
└── values.yaml
文件 / 目录名类型描述主要作用
charts/目录存放 Chart 依赖的所有子 Chart 管理当前 Chart 所依赖的其他 Chart,支持复杂的应用依赖关系
Chart.yaml文件描述 Chart 的基本信息定义 Chart 的名称、描述、版本、依赖关系等元数据
values.yaml文件存储模板文件中使用的变量值提供用户可配置的参数默认值,支持部署时的自定义配置
templates/目录存放所有 YAML 模板文件包含 Kubernetes 资源清单模板,如 Deployment、Service、ConfigMap 等
NOTES.txt文件介绍 Chart 的帮助信息helm install 部署后展示给用户,包含使用指南和默认设置说明
_helpers.tpl文件放置模板助手的地方定义可以在整个 Chart 中重复使用的模板片段或函数,提高模板代码的复用性和可维护性
  • 删除自动生成的 Chart 模板文件(可选步骤)
1
rm -rf nginx/templates/*
  • 编辑 Chart 的 Chart.yaml 文件,定义 Chart 的名称、描述、版本等信息
1
vim nginx/Chart.yaml
1
2
3
4
5
6
apiVersion: v2
name: nginx
description: A custom Helm chart for nginx application
type: application
version: 1.0.0
appVersion: 1.15
  • 创建或编辑 Chart 的模板文件 deployment.yaml,定义要创建的 Deployment
1
vim nginx/templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.15
ports:
- containerPort: 80
  • 创建或编辑 Chart 的模板文件 service.yaml,定义要创建的 Service
1
vim nginx/templates/service.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-pod
name: nginx-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-pod
type: NodePort

(2) 安装自定义的 Chart

  • 安装自定义的 Chart
1
2
# 这里的 web 是 Release 的名称
helm install web nginx/
1
2
3
4
5
6
NAME: web
LAST DEPLOYED: Wed Oct 13 21:10:20 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
  • 还可以将自定义的 Chart 打包成 .tgz 压缩包,共享给别人使用
1
helm package nginx/
1
nginx-1.0.0.tgz
  • 查看实际的 Chart 模板被渲染过后的 YAML 资源文件
1
2
# 这里的 web 是 Release 的名称
helm get manifest web
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
---
# Source: nginx/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
labels:
app: nginx-pod
name: nginx-svc
spec:
ports:
- port: 80
protocol: TCP
targetPort: 80
selector:
app: nginx-pod
type: NodePort
---
# Source: nginx/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deploy
spec:
replicas: 1
selector:
matchLabels:
app: nginx-pod
template:
metadata:
labels:
app: nginx-pod
spec:
containers:
- name: nginx
image: nginx:1.15
ports:
- containerPort: 80

(3) 验证自定义的 Chart

  • 查看发布(Release)的列表
1
helm list
1
2
NAME	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART      	APP VERSION
web default 1 2025-10-13 21:10:20.593922287 +0800 CST deployed nginx-1.0.0 1.15
  • 查看所有 Pod 的运行状态
1
kubectl get pods
1
2
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-85b7dd6b6d-2dswj 1/1 Running 0 104s
  • 查看所有 Service
1
kubectl get svc
1
2
3
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 86d
nginx-svc NodePort 10.0.0.150 <none> 80:32377/TCP 2m20s
1
最后通过任意一个集群节点的 IP 与 Service 对外暴露的端口(比如 `http://192.168.2.191:32377`),就可以在 Kubernetes 集群外部通过浏览器访问 Nginx 的首页面
Chart 的版本升级
  • 在 Chart 安装(发布)后,如果 Chart 的模板文件发生了变更,可以执行以下命令对已部署的应用进行升级
1
2
# 这里 web 是 Release 的名称
helm upgrade web nginx/
1
2
3
4
5
6
7
Release "web" has been upgraded. Happy Helming!
NAME: web
LAST DEPLOYED: Wed Oct 13 21:37:23 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
  • 或者使用 - 参数进行升级(指定包含覆盖配置信息的 YAML 文件)
1
2
# 这里 web 是 Release 的名称
helm upgrade -f values.yaml web nginx/
  • 或者使用 --set 参数进行升级(直接传入参数值)
1
2
# 这里 web 是 Release 的名称
helm upgrade --set imageTag=1.17 web nginx/
Chart 的版本回滚

提示

在 Chart 安装(发布)后,如果没有达到预期的效果,则可以使用 helm rollback 将 Release 回滚到之前的版本。

  • 查看 Release 的列表
1
helm list
1
2
NAME	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART      	APP VERSION
web default 1 2025-10-13 21:10:20.593922287 +0800 CST deployed nginx-1.0.0 1.15
  • 查看指定 Release 的历史版本
1
2
# 这里的 web 是 Release 的名称
helm history web
1
2
3
REVISION	UPDATED                 	STATUS    	CHART      	APP VERSION	DESCRIPTION     
1 Wed Oct 13 21:10:20 2025 superseded nginx-1.0.0 1.15 Install complete
2 Wed Oct 13 21:23:26 2025 deployed nginx-1.0.0 1.15 Upgrade complete
  • 将 Release 回滚到指定的历史版本
1
2
# 这里的 web 是 Release 的名称,1 是要 Release 回滚到的历史版本号
helm rollback web 1
  • 查看 Release 的版本是否成功回滚
1
2
# 这里的 web 是 Release 的名称
helm status web
1
2
3
4
5
6
NAME: web
LAST DEPLOYED: Wed Oct 13 21:31:56 2025
NAMESPACE: default
STATUS: deployed
REVISION: 3
TEST SUITE: None

推送 Chart 到仓库

对于自定义的 Chart,除了可以打包成 .tgz 压缩包,还可以将其推送到 Chart 仓库(如 Harbor、ChartMuseum 等),详细的推送步骤可以参考网上的资料,这里不再累述。

Helm 中 Chart 模板的使用

Chart 模板的简单介绍

Helm 的核心在于模板化的 Kubernetes Manifests 文件,这些模板本质上是基于 Go Template 的模板文件。在原生 Go 模板语法的基础上,Helm 还扩展了许多功能,例如:

  • 自定义的元数据定义(如 Chart.yaml
  • 内置函数库和模板函数
  • 类似编程语言的控制语句(如条件判断、循环、管道等)

这些扩展使模板具备了强大的灵活性和复用性。为了将用户的具体配置与模板结合,Helm 使用 values.yaml 文件来提供参数化的配置数据。

提示

模板文件与 values 文件的结合,这就是 Helm Chart 的核心机制 —— 通过模板化 + 参数化的方式,实现 Kubernetes 应用的灵活部署与管理。

Chart 模板的使用案例

(1) 构建自定义的 Chart

  • 创建一个 Chart,自动生成 Chart 的模板文件(YAML 配置文件)
1
helm create nginx
  • 查看自动生成的目录结构
1
tree nginx/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
nginx/
├── charts
├── Chart.yaml
├── templates
│   ├── deployment.yaml
│   ├── _helpers.tpl
│   ├── hpa.yaml
│   ├── ingress.yaml
│   ├── NOTES.txt
│   ├── serviceaccount.yaml
│   ├── service.yaml
│   └── tests
│   └── test-connection.yaml
└── values.yaml
文件 / 目录名类型描述主要作用
charts/目录存放 Chart 依赖的所有子 Chart 管理当前 Chart 所依赖的其他 Chart,支持复杂的应用依赖关系
Chart.yaml文件描述 Chart 的基本信息定义 Chart 的名称、描述、版本、依赖关系等元数据
values.yaml文件存储模板文件中使用的变量值提供用户可配置的参数默认值,支持部署时的自定义配置
templates/目录存放所有 YAML 模板文件包含 Kubernetes 资源清单模板,如 Deployment、Service、ConfigMap 等
NOTES.txt文件介绍 Chart 的帮助信息helm install 部署后展示给用户,包含使用指南和默认设置说明
_helpers.tpl文件放置模板助手的地方定义可以在整个 Chart 中重复使用的模板片段或函数,提高模板代码的复用性和可维护性
  • 删除自动生成的 Chart 模板文件(可选步骤)
1
rm -rf nginx/templates/*
  • 编辑 Chart 的 Chart.yaml 文件,定义 Chart 的名称、描述、版本等信息
1
vim nginx/Chart.yaml
1
2
3
4
5
6
apiVersion: v2
name: nginx
description: A Helm chart for Nginx
type: application
version: 0.1.0
appVersion: 1.15
  • 编辑 Chart 的 values.yaml 文件,定义全局的变量值
1
vim nginx/values.yaml
1
2
3
4
5
6
7
image: nginx
tag: 1.15
replicas: 3
serviceport: 80
targetport: 80
containerPort: 80
label: nginx-app
  • 创建或编辑 Chart 的模板文件 NOTES.txt,定义 Chart 的帮助信息(使用指南)
1
vim nginx/templates/NOTES.txt
1
2
Get service expose port: `kubectl get svc`
Access nginx by: `http://<node_ip>:<service_port>`
  • 创建或编辑 Chart 的模板文件 deployment.yaml,定义要创建的 Deployment
1
vim nginx/templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app: {{ .Values.label }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: {{ .Values.label }}
template:
metadata:
labels:
app: {{ .Values.label }}
spec:
containers:
- name: web
image: {{ .Values.image }}:{{ .Values.tag }}
ports:
- containerPort: {{ .Values.containerPort }}
  • 创建或编辑 Chart 的模板文件 service.yaml,定义要创建的 Service
1
vim nginx/templates/service.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: v1
kind: Service
metadata:
name: {{ .Release.Name }}
labels:
app: {{ .Values.label }}
spec:
type: NodePort
selector:
app: {{ .Values.label }}
ports:
- port: {{ .Values.serviceport }}
targetPort: {{ .Values.targetport }}
protocol: TCP

(2) 安装自定义的 Chart

  • 安装自定义的 Chart
1
2
# 这里的 web 是 Release 的名称
helm install web nginx/
1
2
3
4
5
6
7
8
9
NAME: web
LAST DEPLOYED: Wed Oct 13 17:39:32 2025
NAMESPACE: default
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
Get service expose port: `kubectl get svc`
Access nginx by: `http://<node_ip>:<service_port>`
  • 查看实际的 Chart 模板被渲染过后的 YAML 资源文件
1
2
# 这里的 web 是 Release 的名称
helm get manifest web
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
---
# Source: nginx/templates/service.yaml
apiVersion: v1
kind: Service
metadata:
name: web
labels:
app: nginx-app
spec:
type: NodePort
selector:
app: nginx-app
ports:
- port: 80
targetPort: 80
protocol: TCP
---
# Source: nginx/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80

(3) 验证自定义的 Chart

  • 查看发布(Release)的列表
1
helm list
1
2
NAME	NAMESPACE	REVISION	UPDATED                                	STATUS  	CHART      	APP VERSION
web default 1 2025-10-29 17:39:32.267654796 +0800 CST deployed nginx-0.1.0 1.15
  • 查看所有 Pod 的运行状态
1
kubectl get pods
1
2
3
4
NAME                   READY   STATUS    RESTARTS   AGE
web-766795cc8b-6knwm 1/1 Running 0 100s
web-766795cc8b-7nlr4 1/1 Running 0 100s
web-766795cc8b-q4h8q 1/1 Running 0 100s
  • 查看所有 Service
1
kubectl get svc
1
2
3
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes ClusterIP 10.0.0.1 <none> 443/TCP 86d
web NodePort 10.0.0.197 <none> 80:30654/TCP 2m13s
1
最后通过任意一个集群节点的 IP 与 Service 对外暴露的端口(比如 `http://192.168.2.191:30654`),就可以在 Kubernetes 集群外部通过浏览器访问 Nginx 的首页面
Chart 模板的调试技巧
  • Helm 提供了 --dry-run--debug 调试参数,可用于在执行 helm install 命令之前,验证 Chart 模板文件的正确性。
  • helm install 命令加上这两个参数后,Helm 会将模板文件与对应的 values.yaml 文件进行渲染,并打印出生成的 YAML 资源清单,而不会实际部署任何 Release。
  • 比如,调试 上面案例 中自定义的 Chart 包,可以使用以下命令:
1
2
# 这里的 web 是 Release 的名称
helm install web --dry-run nginx/
Chart 模板的内置对象

上面使用 {{.Release.Name}} 将 Release 的名称插入到 Chart 模板中。这里的 Release 就是 Helm 的内置对象,下面是一些常用的内置对象:

Helm 内置对象描述
Release.NameRelease 名称
Release.NamespaceRelease 命名空间
Release.ServiceRelease 服务的名称
Release.RevisionRelease 修订版本号,从 1 开始累加
Chart 模板的 Values 对象

Values 对象用于为 Chart 模板文件提供参数值,其来源主要有以下四个:

  • (1) Chart 包中的 values.yaml 文件
  • (2) 父 Chart 包中的 values.yaml 文件
  • (3) 通过 helm installhelm upgrade 命令使用 -f--values 参数传入的自定义 YAML 配置文件
  • (4) 通过 helm installhelm upgrade 命令使用 --set 参数直接传入的值

参数值不同来源的优先级关系

Chart 参数值的优先级遵循一定的覆盖顺序(优先级):Chart 包中的 values.yaml 文件 < 用户通过 -f 参数自定义的 YAML 配置文件 < 用户通过 --set 参数传入的值

  • 举个例子,通过 --set 参数更新 Chart(比如,Pod 的副本数量)
1
2
# 这里的 web 是 Release 的名称
helm upgrade web --set replicas=5 nginx/
1
2
3
4
5
6
7
8
9
10
Release "web" has been upgraded. Happy Helming!
NAME: web
LAST DEPLOYED: Wed Oct 13 18:04:34 2025
NAMESPACE: default
STATUS: deployed
REVISION: 2
TEST SUITE: None
NOTES:
Get service expose port: `kubectl get svc`
Access nginx by: `http://<node_ip>:<service_port>`
  • 查看指定 Release 的历史版本
1
2
# 这里的 web 是 Release 的名称
helm history web
1
2
3
REVISION	UPDATED                 	STATUS    	CHART      	APP VERSION	DESCRIPTION     
1 Wed Oct 13 17:39:32 2025 superseded nginx-0.1.0 1.15 Install complete
2 Wed Oct 13 18:04:34 2025 deployed nginx-0.1.0 1.15 Upgrade complete
  • 查看所有 Pod 的运行状态
1
kubectl get pods
1
2
3
4
5
6
NAME                   READY   STATUS    RESTARTS   AGE
web-766795cc8b-6knwm 1/1 Running 0 28m
web-766795cc8b-7nlr4 1/1 Running 0 28m
web-766795cc8b-lpr27 1/1 Running 0 3m57s
web-766795cc8b-q4h8q 1/1 Running 0 28m
web-766795cc8b-vpdh4 1/1 Running 0 3m57s
Chart 模板的函数与管道

模板函数与管道的简单介绍

前面讲的内容,其实就是将参数值传给 Go 模板引擎进行渲染,模板引擎还支持通过模板函数和管道对拿到数据(参数值)进行二次处理。Helm 支持的模板函数和管道如下所示:

  • 默认值处理

    • default
      • 为不存在或空的值提供默认值
      • 调用语法:{{ .Values.name | default "nginx" }}
  • 大小写转换

    • upper
      • 将字符串转换为大写
      • 调用语法:{{ upper .Values.resources }}
    • lower
      • 将字符串转换为小写
      • 调用语法:{{ lower .Values.resources }}
    • title
      • 将首字母大写
      • 调用语法:{{ title .Values.resources }}
  • 布尔、数字、长度

    • bool
      • 将值转换为布尔
      • 调用语法:{{ bool .Values.featureFlag }}
    • int
      • 将值转换为整数
      • 调用语法:{{ int .Values.replicaCount }}
    • float
      • 将值转换为浮点数
      • 调用语法:{{ float .Values.cpus }}
    • len
      • 获取列表(数组)、字典或字符串的长度
      • 调用语法:{{ len .Values.env }}
  • 字符串转换、拼接与替换

    • quote
      • 将参数值转换为带双引号的字符串
      • 调用语法:{{ quote .Values.label }}
    • cat
      • 拼接多个字符串
      • 调用语法:{{ cat .Release.Name "-" .Chart.Name }}
    • replace
      • 替换字符串
      • 调用语法:{{ .Values.name | replace "_" "-" }}
    • trim
      • 去除字符串首尾空格
      • 调用语法:{{ .Values.name | trim " " }}
    • trimAll
      • 去除指定字符
      • 调用语法:{{ .Values.name | trimAll "-" }}
  • 加空格与缩进

    • indent
      • 每行前加指定空格数
      • 调用语法:{{ .Values.resources | indent 10 }}
    • nindent
      • 每行缩进并加换行
      • 调用语法:{{ .Values.resources | nindent 10 }}
  • 对象转换

    • toYaml
      • 将对象转换为 YAML
      • 调用语法:{{ .Values.resources | toYaml }}
    • toJson
      • 将对象转换为 JSON
      • 调用语法:{{ .Values.config | toJson | quote }}
  • 条件 / 验证

    • hasKey
      • 判断字典中是否存在某个键
      • 调用语法:{{- if hasKey .Values.env "JAVA_HOME" }}
    • required
      • 必填参数验证,参数不存在时报错
      • 调用语法:{{ required "image.repository is required" .Values.image.repository }}

模板函数 quote 的使用案例

  • 上面案例 的基础上,通过模板函数 quote 将从 .Values 中读取到的参数值转换成字符串
1
vim nginx/templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}
labels:
app: {{ quote .Values.label }}
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: {{ quote .Values.label }}
template:
metadata:
labels:
app: {{ quote .Values.label }}
spec:
containers:
- name: web
image: {{ .Values.image }}:{{ .Values.tag }}
ports:
- containerPort: {{ .Values.containerPort }}
  • 将模板文件与对应的 values.yaml 文件进行渲染,并打印出生成的 YAML 资源清单,不会实际部署任何 Release
1
2
# 这里的 web 是 Release 的名称
helm install web --dry-run nginx/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
...(省略)

apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: "nginx-app" # 参数值已经被 quote 模板函数转换为字符串
spec:
replicas: 3
selector:
matchLabels:
app: "nginx-app"
template:
metadata:
labels:
app: "nginx-app"
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
Chart 模板的流程控制语句

流程控制是为 Chart 模板提供了一种能力,满足更复杂的数据逻辑处理。Helm 模板语言提供以下流程控制语句:

  • if/else:条件块
  • with:指定范围
  • range:循环块
if/else

if/else 的简单介绍

  • if/else 块是用于在模板中有条件地包含文本块的方法,条件块的基本结构如下:
1
2
3
4
5
6
7
{{ if PIPELINE }}
# Do something
{{ elseif OTHER PIPELINE }}
# Do something else
{{ else }}
# Default case
{{ end }}
  • 条件判断支持使用 eq 运算符来判断是否相等,除此之外,还支持 neltgtandor 等运算符,请注意数据类型。
  • 条件判断就是判断条件是否为 true,如果值为以下几种情况之一则为 false
    • 一个布尔类型的 false
    • 一个数字零
    • 一个空的字符串
    • 一个空的集合(mapslicetupledictarray
  • 除了上面的这些情况外,其他所有条件都为 true

if/else 的使用案例一,演示如何使用基本的条件判断

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
devops: k8s
  • 在 Chart 包中,deployment.yaml 文件的内容如下
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx
{{ if eq .Values.devops "k8s" }}
devops: true
{{ else }}
devops: false
{{ end }}
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
  • 通过模板引擎渲染后,会得到如下结果
1
2
# 这里的 web 是 Release 的名称
helm install web --dry-run nginx/
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx

devops: true

spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
  • 可以看到渲染出来结果会有多余的空行,这是因为当模板引擎渲染时,会将控制指令删除掉,所以之前占的位置也就空白了,需要使用 {{- if ... }} 的方式来消除空行
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx
{{- if eq .Values.devops "k8s" }}
devops: true
{{- else }}
devops: false
{{- end }}
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
  • 如果使用 -}} 需谨慎,比如在上面的模板文件中:
1
2
3
4
5
6
...(省略)

env:
{{- if eq .Values.devops "k8s" -}}
- devops: true
{{- end }}
  • 最终会渲染成下面这样子,因为 -}} 它会删除双方的换行符,导致模板文件渲染失败
1
env:- devops: true

if/else 的使用案例二,演示如何判断一个数组是否为空

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
2
3
4
5
6
7
resources: {}
# limits:
# cpu: "100m"
# memory: "128Mi"
# requests:
# cpu: "100m"
# memory: "128Mi"
  • 在 Chart 包中,deployment.yaml 文件的内容如下
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1
kind: Deployment
metadata:
name: web
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.16
{{- if .Values.resources }}
resources:
{{ toYaml .Values.resources | indent 12 }}
{{- end }}

if/else 的使用案例三,演示如何判断一个布尔值是否为 true

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
2
3
4
5
6
service:
type: ClusterIP
port: 80
ingress:
enabled: true
host: example.ingress.com
  • 在 Chart 包中,ingress.yaml 文件的内容如下
1
cat templates/ingress.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ .Release.Name }}-ingress
spec:
rules:
- host: {{ .Values.ingress.host }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ .Release.Name }}
port:
number: {{ .Values.service.port }}
{{- end }}
range

在 Helm 模板语言中,可以使用 range 语句来进行循环操作。

range 的使用案例,演示如何通过 range 读取一个数组的所有元素值

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
2
3
4
list:
- 1
- 2
- 3
  • 在 Chart 包中,deployment.yaml 文件的内容如下
1
cat templates/deployment.yaml
  • 在 Chart 包中,deployment.yaml 文件的内容如下(在循环内部使用的是一个 . 符号,这是因为当前的作用域就在当前循环内,这个 . 符号用于表示当前读取到的元素)
1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: ConfigMap
metadata:
name: {{ .Release.Name }}
data:
list: |
{{- range .Values.list }}
{{ . }}
{{- end }}
  • 通过模板引擎渲染后,会得到如下结果
1
2
3
4
5
6
7
8
9
apiVersion: v1
kind: ConfigMap
metadata:
name: web
data:
list: |
1
2
3
with

with 的简单介绍

  • with 语句就可以用来控制变量的作用域范围。
  • with 的使用语法和一个简单的 if 语句比较类似:
1
2
3
{{ with PIPELINE }}
# restricted scope
{{ end }}
  • 值得注意的是,在 with 语句块内不能使用内置对象(比如 .Release.Name),否则模板渲染会失败,可以将内置对象赋值给一个变量来解决该问题。
  • with 语句可以允许将当前范围 . 设置为特定的对象,比如前面一直使用的 .Values.label,就是使用 with 语句来将当前范围 . 指向 .Values.label
  • 还记得之前的 {{ .Release.xxx }} 或者 {{ .Values.xxx }} 吗?其中的 . 符号就是表示对当前范围的引用,.Values 就是告诉模板引擎在当前范围中查找 Values 对象的值。

with 的使用案例,演示如何使用 with 来控制变量作用域

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
2
3
nodeSelector:
team: python
gpu: yes
  • 在 Chart 包中,deployment.yaml 文件的内容如下
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
team: {{ .team }}
gpu: {{ .gpu }}
{{- end }}
containers:
- name: nginx
image: nginx:1.16
  • 通过模板引擎渲染后,会得到如下结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
nodeSelector:
team: python
gpu: true
containers:
- name: nginx
image: nginx:1.16
  • 上面的配置内容还可以继续优化一下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deployment
spec:
replicas: 1
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
{{- with .Values.nodeSelector }}
nodeSelector:
{{ toYaml . | nindent 8 }}
{{- end }}
containers:
- name: nginx
image: nginx:1.16
Chart 模板的变量

在 Chart 模板中,使用变量的场景不多,但下面将看到如何使用变量来简化模板代码,并更好地使用 withrange 语句。

变量的使用案例一,演示如何通过变量获取数组的键值

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
2
3
env:
NAME: "gateway"
JAVA_OPTS: "-Xmx2G"
  • 在 Chart 包中,deployment.yaml 文件的内容如下(在 range 循环中,使用 $k$v 这两个变量来接收后面数组循环的键和值)
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway-deploy
labels:
app: gateway-app
spec:
replicas: 3
selector:
matchLabels:
app: gateway-app
template:
metadata:
labels:
app: gateway-app
spec:
containers:
- name: gateway
image: gateway:2.13
env:
{{- range $k, $v := .Values.env }}
- name: {{ $k }}
value: {{ $v | quote }}
{{- end }}
  • 通过模板引擎渲染后,会得到如下结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
apiVersion: apps/v1
kind: Deployment
metadata:
name: gateway-deploy
labels:
app: gateway-app
spec:
replicas: 3
selector:
matchLabels:
app: gateway-app
template:
metadata:
labels:
app: gateway-app
spec:
containers:
- name: gateway
image: gateway:2.13
env:
- name: NAME
value: "gateway"
- name: JAVA_OPTS
value: "-Xmx2G"

变量的使用案例二,演示如何解决在 with 语句块中不能使用内置对象的问题

  • 在 Chart 包中,values.yaml 文件的内容如下
1
cat values.yaml
1
2
3
4
5
replicas: 3

label:
project: my-project
app: nginx
  • 在 Chart 包中,deployment.yaml 文件的内容如下(模板文件渲染会报错,因为在 with 语句块内不能再使用内置对象,比如 .Release.Name
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deploy
spec:
replicas: {{ .Values.replicas }}
template:
metadata:
labels:
{{- with .Values.label }}
project: {{ .project }}
app: {{ .app }}
release: {{ .Release.Name }}
{{- end }}
  • 上面的模板内容会渲染失败,但可以将内置对象赋值给一个变量来解决该问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-deploy
spec:
replicas: {{ .Values.replicas }}
selector:
matchLabels:
app: {{ .Values.label.app }}
template:
metadata:
labels:
{{- $releaseName := .Release.Name -}}
{{- with .Values.label }}
project: {{ .project }}
app: {{ .app }}
release: {{ $releaseName }}
{{- end }}
  • 通过模板引擎渲染后,会得到如下结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
apiVersion: apps/v1
kind: Deployment
metadata:
name: web-deploy
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
project: my-project
app: nginx
release: web
Chart 模板的命名模板

命名模板的简单介绍

  • 命名模板

    • 用于在 Chart 中复用模板代码片段。
    • 使用 {{- define "templateName" }} ... {{- end }} 定义模板。
    • 使用 {{ template "templateName" . }} 引用模板,并传递上下文 .
  • 公共模板文件

    • Helm 中,templates 目录下以下划线 _ 开头的文件(如 _helpers.tpl)都会被视作公共模板文件。
    • 这些公共模板文件不会直接渲染成 Kubernetes 对象,而是用于存放命名模板或函数,供其他模板使用。
  • 使用注意事项

    • template 函数不能用于 Go 模板的管道,可以使用 include 语句来解决该问题。

命名模板的使用案例一,演示命名模板的基础使用

  • 在 Chart 包中,_helpers.tpl 文件的内容如下
1
cat templates/_helpers.tpl
1
2
3
{{- define "demo.fullname" -}}
{{- .Chart.Name -}}-{{ .Release.Name }}
{{- end -}}
  • 在 Chart 包中,deployment.yaml 文件的内容如下
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "demo.fullname" . }}
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
  • 通过模板引擎渲染后,会得到如下结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web
labels:
app: nginx-app
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80

命名模板的使用案例二,演示如何解决 template 函数不能用于 Go 模板的管道的问题

  • 在 Chart 包中,_helpers.tpl 文件的内容如下
1
cat templates/_helpers.tpl
1
2
3
4
5
6
7
8
9
{{- define "demo.fullname" -}}
{{- .Chart.Name -}}-{{ .Release.Name }}
{{- end -}}

{{- define "demo.labels" -}}
app: {{ template "demo.fullname" . }}
chart: "{{ .Chart.Name }}-{{ .Chart.Version }}"
release: "{{ .Release.Name }}"
{{- end -}}
  • 在 Chart 包中,deployment.yaml 文件的内容如下(模板文件渲染会报错,因为 template 函数不能用于 Go 模板的管道)
1
cat templates/deployment.yaml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ template "demo.fullname" . }}
labels:
{{- template "demo.labels" . | nindent 4 }}
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
  • 上面的模板内容会渲染失败,但可以使用 include 语句来解决该问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "demo.fullname" . }}
labels:
{{- include "demo.labels" . | nindent 4 }}
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80
  • 通过模板引擎渲染后,会得到如下结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-web
labels:
app: nginx-web
chart: "nginx-0.1.0"
release: "web"
spec:
replicas: 3
selector:
matchLabels:
app: nginx-app
template:
metadata:
labels:
app: nginx-app
spec:
containers:
- name: web
image: nginx:1.15
ports:
- containerPort: 80