Helm Chart 管理
Helm Chart 管理
Helm 是 Kubernetes 的包管理器,简化应用部署和版本管理。
Chart 结构
myapp/
├── Chart.yaml # Chart 元数据
├── values.yaml # 默认配置值
├── values-dev.yaml # 开发环境配置
├── values-prod.yaml # 生产环境配置
├── charts/ # 依赖的子 Chart
├── templates/ # Kubernetes 资源模板
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── hpa.yaml
│ ├── _helpers.tpl # 模板辅助函数
│ └── NOTES.txt # 安装后提示信息
└── README.md
Chart.yaml
apiVersion: v2
name: myapp
description: A Helm chart for MyApp
type: application
version: 1.0.0 # Chart 版本
appVersion: "1.0.0" # 应用版本
keywords:
- kubernetes
- microservices
home: https://github.com/example/myapp
sources:
- https://github.com/example/myapp
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: mongodb
version: "13.0.0"
repository: https://charts.bitnami.com/bitnami
condition: mongodb.enabled
- name: redis
version: "17.0.0"
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled
values.yaml
# 副本数
replicaCount: 3
# 镜像配置
image:
repository: myapp
pullPolicy: IfNotPresent
tag: "" # 默认使用 Chart.appVersion
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
# Service Account
serviceAccount:
create: true
annotations: {}
name: ""
# Pod 注解和标签
podAnnotations:
prometheus.io/scrape: "true"
prometheus.io/port: "8080"
podLabels:
version: v1
# 安全上下文
podSecurityContext:
runAsNonRoot: true
runAsUser: 1000
fsGroup: 2000
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop:
- ALL
# Service 配置
service:
type: ClusterIP
port: 80
targetPort: 8080
annotations: {}
# Ingress 配置
ingress:
enabled: false
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: chart-example.local
paths:
- path: /
pathType: Prefix
tls:
- secretName: chart-example-tls
hosts:
- chart-example.local
# 资源限制
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 200m
memory: 256Mi
# HPA 自动扩缩容
autoscaling:
enabled: true
minReplicas: 3
maxReplicas: 10
targetCPUUtilizationPercentage: 70
targetMemoryUtilizationPercentage: 80
# 健康检查
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
# 环境变量
env:
- name: APP_ENV
value: "production"
- name: LOG_LEVEL
value: "info"
# ConfigMap
configMap:
enabled: true
data:
app.json: |
{
"port": 8080,
"logLevel": "info"
}
# Secret
secret:
enabled: true
data: {}
# 持久化存储
persistence:
enabled: false
storageClass: ""
accessMode: ReadWriteOnce
size: 10Gi
# MongoDB 依赖
mongodb:
enabled: true
auth:
rootPassword: "password"
database: myapp
# Redis 依赖
redis:
enabled: true
auth:
password: "password"
模板示例
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "myapp.fullname" . }}
labels:
{{- include "myapp.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "myapp.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
{{- with .Values.podAnnotations }}
{{- toYaml . | nindent 8 }}
{{- end }}
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
{{- with .Values.podLabels }}
{{- toYaml . | nindent 8 }}
{{- end }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
serviceAccountName: {{ include "myapp.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.targetPort }}
protocol: TCP
{{- with .Values.env }}
env:
{{- toYaml . | nindent 12 }}
{{- end }}
livenessProbe:
{{- toYaml .Values.livenessProbe | nindent 12 }}
readinessProbe:
{{- toYaml .Values.readinessProbe | nindent 12 }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
_helpers.tpl
{{/*
扩展 Chart 名称
*/}}
{{- define "myapp.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
创建完整名称
*/}}
{{- define "myapp.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{/*
Chart 标签
*/}}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ include "myapp.chart" . }}
{{ include "myapp.selectorLabels" . }}
{{- if .Chart.AppVersion }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
{{- end }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
选择器标签
*/}}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
CI/CD 中使用 Helm
GitHub Actions
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: '3.13.0'
- name: Deploy with Helm
run: |
helm upgrade --install myapp ./helm/myapp \
--namespace production \
--create-namespace \
--set image.tag=${{ github.sha }} \
--values helm/myapp/values-prod.yaml \
--wait \
--timeout 5m
GitLab CI
deploy:
stage: deploy
image: alpine/helm:latest
script:
- helm upgrade --install myapp ./helm/myapp
--namespace production
--set image.tag=$CI_COMMIT_SHA
--values helm/myapp/values-prod.yaml
小结
✅ Chart 结构:标准目录布局和文件组织
✅ values.yaml:配置管理和参数化
✅ 模板:动态生成 Kubernetes 资源
✅ CI/CD 集成:自动化部署流程
下一节介绍发布策略和最佳实践。