Chapter 08

Helm:包管理与模板引擎

Helm 是 Kubernetes 的包管理器,将复杂应用的多个 YAML 打包为 Chart,实现一键安装、升级、回滚,并通过 values.yaml 实现多环境配置。

Helm 解决了什么问题

部署一个完整的应用(如 MySQL)需要创建 Deployment、Service、ConfigMap、Secret、PVC、ServiceAccount 等多个 YAML 文件,还需要按正确顺序 apply。Helm 将这些打包为一个 Chart,让你用一行命令完成整个应用的部署。

没有 Helm

  • 手动管理 10+ 个 YAML 文件
  • 不同环境复制修改 YAML
  • 升级时手动比较 diff
  • 回滚需要记住旧配置
  • 无法复用他人的配置

有了 Helm

  • 一条命令安装/升级/回滚
  • values.yaml 管理环境差异
  • 版本化的发布历史记录
  • Artifact Hub 上万现成 Chart
  • 模板化复用,DRY 原则

Helm 安装

# macOS
brew install helm

# Linux
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash

# 验证
helm version

Chart 目录结构

Chart 标准目录结构

my-app/
├── Chart.yaml           Chart 元数据(名称、版本、描述)
├── values.yaml          默认配置值(最重要的文件)
├── charts/              依赖的子 Chart
├── templates/           YAML 模板目录
│   ├── deployment.yaml
│   ├── service.yaml
│   ├── configmap.yaml
│   ├── ingress.yaml
│   ├── _helpers.tpl       模板辅助函数(下划线开头不渲染为资源)
│   └── NOTES.txt          安装成功后显示的提示信息
└── .helmignore           类似 .gitignore,打包时排除的文件

Chart.yaml

apiVersion: v2                    # Helm 3 使用 v2
name: my-app                      # Chart 名称
description: A simple web application
type: application                  # application 或 library
version: 0.1.0                    # Chart 版本(SemVer)
appVersion: "1.2.3"              # 应用版本(显示用,不影响部署)
dependencies:                     # 依赖的 Chart
- name: mysql
  version: 9.x.x
  repository: https://charts.bitnami.com/bitnami
  condition: mysql.enabled        # 可选条件,values 中控制是否启用

values.yaml

# 这是模板的默认值,用户可以通过 --values 或 --set 覆盖
replicaCount: 2

image:
  repository: nginx
  tag: "1.25"
  pullPolicy: IfNotPresent

service:
  type: ClusterIP
  port: 80

ingress:
  enabled: false                 # 默认不创建 Ingress
  host: example.com

resources:
  requests:
    cpu: 100m
    memory: 128Mi
  limits:
    cpu: 500m
    memory: 256Mi

mysql:
  enabled: true
  auth:
    rootPassword: changeme
    database: myapp

模板语法

Helm 使用 Go 模板语言({{ }})将 values.yaml 中的值注入 YAML 模板。

# templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ include "my-app.fullname" . }}     # 调用 _helpers.tpl 中的函数
  labels:
    {{- include "my-app.labels" . | nindent 4 }}  # 缩进 4 空格
spec:
  replicas: {{ .Values.replicaCount }}          # 注入 values
  selector:
    matchLabels:
      {{- include "my-app.selectorLabels" . | nindent 6 }}
  template:
    spec:
      containers:
      - name: {{ .Chart.Name }}                  # Chart 名称
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        resources:
          {{- toYaml .Values.resources | nindent 10 }}  # 对象直接转 YAML
{{- if .Values.ingress.enabled }}              # 条件判断
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: {{ include "my-app.fullname" . }}
spec:
  rules:
  - host: {{ .Values.ingress.host }}
{{- end }}

Helm 常用命令

仓库管理

# 添加常用仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add stable https://charts.helm.sh/stable
helm repo update                     # 更新本地缓存

# 搜索 Chart
helm search repo mysql
helm search hub redis               # 从 Artifact Hub 搜索

# 查看 Chart 的 values
helm show values bitnami/mysql

安装与升级

# 安装(第一次部署)
helm install my-release bitnami/mysql \
  --namespace production \
  --create-namespace \
  --values prod-values.yaml \
  --set auth.rootPassword=myStrongPass

# 升级(更新配置或 Chart 版本)
helm upgrade my-release bitnami/mysql \
  --values prod-values.yaml

# install or upgrade(幂等,推荐在 CI 中使用)
helm upgrade --install my-release bitnami/mysql \
  --values prod-values.yaml

# 查看 Release 列表
helm list -A                          # 所有 namespace

# 查看 Release 状态
helm status my-release

# 查看发布历史
helm history my-release

# 回滚到上一版本
helm rollback my-release

# 回滚到指定版本
helm rollback my-release 2

# 卸载
helm uninstall my-release
helm upgrade --install 的重要性

在 CI/CD 流水线中,始终使用 helm upgrade --install 而不是分别判断 install/upgrade。这样无论是首次部署还是更新,命令都能正确执行,保证流水线的幂等性。

创建自定义 Chart

# 创建 Chart 脚手架
helm create my-app

# 检查模板语法(不部署)
helm lint my-app/

# 渲染模板(查看生成的 YAML,不部署)
helm template my-release my-app/ \
  --values my-values.yaml

# 调试安装(--dry-run 只渲染,不实际部署)
helm install my-release my-app/ \
  --dry-run --debug

# 打包 Chart
helm package my-app/              # 生成 my-app-0.1.0.tgz

# 推送到 OCI 仓库(Helm 3.8+)
helm push my-app-0.1.0.tgz oci://registry.example.com/charts

多环境配置管理

# values-dev.yaml / values-staging.yaml / values-prod.yaml
# 每个环境只覆盖不同的部分

# 开发环境部署
helm upgrade --install my-app ./my-app \
  --namespace dev \
  -f values-dev.yaml

# 生产环境部署(基础值 + 生产覆盖值)
helm upgrade --install my-app ./my-app \
  --namespace production \
  -f values.yaml \
  -f values-prod.yaml \        # 后面的 -f 覆盖前面的
  --set image.tag=$CI_COMMIT_SHA  # --set 优先级最高
常见错误:values 中的密码暴露

不要将生产密码写入 values.yaml 并提交到 Git!使用 --set 从 CI/CD 环境变量注入,或配合 Helm Secrets 插件(结合 SOPS 加密)管理敏感 values。在 values.yaml 中只保留空占位符或非敏感默认值。