用 kubectl apply -f 部署一个简单应用还行,一旦应用包含 Deployment、Service、ConfigMap、Secret、Ingress、HPA、ServiceAccount 等十几个资源,手工维护一堆 YAML 就变成负担:改个镜像版本要在多个文件里找,换套环境要复制粘贴整份配置,想回滚还得靠版本控制硬比对。
Helm 就是为解决这些问题而生的。它被称为「Kubernetes 的包管理器」,用「Chart(包)」「Release(部署实例)」「Values(配置值)」三个核心概念,把一堆 YAML 组织成可参数化、可版本化、可一键回滚的部署单元。类比一下:如果 Kubernetes 是操作系统,那 Helm 就像 apt/yum,Chart 像 rpm/deb 包,Release 像已安装的软件实例。
这篇文章会讲清 Helm 3 的核心概念和工作流程、Chart 的目录结构、如何从零写一个 Chart、如何用 values.yaml 管理多环境、升级与回滚的实操命令,以及仓库管理和安全注意事项,让你能真正把 Helm 用起来。
一、Helm 3 的核心概念
Helm 3 相比 Helm 2 最大的变化是去掉了 Tiller(服务端组件),改用客户端直连 API Server,权限模型直接走 Kubernetes 的 RBAC,安全性和易用性都大幅提升。
三个核心概念:
- Chart:一个应用包,包含模板化的 YAML 和默认配置,可被版本化、打包、分享;
- Release:Chart 在集群里的一次部署实例。同一个 Chart 可以部署多个 Release(如
dev、prod),互不干扰; - Values:配置值,用来填充模板。多环境差异通过覆盖 values 实现,模板本身不用改。
外加两个概念:
- Repository(仓库):存放 Chart 的地方,可以是 HTTP 服务器或对象存储;
- Revision(修订版本):每次 helm upgrade 都会产生新的 revision,回滚就是切到旧 revision。
二、安装 Helm
Helm 是单文件二进制,安装很快。
方式一:官方脚本(Linux/macOS)
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
chmod 700 get_helm.sh
./get_helm.sh
方式二:包管理器
# RHEL/CentOS/Rocky
sudo dnf install helm
# Debian/Ubuntu(部分源需先添加官方源)
sudo apt-get install helm
方式三:直接下载二进制
wget https://get.helm.sh/helm-v3.14.0-linux-amd64.tar.gz
tar -zxvf helm-v3.14.0-linux-amd64.tar.gz
sudo mv linux-amd64/helm /usr/local/bin/
验证:
helm version
如果当前用户没有集群权限,先确保 kubeconfig 可用:
kubectl cluster-info
三、Chart 的目录结构
一个标准 Chart 长这样:
mychart/
├── Chart.yaml # Chart 元信息(名称、版本、appVersion)
├── values.yaml # 默认配置值
├── charts/ # 依赖的子 Chart
├── templates/ # 模板文件(渲染成 K8s 资源)
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── configmap.yaml
│ ├── ingress.yaml
│ ├── _helpers.tpl # 可复用的模板片段
│ └── NOTES.txt # 安装后提示信息
└── .helmignore # 打包时忽略的文件
Chart.yaml 示例:
apiVersion: v2
name: myapp
description: A demo web application
type: application
version: 0.1.0 # Chart 版本
appVersion: "1.0.0" # 应用版本
新手最容易混淆 version 和 appVersion:version 是 Chart 自身的版本(模板变了就升它),appVersion 是被部署应用的版本(应用升级才升它)。两者独立。
四、模板与 Values 的配合
templates/deployment.yaml 用 Go 模板语法引用 values:
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ .Release.Name }}-{{ .Chart.Name }}
labels:
app: {{ .Chart.Name }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
app: {{ .Chart.Name }}
template:
metadata:
labels:
app: {{ .Chart.Name }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.targetPort }}
resources:
{{ toYaml .Values.resources | indent 12 }}
对应的 values.yaml:
replicaCount: 2
image:
repository: nginx
tag: "1.25"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 80
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 256Mi
常用内置对象:
- .Release.Name / .Release.Namespace:本次部署的名称与命名空间;
- .Chart.Name / .Chart.Version:Chart 名称与版本;
- .Values.*:values 中的配置;
- .Capabilities.KubeVersion:当前集群版本,可用于条件判断。
多环境就用不同的 values 文件覆盖:
# values.yaml(默认) + values-prod.yaml(覆盖)
helm install myapp ./mychart -f values-prod.yaml
模板支持条件与循环,可以按环境开关资源:
{{- if .Values.ingress.enabled }}
# 只有开启 ingress 时才渲染这段
{{- end }}
五、安装、升级与回滚
先在本地渲染出来看看,确定要下发的 YAML 长什么样:
helm template myapp ./mychart -f values-prod.yaml > rendered.yaml
这一步非常有用,能在真正部署前发现模板错误。
语法检查:
helm lint ./mychart
安装:
helm install myapp ./mychart -n demo --create-namespace -f values-prod.yaml
查看 Release:
helm list -A
helm status myapp -n demo
helm get values myapp -n demo # 看实际使用的值
helm get manifest myapp -n demo # 看渲染后的资源清单
升级:
helm upgrade myapp ./mychart -n demo -f values-prod.yaml
# 只改镜像版本
helm upgrade myapp ./mychart -n demo --set image.tag=1.26
回滚:
# 查看历史版本
helm history myapp -n demo
# 回滚到上一个版本
helm rollback myapp -n demo
# 回滚到指定 revision
helm rollback myapp 3 -n demo
回滚是 Helm 的一大优势:它会对比 revision 之间的资源差异并应用旧版本配置,比手工改回 YAML 可靠得多。
卸载:
helm uninstall myapp -n demo
风险提示:helm uninstall 默认会删除该 Release 管理的所有资源,包括 Service、Deployment 等。若有 PVC 是通过 Chart 创建的,是否保留取决于你是否加了 helm.sh/resource-policy: keep 注解,否则可能连带删除存储导致数据丢失。卸载前用 helm get manifest 确认资源清单,并对有状态数据做备份。回滚方式:若 Chart 仍在本机,可 helm install 恢复;若数据已丢,只能从备份恢复。
六、Chart 仓库与依赖管理
添加公共仓库(示例,具体地址以官方为准):
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm search repo nginx
拉取并查看某个 Chart 的默认值:
helm pull bitnami/nginx --untar
cat nginx/values.yaml
依赖管理:Chart 可以依赖其他 Chart,在 Chart.yaml 里声明:
dependencies:
- name: postgresql
version: "12.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
然后更新依赖:
helm dependency update ./mychart
搭建私有仓库(用对象存储或静态文件服务器即可):
# 打包 Chart
helm package ./mychart
# 生成索引
helm repo index . --url https://charts.example.com
# 客户端添加
helm repo add internal https://charts.example.com
七、Helm 常用操作速查
| 操作 | 命令 |
|---|---|
| 安装 | helm install |
| 升级 | helm upgrade |
| 回滚 | helm rollback |
| 列出 | helm list -A |
| 查看值 | helm get values |
| 渲染预览 | helm template |
| 语法检查 | helm lint |
| 查看历史 | helm history |
| 卸载 | helm uninstall |
| 添加仓库 | helm repo add |
八、多环境与最佳实践
一套 Chart 多环境。把公共部分放 values.yaml,各环境差异放 values-dev.yaml、values-prod.yaml,部署时用 -f 叠加。这样模板只有一份,维护成本最低。
目录建议:
helm/
├── mychart/
│ ├── values.yaml
│ ├── values-dev.yaml
│ ├── values-staging.yaml
│ └── values-prod.yaml
优先用 helm template 做 CI 校验。在 CI 流水线里渲染并跑 kubeval 或 kubectl apply --dry-run=server,能在合并前拦住大部分配置错误。
敏感信息不要写进 values。数据库密码、密钥等应走 Kubernetes Secret,或用外部方案(如外部 Secret 管理器)注入,不要把明文密码提交到 Git。
锁定 Chart 版本。生产环境部署时明确指定 Chart 版本号,避免仓库更新导致行为漂移:
helm install myapp ./mychart --version 1.2.3
注意 --atomic 与超时。--atomic 会在升级失败时自动回滚,配合 --timeout 使用更稳:
helm upgrade myapp ./mychart -n demo --atomic --timeout 5m
风险提示:--atomic 会自动回滚,但回滚过程同样会重建 Pod,可能造成短暂中断。对可用性要求高的服务建议配合 PodDisruptionBudget。
九、Helm 的边界:哪些事它不做
把 Helm 用顺手之后,容易产生一种「什么都用 Helm 管」的冲动,这里要泼点冷水。Helm 的定位是「模板化打包和生命周期管理」,它擅长的是把一组静态的、声明式的 Kubernetes 资源组织成一个可参数化、可版本化的包。但它并不负责运行时的很多事情。
第一,Helm 不做配置热更新。改了 values 必须 helm upgrade 触发一次渲染和下发,Helm 不会像 Operator 那样持续 watch 集群状态并自动纠偏。如果你的应用需要「声明期望状态、由控制器持续维持」,那是 Operator 的领域,不是 Helm 的强项。
第二,Helm 不管理「集群外部」的资源。它只能创建 Kubernetes API 对象。数据库实例、对象存储桶、DNS 记录、云厂商负载均衡的具体参数,这些要么通过 External Secrets、Crossplane 之类的方案,要么在 Kubernetes 里用 CRD + Operator 表达,Helm 只能负责把对应的 CR 交给对应的控制器。
第三,Helm 的模板能力有限。它用的是 Go template,做条件、循环没问题,但逻辑一复杂就会变得难读难维护。如果模板里塞满了几十层嵌套的 if 和 range,说明你可能该考虑换一种组织方式,或者拆分成多个子 Chart,而不是继续堆模板。
第四,Helm 不认识「部署完成是否健康」。helm install 成功只代表资源被 API Server 接受,不代表 Pod 真的起来了。要让 Helm 等待就绪,得用 --wait,并给资源配好 readinessProbe,否则 helm status 显示 deployed、实际服务却不可用的「假成功」很常见。
认清这些边界,能帮你判断什么时候该用 Helm、什么时候该上 Operator,也能避免把 Helm 当成万能胶而过度设计。
再补一个实务上的判断标准:如果你需要的是「一次把事情装好、之后偶尔升级」,Helm 是合适的;如果你需要的是「持续保证实际状态等于期望状态、能自动重建、能根据事件做反应」,那就是控制器/Operator 的世界。两者并不互斥——现实中很常见的组合是「用 Helm 部署 Operator,再由 Operator 管理真正的业务实例」,各司其职,各自发挥长处。
常见问题
Q1:Helm 和 kubectl 的关系是什么?
A:Helm 是构建在 kubectl 能力之上的客户端工具,模板最终渲染成标准 Kubernetes 资源再由 API Server 创建。Helm 不替代 kubectl,两者常配合使用(Helm 部署,kubectl 排障)。
Q2:chart version 和 appVersion 到底改哪个?
A:改了模板/配置结构就升 version;只是换了应用镜像版本就升 appVersion。实践中两个一起升也无妨,但概念要分清。
Q3:Helm 2 的 Tiller 没了,权限怎么控制?
A:Helm 3 直接用你的 kubeconfig 身份访问集群,权限由 RBAC 决定。给 CI 用的 ServiceAccount 按最小权限授权即可。
Q4:升级失败了一半,资源处于混乱状态怎么办?
A:用 helm history 找到上一个健康版本,helm rollback 回退;再用 helm get manifest 对比差异。生产升级建议加 --atomic。
Q5:不同环境的值怎么管理才不混乱?
A:守住一条原则——模板里不放环境相关的硬编码,所有差异都通过 values 注入。公共值放默认文件,差异放各环境文件,用 -f 依次覆盖。
总结
- 记住三个核心:Chart 是包,Release 是部署实例,Values 是配置;同一 Chart 可部署多套 Release 服务于不同环境。
- 部署前先用
helm template渲染、helm lint检查,把错误拦在集群之外,这是最省事的习惯。 - 升级用
helm upgrade,出问题用helm rollback秒回上一个 revision,这是 Helm 相对裸 YAML 的核心价值。 - 多环境靠「一套模板 + 多份 values 文件」实现,模板里杜绝环境硬编码;敏感信息走 Secret,不进 Git。
helm uninstall和存储卷删除是高风险操作,卸载前用helm get manifest核对资源、备份有状态数据,必要时加resource-policy: keep注解保护 PVC。
企业QQ咨询




