摘要:Helm 是 Kubernetes 的包管理工具,提供 Chart 打包、依赖管理、版本控制和一键部署能力。本文详解 Chart 目录结构、Go 模板语法、依赖管理、Helm Hooks、Chart 开发最佳实践、CI/CD 集成及生产 FAQ。

一、为什么需要 Helm?

在 Kubernetes 原生方式下,部署一个完整应用需要维护多个独立的 YAML 清单文件,存在文件分散、环境差异管理困难、版本追溯和回滚复杂等问题。Helm 通过 Chart 封装和 Values 参数化,将多资源管理统一为单次操作。

使用 Helm

helm install

集中部署

values 管理环境

版本与回滚

无 Helm:手动管理

deployment.yaml

多文件管理痛点

service.yaml

configmap.yaml

secret.yaml

ingress.yaml

二、Helm 核心概念

概念 说明
Chart 应用的打包格式,包含 K8s 资源模板与默认配置
Release Chart 的一次安装实例,同一 Chart 可多次安装产生多个 Release
Values 配置参数,用于自定义 Chart 行为

Chart

模板文件

默认配置

Release

prod-db 实例

test-db 实例

Values

密码、存储、副本数

三、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 覆盖优先级

从低到高(后者覆盖前者):

  1. Chart 内 values.yaml
  2. 父 Chart 的 values.yaml(子 Chart 时)
  3. -f values-prod.yaml 指定的文件
  4. --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 生命周期钩子

Helm 核心能力

一键部署

多环境配置

版本管理与回滚

依赖管理

社区 Chart 生态

Logo

开源鸿蒙跨平台开发社区汇聚开发者与厂商,共建“一次开发,多端部署”的开源生态,致力于降低跨端开发门槛,推动万物智联创新。

更多推荐