Helm是K8s的包管理器,将一组K8s YAML模板化,通过values.yaml参数化配置,实现"一键部署"复杂应用。类似apt/yum之于Linux。
┌──────────── Helm核心概念 ────────────┐
│ │
│ Chart = 一个应用包 │
│ ├── Chart.yaml # 元数据 │
│ ├── values.yaml # 默认配置 │
│ ├── templates/ # K8s模板 │
│ │ ├── deployment.yaml │
│ │ ├── service.yaml │
│ │ ├── ingress.yaml │
│ │ ├── _helpers.tpl # 共用模板 │
│ │ └── NOTES.txt # 安装提示 │
│ └── charts/ # 依赖Chart │
│ │
│ Release = Chart的一次安装实例 │
│ 同一Chart可以安装多次(不同Release) │
│ │
│ Repository = Chart仓库 │
│ Artifact Hub / Chart Museum / 自建 │
│ │
│ Helm 3架构(无Tiller): │
│ helm → K8s API Server │
│ Release存储在K8s Secret中 │
└────────────────────────────────────────┘
# 安装Helm
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# ✅ 验证通过
helm version
# version.BuildInfo{Version:"v3.14.x", ...}
# 添加仓库
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# 搜索Chart
helm search repo nginx
# NAME CHART VERSION APP VERSION DESCRIPTION
# bitnami/nginx 16.x.x 1.25.x NGINX Open Source...
# 安装Chart
helm install my-nginx bitnami/nginx \
--namespace web \
--create-namespace \
--set replicaCount=3 \
--set service.type=NodePort
# ✅ 验证通过
helm list -n web
# NAME NAMESPACE REVISION STATUS CHART APP VERSION
# my-nginx web 1 deployed nginx-16.x.x 1.25.x
# 查看Release状态
helm status my-nginx -n web
# 查看Release历史
helm history my-nginx -n web
# 创建Chart
helm create my-app
# Creating my-app
# 目录结构
tree my-app
# my-app/
# ├── Chart.yaml
# ├── Chart.lock
# ├── values.yaml
# ├── charts/
# ├── templates/
# │ ├── deployment.yaml
# │ ├── service.yaml
# │ ├── ingress.yaml
# │ ├── hpa.yaml
# │ ├── serviceaccount.yaml
# │ ├── _helpers.tpl
# │ ├── NOTES.txt
# │ └── tests/
# │ └── test-connection.yaml
# my-app/Chart.yaml
apiVersion: v2
name: my-app
description: A Helm chart for my application
type: application # application | library
version: 1.0.0 # Chart版本(SemVer2)
appVersion: "2.1.0" # 应用版本
kubeVersion: ">=1.24.0" # 兼容的K8s版本
dependencies:
- name: redis
version: "18.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled # 条件依赖
alias: cache # 别名
- name: postgresql
version: "13.x.x"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
maintainers:
- name: team
email: team@example.com
home: https://github.com/example/my-app
sources:
- https://github.com/example/my-app
keywords: ["web", "api", "microservice"]
# my-app/values.yaml
replicaCount: 2
image:
repository: my-registry/my-app
pullPolicy: IfNotPresent
tag: "" # 默认用Chart.appVersion
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
serviceAccount:
create: true
annotations: {}
name: ""
podAnnotations: {}
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop: ["ALL"]
readOnlyRootFilesystem: true
service:
type: ClusterIP
port: 8080
ingress:
enabled: false
className: nginx
annotations: {}
hosts:
- host: my-app.example.com
paths:
- path: /
pathType: Prefix
tls: []
resources:
requests:
cpu: 100m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
# 依赖Chart配置
redis:
enabled: true
architecture: standalone
auth:
enabled: false
postgresql:
enabled: true
auth:
username: app
database: appdb
primary:
persistence:
size: 10Gi
# my-app/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
replicas: {{ .Values.replicaCount }}
selector:
matchLabels:
{{- include "my-app.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
labels:
{{- include "my-app.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "my-app.serviceAccountName" . }}
securityContext:
{{- toYaml .Values.podSecurityContext | nindent 8 }}
containers:
- name: {{ .Chart.Name }}
securityContext:
{{- toYaml .Values.securityContext | nindent 12 }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.port }}
env:
- name: REDIS_HOST
value: {{ include "my-app.redisHost" . | quote }}
- name: DB_HOST
value: {{ include "my-app.postgresqlHost" . | quote }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
livenessProbe:
httpGet:
path: /healthz
port: http
readinessProbe:
httpGet:
path: /ready
port: http
# my-app/templates/_helpers.tpl
{{- define "my-app.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else if .Values.nameOverride }}
{{- .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- define "my-app.labels" -}}
helm.sh/chart: {{ printf "%s-%s" .Chart.Name .Chart.Version | replace "+" "_" | trunc 63 | trimSuffix "-" }}
{{ include "my-app.selectorLabels" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "my-app.selectorLabels" -}}
app.kubernetes.io/name: {{ .Chart.Name }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
{{- define "my-app.redisHost" -}}
{{- if .Values.redis.enabled }}
{{- printf "%s-cache-master" (include "my-app.fullname" .) }}
{{- else }}
{{- .Values.externalRedis.host | default "redis" }}
{{- end }}
{{- end }}
# 安装时自定义values
helm install my-app ./my-app \
-f my-values.yaml \
--set image.tag=v2.1.0 \
--set replicaCount=5
# 升级
helm upgrade my-app ./my-app \
--set image.tag=v2.2.0 \
--reuse-values # 保留之前的values
# 回滚
helm rollback my-app 1 # 回滚到revision 1
# 卸载
helm uninstall my-app -n web
# 调试模板渲染(不安装)
helm template my-app ./my-app > rendered.yaml
helm install my-app ./my-app --dry-run --debug
# 更新依赖
helm dependency update ./my-app
helm dependency build ./my-app
# ✅ 验证通过 - 完整安装流程
helm install my-app ./my-app -n production -f prod-values.yaml
kubectl get all -n production -l app.kubernetes.io/instance=my-app
# 查看渲染后的YAML
helm get manifest my-app -n web
# 查看所有values
helm get values my-app -n web --all
# Chart验证
helm lint ./my-app
# ==> Linting ./my-app
# 1 chart(s) linted, 0 chart(s) failed
# 查看Release状态异常
helm status my-app -n web
下一课预告:第17课深入自定义CRD——扩展K8s API。
16-helm包管理补充要点K8s生产实践扩展
🔹 资源配额(ResourceQuota):限制命名空间总资源
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: production
spec:
hard:
requests.cpu: "20"
requests.memory: 40Gi
limits.cpu: "40"
limits.memory: 80Gi
pods: "50"
services: "10"
🔹 LimitRange:设置默认资源限制
apiVersion: v1
kind: LimitRange
metadata:
name: default-limits
spec:
limits:
- type: Container
default:
cpu: "200m"
memory: 256Mi
defaultRequest:
cpu: "100m"
memory: 128Mi
max:
cpu: "2"
memory: 4Gi
🔹 Pod优先级与抢占
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority
value: 1000000
globalDefault: false
---
spec:
preemptionPolicy: PreemptLowerPriority
🔹 优雅处理Pod中断
• PDB保证最小可用副本
• preStop钩子处理连接排空
• terminationGracePeriodSeconds充足
• 应用必须处理SIGTERM信号
🔹 生产环境Checklist
✅ 设置resources requests/limits
✅ 配置liveness/readiness探针
✅ 使用PDB保护关键服务
✅ 实现优雅关闭(SIGTERM)
✅ 配置HPA自动伸缩
✅ 使用NetworkPolicy隔离
✅ 开启RBAC最小权限
✅ 日志结构化输出
✅ 指标暴露/metrics端点
✅ 配置PVC数据备份
16-helm包管理生产环境进阶要点
🔹 性能优化关键参数
• kubelet: --max-pods=110 --pods-per-core=10
• kube-apiserver: --max-requests-inflight=800
• etcd: --quota-backend-bytes=8589934592
• kube-scheduler: --percentage-of-nodes-to-score=50
🔹 集群容量规划
• 控制平面:3节点,8C16G起步
• Worker节点:按应用类型分组
• etcd:SSD磁盘,<2ms延迟
• 网络带宽:10Gbps+集群内互联
🔹 故障自愈最佳实践
1. Pod: livenessProbe自动重启
2. Deployment: ReplicaSet保证副本数
3. Node: kubelet自注册+健康检查
4. Cluster: Cluster Autoscaler增减节点
5. Multi-Cluster: Karmada联邦容灾
🔹 K8s版本升级策略
• 每次只升一个minor版本
• 先升级控制平面,再升级Worker
• 使用kubeadm upgrade plan预检
• 准备回滚方案
• 在staging环境验证后再升级prod