Helm 包管理实战
场景
团队需要在 K8s 集群里部署复杂应用:微服务、数据库、中间件、监控组件。手写 YAML 不仅繁琐,还难以管理版本、环境差异、依赖关系。
Helm 解决三个核心问题:
- 模板化 — 把 YAML 参数化,同一套 Chart 跨环境复用
- 依赖管理 —
requirements.yaml/Chart.yaml声明依赖,一键拉取 - 发布管理 — 版本、回滚、历史、diff,发布过程可控
前置条件
- K8s 集群 1.19+(Helm 3 不再需要 Tiller)
- 本地已安装 Helm 3.8+
- 有集群的 kubeconfig,且有创建 namespace、CRD 的权限
- 了解基本的 K8s 资源对象
配置
1. 基础操作
# 添加常用仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo add grafana https://grafana.github.io/helm-charts
helm repo update
# 搜索
helm search repo nginx
helm search repo prometheus
# 查看 Chart 详情
helm show chart bitnami/redis
helm show values bitnami/redis > redis-values.yaml
2. 安装与配置
# 默认值安装
helm install my-redis bitnami/redis -n redis --create-namespace
# 自定义 values
helm install my-redis bitnami/redis \
-n redis --create-namespace \
-f redis-values.yaml \
--set auth.password=StrongPass123 \
--set replica.replicaCount=2
# 覆盖单个值(命令行优先级最高)
helm upgrade my-redis bitnami/redis -n redis \
--set replica.replicaCount=3 \
--set auth.password=NewPass456
3. 管理发布
# 查看
helm list -n redis
helm status my-redis -n redis
helm get values my-redis -n redis # 当前生效的值
helm get manifest my-redis -n redis # 渲染后的完整 manifest
# 回滚
helm history my-redis -n redis
helm rollback my-redis 1 -n redis # 回滚到 revision 1
# 卸载(保留 PVC 用 --keep-history)
helm uninstall my-redis -n redis
4. 开发自己的 Chart
helm create myapp
# 生成结构:
# myapp/
# Chart.yaml # 元数据
# values.yaml # 默认值
# templates/ # 模板
# charts/ # 依赖 Chart
Chart.yaml 关键字段
apiVersion: v2
name: myapp
description: 我的微服务应用
type: application
version: 1.0.0 # Chart 版本
appVersion: "1.2.3" # 应用版本
keywords:
- microservice
- api
maintainers:
- name: 运维团队
email: ops@example.com
dependencies:
- name: redis
version: "17.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
values.yaml 设计原则
# 全局配置
global:
imageRegistry: harbor.example.com
imagePullSecrets:
- harbor-secret
# 开关控制
redis:
enabled: true
auth:
enabled: true
password: "changeme"
# 资源配额
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
# 环境区分
env: production
5. 模板最佳实践
# _helpers.tpl 定义通用标签
{{- define "myapp.labels" -}}
helm.sh/chart: {{ .Chart.Name }}-{{ .Chart.Version | replace "+" "_" }}
{{ include "myapp.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
# 模板中使用
metadata:
labels:
{{- include "myapp.labels" . | nindent 4 }}
环境区分(values-prod.yaml / values-staging.yaml)
# 生产环境
helm install myapp ./myapp -n prod -f values.yaml -f values-prod.yaml
# 测试环境
helm install myapp ./myapp -n staging -f values.yaml -f values-staging.yaml
6. 常用调试技巧
# 只渲染不安装(调试模板)
helm template myapp ./myapp -n test -f values.yaml
# 模拟升级(看 diff)
helm upgrade --dry-run myapp ./myapp -n prod -f values-prod.yaml
# 查看 hooks
helm get hooks my-release -n ns
# 调试模板函数
helm template ./myapp --show-only templates/deployment.yaml
验证
# 部署后检查
kubectl get pods -n ns -l app=myapp
kubectl logs -n ns -l app=myapp -c main
helm test my-release -n ns # 运行 Chart 定义的测试
# 验证 Chart 语法
helm lint ./myapp
回滚
# 快速回滚
helm rollback myapp 1 -n prod
# 指定版本回滚
helm history myapp -n prod
helm rollback myapp 3 -n prod
坑
| 坑 | 现象 | 避坑 |
|---|---|---|
values 里写了 enabled: false 但依赖 Chart 还是装了 |
依赖的 condition 写错 |
检查 Chart.yaml 里的 condition: xxx.enabled |
| 升级后旧 PVC 绑不上 | StorageClass / PVC 名字变了 | 用 helm upgrade 不要改 PVC 名,或手动迁移 |
helm upgrade 把 ConfigMap 覆盖了 |
没用 --reuse-values |
helm upgrade -f new.yaml --reuse-values |
helm dependency update 报错 |
依赖仓库没加 / 版本不存在 | helm repo update 先,指定版本号 |
| Chart 版本和 App 版本混淆 | Chart version ≠ appVersion | version 是 Chart 版本,appVersion 是镜像版本 |
| 环境变量没生效 | 模板里写死值了 | 用 .Values.xxx 不要硬编码 |
helm upgrade 把 PVC 删了 |
Chart 里 PVC 没设 keepPolicy |
加 helm.sh/resource-policy: keep 注解 |