Helm 详解:Kubernetes 应用包管理与部署
概念说明Chart应用打包格式,含模板与默认配置ReleaseChart 的安装实例Values配置参数,支持多环境覆盖Hooks生命周期钩子fill:#333;important;important;fill:none;color:#333;color:#333;important;fill:none;fill:#333;height:1em;Helm 核心能力一键部署多环境配置版本管理与回滚依
摘要:Helm 是 Kubernetes 的包管理工具,提供 Chart 打包、依赖管理、版本控制和一键部署能力。本文详解 Chart 目录结构、Go 模板语法、依赖管理、Helm Hooks、Chart 开发最佳实践、CI/CD 集成及生产 FAQ。
一、为什么需要 Helm?
在 Kubernetes 原生方式下,部署一个完整应用需要维护多个独立的 YAML 清单文件,存在文件分散、环境差异管理困难、版本追溯和回滚复杂等问题。Helm 通过 Chart 封装和 Values 参数化,将多资源管理统一为单次操作。
二、Helm 核心概念
| 概念 | 说明 |
|---|---|
| Chart | 应用的打包格式,包含 K8s 资源模板与默认配置 |
| Release | Chart 的一次安装实例,同一 Chart 可多次安装产生多个 Release |
| Values | 配置参数,用于自定义 Chart 行为 |
三、Chart 目录结构详解
my-chart/
├── Chart.yaml # Chart 元数据
├── values.yaml # 默认配置
├── charts/ # 依赖 Chart(helm dependency update 生成)
├── Chart.lock # 依赖版本锁定
└── templates/ # 模板文件
├── deployment.yaml
├── service.yaml
├── ingress.yaml
├── _helpers.tpl # 辅助模板
├── NOTES.txt # 安装后提示
└── hooks/ # Hooks 模板(可选)
3.1 Chart.yaml
apiVersion: v2
name: my-webapp
description: A web application chart
type: application
version: 1.2.0 # Chart 版本
appVersion: "2.1.0" # 应用版本
dependencies:
- name: mysql
version: "9.x.x"
repository: https://charts.bitnami.com/bitnami
| 字段 | 说明 |
|---|---|
| version | Chart 版本,语义化版本 |
| appVersion | 应用版本 |
| dependencies | 依赖的 Chart 列表 |
3.2 values.yaml
replicaCount: 2
image:
repository: my-webapp
tag: "2.1.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
ingress:
enabled: false
hostname: app.example.com
resources:
requests:
cpu: "100m"
memory: "128Mi"
limits:
cpu: "500m"
memory: "256Mi"
mysql:
enabled: true
auth:
rootPassword: "" # 生产环境通过 Secret 或 --set 传入
3.3 templates/
| 文件 | 说明 |
|---|---|
| deployment.yaml | Deployment 模板 |
| service.yaml | Service 模板 |
| _helpers.tpl | 定义可复用的命名模板函数 |
| NOTES.txt | 安装后显示给用户的提示 |
| *.yaml | 其他 K8s 资源模板 |
四、Go 模板语法入门
4.1 基础取值
replicas: {{ .Values.replicaCount }}
image: {{ .Values.image.repository }}:{{ .Values.image.tag }}
4.2 条件判断
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: {{ include "my-chart.fullname" . }}
spec:
rules:
- host: {{ .Values.ingress.hostname }}
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: {{ include "my-chart.fullname" . }}
port:
number: 80
{{- end }}
4.3 range 循环
env:
{{- range $key, $value := .Values.extraEnv }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
4.4 with 作用域
{{- with .Values.resources }}
resources:
requests:
cpu: {{ .requests.cpu }}
memory: {{ .requests.memory }}
limits:
cpu: {{ .limits.cpu }}
memory: {{ .limits.memory }}
{{- end }}
4.5 常用函数
| 函数 | 说明 |
|---|---|
| include | 调用 _helpers.tpl 中的模板 |
| toYaml | 转换为 YAML |
| nindent | 缩进 |
| quote | 加引号 |
| default | 默认值 |
五、_helpers.tpl 与 NOTES.txt
5.1 _helpers.tpl
{{/*
Chart 名称
*/}}
{{- define "my-chart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
完整名称
*/}}
{{- define "my-chart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{/*
标签
*/}}
{{- define "my-chart.labels" -}}
helm.sh/chart: {{ include "my-chart.name" . }}
app.kubernetes.io/name: {{ include "my-chart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
5.2 模板示例(templates/deployment.yaml)
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-chart.fullname" . }}
labels:
{{- include "my-chart.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "my-chart.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-chart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: 80
resources:
{{- toYaml .Values.resources | nindent 12 }}
5.3 NOTES.txt
1. Get the application URL by running these commands:
{{- if .Values.ingress.enabled }}
http{{ if $.Values.ingress.tls }}s{{ end }}://{{ .Values.ingress.hostname }}
{{- else }}
export POD_NAME=$(kubectl get pods -l "app.kubernetes.io/instance={{ .Release.Name }}" -o jsonpath="{.items[0].metadata.name}")
kubectl port-forward $POD_NAME 8080:80
{{- end }}
六、依赖管理
6.1 Chart.yaml dependencies
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
6.2 子 Chart 覆盖
子 Chart 的 values 可通过父 Chart 的 values.yaml 中同名 key 覆盖:
# values.yaml
mysql:
enabled: true
auth:
rootPassword: "mysecret"
primary:
persistence:
size: 20Gi
6.3 依赖更新命令
helm dependency update ./my-chart # 下载到 charts/
helm dependency list ./my-chart # 查看依赖
七、Helm Hooks
Hooks 在 Release 生命周期的特定阶段执行。
| Hook | 执行时机 |
|---|---|
| pre-install | 安装前 |
| post-install | 安装后 |
| pre-delete | 删除前 |
| post-delete | 删除后 |
| pre-upgrade | 升级前 |
| post-upgrade | 升级后 |
| pre-rollback | 回滚前 |
| post-rollback | 回滚后 |
7.1 示例
# templates/post-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: "{{ .Release.Name }}-db-migrate"
annotations:
"helm.sh/hook": post-install
"helm.sh/hook-weight": "5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: my-app:migrate
| 注解 | 说明 |
|---|---|
| helm.sh/hook | 指定 Hook 类型 |
| helm.sh/hook-weight | 权重,数值小的先执行 |
| helm.sh/hook-delete-policy | before-hook-creation、hook-succeeded、hook-failed |
八、Helm 常用命令
# ==================== 仓库管理 ====================
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo mysql
# ==================== 安装与管理 ====================
helm install my-release bitnami/mysql -f my-values.yaml
helm install my-release bitnami/mysql --set auth.rootPassword=secretpass
helm install my-release bitnami/mysql -n production --create-namespace
helm install my-release bitnami/mysql --dry-run --debug
# ==================== 升级与回滚 ====================
helm upgrade my-release bitnami/mysql -f new-values.yaml
helm upgrade --install my-release bitnami/mysql # 幂等部署
helm history my-release
helm rollback my-release
helm rollback my-release 2
# ==================== 查看与调试 ====================
helm list
helm list -A
helm status my-release
helm get manifest my-release
helm get values my-release
helm template my-release ./my-chart -f values.yaml --debug
# ==================== 卸载 ====================
helm uninstall my-release
九、Values 覆盖优先级
从低到高(后者覆盖前者):
- Chart 内
values.yaml - 父 Chart 的
values.yaml(子 Chart 时) -f values-prod.yaml指定的文件--set key=value命令行参数
# 优先级:--set > -f values-prod.yaml > values.yaml
helm install my-release ./my-chart -f values-prod.yaml --set replicaCount=5
十、Helm + CI/CD 集成模式
10.1 典型流程
# 1. 构建镜像
docker build -t my-registry/my-app:$TAG .
# 2. 推送镜像
docker push my-registry/my-app:$TAG
# 3. Helm 升级
helm upgrade --install my-app ./my-chart \
-n production \
-f values-prod.yaml \
--set image.tag=$TAG \
--atomic \
--timeout 5m
10.2 幂等部署
helm upgrade --install my-release ./my-chart -f values.yaml
10.3 原子升级
helm upgrade my-release ./my-chart --atomic
# 失败时自动回滚
十一、常见社区 Chart
| 类别 | Chart | 用途 |
|---|---|---|
| 数据库 | bitnami/mysql, bitnami/postgresql, bitnami/redis | 关系型/NoSQL 存储 |
| 监控 | prometheus-community/kube-prometheus-stack, grafana/grafana | 指标采集与可视化 |
| 日志 | elastic/elasticsearch, elastic/kibana, fluent/fluent-bit | 日志存储与采集 |
| Ingress | ingress-nginx/ingress-nginx, traefik/traefik | 七层负载均衡 |
| CI/CD | jenkins/jenkins, argoproj/argo-cd | 流水线与 GitOps |
十二、Chart 开发最佳实践
| 实践 | 说明 |
|---|---|
| _helpers.tpl | 定义 fullname、labels 等复用模板 |
| NOTES.txt | 安装后显示访问方式、后续步骤 |
| values 结构 | 合理分层,便于环境覆盖 |
| 敏感信息 | 通过 Secret 或 --set 传入,不写入 values.yaml |
| 条件渲染 | 使用 if 控制可选资源(如 Ingress) |
| Chart 版本 | 遵循语义化版本,变更时递增 |
十三、FAQ
13.1 模板渲染如何调试?
# 本地渲染,不连接集群
helm template my-release ./my-chart -f values.yaml --debug
# 显示渲染后的 YAML
helm get manifest my-release
--debug 会输出渲染过程中的中间结果,便于排查模板错误。
13.2 values 覆盖优先级如何确认?
命令行 --set > -f xxx.yaml > values.yaml。多次 -f 时,后面的覆盖前面的。可通过 helm get values 查看最终生效的 values。
13.3 Chart 版本如何管理?
- 语义化版本:主版本.次版本.修订号
- 在 Chart.yaml 中维护 version 和 appVersion
- 发布到 Chart 仓库时打 tag
- 使用 Chart.lock 锁定依赖版本
13.4 子 Chart 依赖如何覆盖?
在父 Chart 的 values.yaml 中,以子 Chart 的 name 为 key 写入配置:
mysql:
auth:
rootPassword: "override"
十四、生产建议
| 类别 | 建议 |
|---|---|
| 敏感信息 | 使用 Secret 或 --set,不提交到版本库 |
| 部署 | 使用 helm upgrade --install 实现幂等 |
| 关键 Release | 使用 --atomic 失败时自动回滚 |
| 超时 | 大资源使用 --timeout 10m |
| 环境 | 不同环境使用不同 values 文件 |
十五、总结
| 概念 | 说明 |
|---|---|
| Chart | 应用打包格式,含模板与默认配置 |
| Release | Chart 的安装实例 |
| Values | 配置参数,支持多环境覆盖 |
| Hooks | 生命周期钩子 |
更多推荐


所有评论(0)