# 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\. 基础操作 ```bash # 添加常用仓库 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\. 安装与配置 ```bash # 默认值安装 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\. 管理发布 ```bash # 查看 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 ```bash helm create myapp # 生成结构: # myapp/ # Chart.yaml # 元数据 # values.yaml # 默认值 # templates/ # 模板 # charts/ # 依赖 Chart ``` **Chart.yaml 关键字段** ```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 设计原则** ```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\. 模板最佳实践 ```yaml # _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)** ```bash # 生产环境 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\. 常用调试技巧 ```bash # 只渲染不安装(调试模板) 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 ``` ## 验证 ```bash # 部署后检查 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 ``` ## 回滚 ```bash # 快速回滚 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` 注解 |