Helm 包管理
Helm 是 Kubernetes 的包管理工具,被誉为"Kubernetes 的 apt/yum"。它将一组相关的 Kubernetes 资源打包成一个可重用的单元(称为 Chart),让复杂应用的部署变得像安装软件包一样简单。本教程将带你从零开始掌握 Helm 的使用和开发。
为什么需要 Helm?
在深入学习 Helm 之前,我们先看看直接使用 kubectl 管理应用会遇到哪些问题。
手动管理的痛点
假设你要部署一个典型的 Web 应用,通常需要创建以下资源:
- Deployment:管理应用 Pod
- Service:暴露服务
- ConfigMap:存储配置
- Secret:存储敏感信息
- Ingress:配置外部访问
- HorizontalPodAutoscaler:自动扩缩容
每个资源都是一个 YAML 文件,你需要逐个应用它们。当需要升级时,又要逐个更新。如果有多套环境(开发、测试、生产),配置又有细微差异,就需要维护多套几乎相同的 YAML 文件。
更麻烦的是,这些资源之间存在依赖关系。比如 Deployment 依赖 ConfigMap,ConfigMap 更新后 Deployment 需要重启才能生效。手动管理这些关系非常繁琐且容易出错。
Helm 如何解决问题
Helm 引入了"包"的概念,把一组相关的 Kubernetes 资源打包成一个 Chart。你可以:
- 一键安装:一条命令部署整个应用栈
- 版本管理:跟踪每次部署的版本,支持回滚
- 配置复用:通过参数化配置,一个 Chart 部署到多个环境
- 依赖管理:自动处理应用间的依赖关系
打个比方,如果 kubectl 是手动拼装电脑的螺丝刀,那么 Helm 就是一键安装软件的软件中心。
核心概念
Helm 有三个核心概念,理解它们是掌握 Helm 的基础。
Chart(图表)
Chart 是 Helm 的打包格式,包含了一组 Kubernetes 资源定义。可以把 Chart 理解为软件安装包,比如一个 WordPress Chart 包含了部署 WordPress 所需的所有资源:Deployment、Service、ConfigMap、Secret 等。
Chart 是可参数化的。同一个 Chart 通过不同的配置值,可以部署出不同实例。比如用同一个 WordPress Chart,通过不同的域名和数据库配置,部署多个 WordPress 站点。
Release(发布)
Release 是 Chart 的一次安装实例。每次使用 helm install 安装 Chart,就会创建一个新的 Release。同一个 Chart 可以安装多次,每次都是独立的 Release。
Release 这个名字可能有点迷惑,它更像是"部署实例"。比如你用 WordPress Chart 安装了两个站点,就有两个 Release:wordpress-dev 和 wordpress-prod。
Repository(仓库)
Repository 是存放 Chart 的地方,类似 apt 的软件源或 Docker 的镜像仓库。你可以从公共仓库下载 Chart,也可以搭建私有仓库存储内部应用的 Chart。
安装 Helm
各平台安装方法
macOS(使用 Homebrew)
brew install helm
Windows(使用 Chocolatey 或 Scoop)
# 使用 Chocolatey
choco install kubernetes-helm
# 使用 Scoop
scoop install helm
Linux
# 使用官方脚本
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# 或使用 apt(Debian/Ubuntu)
curl https://baltocdn.com/helm/signing.asc | sudo apt-key add -
sudo apt-get install apt-transport-https --yes
echo "deb https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm
验证安装
helm version
输出类似:
version.BuildInfo{Version:"v3.13.0", GitCommit:"...", GitTreeState:"clean", GoVersion:"go1.20.8"}
配置自动补全
# Bash
source <(helm completion bash)
echo "source <(helm completion bash)" >> ~/.bashrc
# Zsh
source <(helm completion zsh)
echo "source <(helm completion zsh)" >> ~/.zshrc
# Fish
helm completion fish | source
基本使用
添加仓库
Helm 默认没有配置任何仓库,需要手动添加。常用的公共仓库有:
# 添加 Bitnami 仓库(包含大量高质量 Chart)
helm repo add bitnami https://charts.bitnami.com/bitnami
# 添加官方稳定仓库
helm repo add stable https://charts.helm.sh/stable
# 添加 incubator 仓库(实验性 Chart)
helm repo add incubator https://charts.helm.sh/incubator
# 更新仓库索引
helm repo update
# 查看已添加的仓库
helm repo list
搜索 Chart
# 在已添加的仓库中搜索
helm search repo bitnami
# 搜索特定应用
helm search repo wordpress
# 搜索 Artifact Hub(公共 Chart 目录)
helm search hub wordpress
查看 Chart 信息
# 查看 Chart 基本信息
helm show chart bitnami/wordpress
# 查看完整 README
helm show readme bitnami/wordpress
# 查看默认配置值
helm show values bitnami/wordpress
# 查看所有信息
helm show all bitnami/wordpress
安装 Chart
# 基本安装(自动生成 Release 名称)
helm install bitnami/wordpress --generate-name
# 指定 Release 名称
helm install my-wordpress bitnami/wordpress
# 指定命名空间
helm install my-wordpress bitnami/wordpress -n web-apps
# 使用自定义配置值
helm install my-wordpress bitnami/wordpress -f values.yaml
# 通过命令行设置值
helm install my-wordpress bitnami/wordpress \
--set wordpressUsername=admin \
--set wordpressPassword=secret \
--set service.type=NodePort
# 混合使用文件和命令行
helm install my-wordpress bitnami/wordpress \
-f values.yaml \
--set replicaCount=3
查看已安装的 Release
# 列出所有 Release
helm list
# 列出所有命名空间的 Release
helm list -A
# 查看特定 Release 详情
helm status my-wordpress
# 查看 Release 的历史版本
helm history my-wordpress
升级 Release
# 升级到新版本
helm upgrade my-wordpress bitnami/wordpress
# 升级并更新配置
helm upgrade my-wordpress bitnami/wordpress \
--set replicaCount=5
# 升级时如果 Release 不存在则安装
helm upgrade --install my-wordpress bitnami/wordpress
回滚 Release
# 回滚到上一个版本
helm rollback my-wordpress
# 回滚到指定版本
helm rollback my-wordpress 2
卸载 Release
# 卸载 Release
helm uninstall my-wordpress
# 卸载但保留历史记录
helm uninstall my-wordpress --keep-history
Chart 结构详解
了解 Chart 的目录结构,是开发自定义 Chart 的基础。一个典型的 Chart 结构如下:
mychart/
├── Chart.yaml # Chart 元数据(必需)
├── values.yaml # 默认配置值(必需)
├── charts/ # 依赖的子 Chart
├── templates/ # Kubernetes 资源模板
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ ├── _helpers.tpl # 模板助手函数
│ └── NOTES.txt # 安装后显示的提示信息
├── .helmignore # 打包时忽略的文件
├── LICENSE # 许可证
├── README.md # 说明文档
└── values.schema.json # 值的 JSON Schema 验证
Chart.yaml 详解
Chart.yaml 是 Chart 的核心配置文件,包含 Chart 的元数据:
apiVersion: v2 # Chart API 版本(Helm 3 使用 v2)
name: mychart # Chart 名称(必需)
version: 1.0.0 # Chart 版本(必需,遵循 SemVer)
kubeVersion: ">= 1.20.0" # 兼容的 Kubernetes 版本
description: A Helm chart for my application
type: application # application 或 library
keywords:
- web
- frontend
home: https://example.com
sources:
- https://github.com/example/mychart
maintainers:
- name: John Doe
email: [email protected]
url: https://example.com
icon: https://example.com/icon.png
appVersion: "2.0.0" # 应用版本(与 Chart 版本不同)
deprecated: false # 是否已废弃
annotations:
artifacthub.io/license: Apache-2.0
版本说明:
version:Chart 本身的版本,每次修改 Chart 都应该增加appVersion:Chart 包含的应用版本,比如 nginx:1.25 中的 1.25
values.yaml 详解
values.yaml 定义了 Chart 的默认配置值,这些值可以在安装时被覆盖:
# 副本数
replicaCount: 3
# 镜像配置
image:
repository: nginx
tag: "1.25"
pullPolicy: IfNotPresent
# 服务配置
service:
type: ClusterIP
port: 80
# 资源限制
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
# 环境变量
env:
- name: APP_ENV
value: production
# 亲和性配置
nodeSelector: {}
tolerations: []
affinity: {}
模板语法
Helm 使用 Go 模板语言编写 Kubernetes 资源模板。以下是一个 Deployment 模板示例:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "mychart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
模板语法要点:
| 语法 | 说明 | 示例 |
|---|---|---|
{{ .Values.key }} | 访问 values.yaml 中的值 | {{ .Values.replicaCount }} |
{{ .Chart.key }} | 访问 Chart.yaml 中的值 | {{ .Chart.Name }} |
{{ .Release.Name }} | 访问 Release 信息 | {{ .Release.Name }} |
{{- ... -}} | 去除空白 | {{- include "mychart.labels" . -}} |
| | 管道操作 | {{ .Values.resources | toYaml }} |
nindent N | 缩进 N 空格并换行 | | nindent 4 |
预定义值
Helm 在模板中提供了一些预定义的对象:
# Release 对象
{{ .Release.Name }} # Release 名称
{{ .Release.Namespace }} # 命名空间
{{ .Release.Service }} # 执行发布的服务
{{ .Release.IsUpgrade }} # 是否是升级操作
{{ .Release.IsInstall }} # 是否是安装操作
# Chart 对象
{{ .Chart.Name }} # Chart 名称
{{ .Chart.Version }} # Chart 版本
{{ .Chart.AppVersion }} # 应用版本
# Values 对象
{{ .Values.replicaCount }} # values.yaml 中的值
# Files 对象
{{ .Files.Get "config.ini" }} # 读取文件内容
# Capabilities 对象
{{ .Capabilities.KubeVersion }} # Kubernetes 版本
_helpers.tpl 文件
_helpers.tpl 文件用于定义可重用的模板片段,以 _ 开头的文件不会被渲染成 Kubernetes 资源:
{{/*
Expand the name of the chart.
*/}}
{{- define "mychart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "mychart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Create chart name and version as used by the chart label.
*/}}
{{- define "mychart.chart" -}}
{{- printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Common labels
*/}}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ include "mychart.chart" . }}
{{ include "mychart.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
使用定义好的模板:
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
创建自定义 Chart
使用命令创建骨架
helm create mychart
这会创建一个完整的 Chart 目录结构,包含常用的模板文件。
编写模板
让我们创建一个简单的 Nginx Chart 作为示例。
values.yaml:
replicaCount: 1
image:
repository: nginx
pullPolicy: IfNotPresent
tag: "1.25"
service:
type: ClusterIP
port: 80
ingress:
enabled: false
className: ""
hosts:
- host: chart-example.local
paths:
- path: /
pathType: ImplementationSpecific
resources: {}
templates/deployment.yaml:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "mychart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.port }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
templates/service.yaml:
apiVersion: v1
kind: Service
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
type: {{ .Values.service.type }}
ports:
- port: {{ .Values.service.port }}
targetPort: http
protocol: TCP
name: http
selector:
{{- include "mychart.selectorLabels" . | nindent 4 }}
验证和调试
# 验证 Chart 语法
helm lint mychart
# 渲染模板查看输出(不安装)
helm template myrelease mychart
# 使用自定义值渲染
helm template myrelease mychart -f custom-values.yaml
# 使用 --dry-run 模拟安装
helm install myrelease mychart --dry-run --debug
打包和分发
# 打包 Chart
helm package mychart
# 这会生成 mychart-1.0.0.tgz 文件
# 本地安装打包好的 Chart
helm install myrelease mychart-1.0.0.tgz
依赖管理
复杂应用通常依赖其他服务。比如 WordPress 依赖 MySQL,可以使用 Chart 依赖来管理这种关系。
定义依赖
在 Chart.yaml 中定义依赖:
apiVersion: v2
name: myapp
version: 1.0.0
dependencies:
- name: mysql
version: "9.x.x"
repository: https://charts.bitnami.com/bitnami
condition: mysql.enabled
- name: redis
version: "17.x.x"
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled
tags:
- cache
更新依赖
# 下载依赖到 charts/ 目录
helm dependency update myapp
# 查看依赖状态
helm dependency list myapp
条件启用依赖
在 values.yaml 中控制依赖是否启用:
mysql:
enabled: true
auth:
rootPassword: secret
database: myapp
redis:
enabled: false
子 Chart 配置
子 Chart 的配置通过父 Chart 的 values.yaml 进行:
# 父 Chart 自己的配置
replicaCount: 3
# 子 Chart mysql 的配置
mysql:
enabled: true
auth:
rootPassword: secret
database: myapp
# 子 Chart redis 的配置
redis:
enabled: true
auth:
password: redis-secret
最佳实践
1. 版本控制
将 Chart 纳入 Git 版本控制,每次修改更新 version 字段。
2. 值的文档化
在 values.yaml 中添加注释说明每个配置项:
# 副本数,生产环境建议设置为 3 或更高
replicaCount: 1
# 镜像配置
image:
repository: nginx
# 镜像标签,建议使用具体版本而非 latest
tag: "1.25"
# 拉取策略:Always, Never, IfNotPresent
pullPolicy: IfNotPresent
3. 使用 values.schema.json 验证
创建 JSON Schema 文件验证用户输入:
{
"$schema": "https://json-schema.org/draft-07/schema#",
"type": "object",
"properties": {
"replicaCount": {
"type": "integer",
"minimum": 1,
"maximum": 100,
"description": "Number of replicas"
},
"service": {
"type": "object",
"properties": {
"type": {
"type": "string",
"enum": ["ClusterIP", "NodePort", "LoadBalancer"]
}
}
}
}
}
4. 使用 --dry-run 验证
在安装或升级前,始终使用 --dry-run 检查:
helm upgrade --install myrelease mychart --dry-run --debug
5. 合理使用标签
使用标准的 Kubernetes 标签:
labels:
app.kubernetes.io/name: myapp
app.kubernetes.io/instance: myrelease
app.kubernetes.io/version: "1.0.0"
app.kubernetes.io/component: frontend
app.kubernetes.io/part-of: myproject
app.kubernetes.io/managed-by: Helm
6. 避免硬编码
不要在模板中硬编码值,全部通过 values.yaml 配置:
# 不好
image: nginx:1.25
# 好
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
常用命令速查
| 命令 | 说明 |
|---|---|
helm repo add <name> <url> | 添加仓库 |
helm repo update | 更新仓库索引 |
helm search repo <keyword> | 搜索 Chart |
helm show values <chart> | 查看默认值 |
helm install <release> <chart> | 安装 Chart |
helm upgrade <release> <chart> | 升级 Release |
helm rollback <release> [revision] | 回滚 Release |
helm uninstall <release> | 卸载 Release |
helm list | 列出所有 Release |
helm history <release> | 查看历史版本 |
helm lint <chart> | 验证 Chart |
helm template <release> <chart> | 渲染模板 |
helm package <chart> | 打包 Chart |
helm dependency update <chart> | 更新依赖 |
小结
本章我们学习了:
- Helm 概念:Chart、Release、Repository
- 基本使用:安装、升级、回滚、卸载
- Chart 结构:目录结构和文件说明
- 模板语法:Go 模板和预定义值
- 依赖管理:管理 Chart 间的依赖关系
- 最佳实践:版本控制、文档化、验证
Helm 大大简化了 Kubernetes 应用的部署和管理,是云原生应用交付的标配工具。
练习
- 安装 Helm 并添加 Bitnami 仓库
- 使用 Helm 部署一个 WordPress 应用
- 创建一个自定义 Chart 并部署
- 练习升级和回滚操作
- 添加一个依赖(如 Redis)到你的 Chart
参考资料
- Helm 官方文档
- Helm Chart 模板指南
- Artifact Hub - 公共 Chart 目录
- Bitnami Charts