Helm — Kubernetes 包管理器
核心概念
Chart(包):K8s 应用的打包格式
├── Chart.yaml → 包元数据
├── values.yaml → 默认配置值
├── templates/ → K8s 资源模板
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ └── _helpers.tpl → 模板辅助函数
└── charts/ → 依赖的子 Chart
Release(发布):Chart 在集群中的一次部署实例
Repository(仓库):Chart 的存储和分发中心常用命令
bash
# 添加仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
# 搜索 Chart
helm search repo redis
helm search hub kafka # 在 Artifact Hub 搜索
# 安装
helm install my-redis bitnami/redis \
--namespace production \
--create-namespace \
--set auth.password=mypassword \
--set replica.replicaCount=2
# 使用自定义 values 文件安装
helm install my-redis bitnami/redis \
-f custom-values.yaml \
--namespace production
# 查看已安装的 Release
helm list -n production
helm list --all-namespaces
# 升级
helm upgrade my-redis bitnami/redis \
--namespace production \
--set image.tag=7.2.0 \
--reuse-values # 保留之前的 values
# 回滚
helm rollback my-redis 1 # 回滚到第1个版本
helm history my-redis -n production # 查看历史版本
# 卸载
helm uninstall my-redis -n production
# 渲染模板(不安装,用于调试)
helm template my-release ./my-chart -f values.yaml
# 验证 Chart
helm lint ./my-chart创建自定义 Chart
bash
# 创建 Chart 骨架
helm create order-serviceChart.yaml
yaml
apiVersion: v2
name: order-service
description: Order Service Helm Chart
type: application
version: 1.2.0 # Chart 版本
appVersion: "2.0.0" # 应用版本
dependencies:
- name: redis
version: "18.x.x"
repository: https://charts.bitnami.com/bitnami
condition: redis.enabledvalues.yaml
yaml
replicaCount: 2
image:
repository: my-registry/order-service
tag: "1.2.0"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: true
className: nginx
host: api.example.com
path: /orders
resources:
requests:
cpu: 100m
memory: 256Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 70
env:
SPRING_PROFILES_ACTIVE: production
LOG_LEVEL: INFO
secrets:
dbPassword: "" # 通过 --set 或外部 Secret 注入
redis:
enabled: true
auth:
password: ""templates/deployment.yaml
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "order-service.fullname" . }}
labels:
{{- include "order-service.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "order-service.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "order-service.selectorLabels" . | nindent 8 }}
annotations:
# 配置变更时触发 Pod 重启
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- containerPort: {{ .Values.service.targetPort }}
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
{{- if .Values.secrets.dbPassword }}
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "order-service.fullname" . }}-secret
key: db-password
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
readinessProbe:
httpGet:
path: /actuator/health/readiness
port: {{ .Values.service.targetPort }}
initialDelaySeconds: 10
periodSeconds: 5
livenessProbe:
httpGet:
path: /actuator/health/liveness
port: {{ .Values.service.targetPort }}
initialDelaySeconds: 30
periodSeconds: 10templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "order-service.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- define "order-service.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 }}
{{/*
Common labels
*/}}
{{- define "order-service.labels" -}}
helm.sh/chart: {{ include "order-service.chart" . }}
{{ include "order-service.selectorLabels" . }}
app.kubernetes.io/version: {{ .Values.image.tag | default .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "order-service.selectorLabels" -}}
app.kubernetes.io/name: {{ include "order-service.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}多环境管理
bash
# 目录结构
helm/
order-service/
Chart.yaml
values.yaml # 默认值
values-dev.yaml # 开发环境覆盖
values-staging.yaml # 预发布环境覆盖
values-prod.yaml # 生产环境覆盖
templates/
# 部署到不同环境
helm upgrade --install order-service ./helm/order-service \
-f ./helm/order-service/values.yaml \
-f ./helm/order-service/values-prod.yaml \
--namespace production \
--set image.tag=${CI_COMMIT_SHA}Helm Secrets(加密敏感配置)
bash
# 安装 helm-secrets 插件
helm plugin install https://github.com/jkroepke/helm-secrets
# 加密 values 文件(使用 SOPS + AWS KMS/GPG)
helm secrets enc values-prod-secrets.yaml
# 部署时自动解密
helm secrets upgrade --install order-service ./chart \
-f values-prod.yaml \
-f secrets://values-prod-secrets.yaml故障处理案例
案例一:Release 卡在 pending-upgrade 状态
现象:helm list 显示 Release 状态为 pending-upgrade,无法继续操作。
解决:
bash
# 查看 Release 历史
helm history order-service -n production
# 强制回滚到上一个版本
helm rollback order-service 0 -n production --force
# 或删除 pending 状态的 Secret
kubectl get secrets -n production | grep order-service
kubectl delete secret sh.helm.release.v1.order-service.v3 -n production案例二:模板渲染错误
bash
# 调试模板渲染
helm template order-service ./chart -f values.yaml --debug 2>&1 | head -50
# 验证 Chart
helm lint ./chart -f values.yaml案例三:依赖 Chart 版本冲突
bash
# 更新依赖
helm dependency update ./chart
# 查看依赖
helm dependency list ./chart