Helm Charts Kubernetes
Helm Charts für Kubernetes
Helm ist der Package Manager für Kubernetes. Lernen Sie Charts zu erstellen, zu konfigurieren und in Produktionsumgebungen einzusetzen.
Was ist Helm?
┌─────────────────────────────────────────────────────────────┐ │ HELM │ ├─────────────────────────────────────────────────────────────┤ │ │ │ OHNE HELM: │ │ ┌─────────────────────────────────────────────┐ │ │ │ deployment.yaml │ │ │ │ service.yaml │ │ │ │ configmap.yaml → kubectl apply -f │ │ │ │ secret.yaml │ │ │ │ ingress.yaml │ │ │ └─────────────────────────────────────────────┘ │ │ × Keine Versionierung │ │ × Keine Parameter │ │ × Schwer zu verwalten │ │ │ │ MIT HELM: │ │ ┌─────────────────────────────────────────────┐ │ │ │ myapp-chart/ │ │ │ │ Chart.yaml │ │ │ │ values.yaml → helm install myapp│ │ │ │ templates/ │ │ │ └─────────────────────────────────────────────┘ │ │ ✓ Versioniert │ │ ✓ Parametrisiert │ │ ✓ Wiederverwendbar │ │ │ └─────────────────────────────────────────────────────────────┘
Helm Installation
# macOS brew install helm # Linux curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash # Windows (Chocolatey) choco install kubernetes-helm # Version prüfen helm version
Chart Struktur
myapp/ ├── Chart.yaml # Chart Metadaten ├── values.yaml # Default Konfiguration ├── charts/ # Abhängigkeiten ├── templates/ # Kubernetes Manifests (Templates) │ ├── _helpers.tpl # Template Helpers │ ├── deployment.yaml │ ├── service.yaml │ ├── configmap.yaml │ ├── ingress.yaml │ ├── hpa.yaml │ └── NOTES.txt # Post-Install Hinweise └── .helmignore # Dateien zum Ignorieren
Chart.yaml
# Chart.yaml
apiVersion: v2
name: myapp
description: A Helm chart for MyApp
type: application
version: 1.0.0 # Chart Version
appVersion: "2.3.1" # App Version
maintainers:
- name: DevOps Team
email: devops@example.com
dependencies:
- name: postgresql
version: "12.1.0"
repository: "https://charts.bitnami.com/bitnami"
condition: postgresql.enabled
- name: redis
version: "17.0.0"
repository: "https://charts.bitnami.com/bitnami"
condition: redis.enabled
values.yaml
# values.yaml - Default Konfiguration
replicaCount: 2
image:
repository: myapp/backend
tag: "latest"
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: true
className: nginx
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-tls
hosts:
- app.example.com
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
env:
LOG_LEVEL: info
DATABASE_HOST: postgresql
secrets:
databasePassword: "" # Überschreiben bei Installation
postgresql:
enabled: true
auth:
database: myapp
username: myapp
redis:
enabled: false
Templates
# templates/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:
labels:
{{- include "myapp.selectorLabels" . | nindent 8 }}
annotations:
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:
- name: http
containerPort: {{ .Values.service.targetPort }}
protocol: TCP
env:
{{- range $key, $value := .Values.env }}
- name: {{ $key }}
value: {{ $value | quote }}
{{- end }}
- name: DATABASE_PASSWORD
valueFrom:
secretKeyRef:
name: {{ include "myapp.fullname" . }}
key: database-password
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 15
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
resources:
{{- toYaml .Values.resources | nindent 12 }}
# templates/_helpers.tpl
{{/*
Expand the name of the chart.
*/}}
{{- define "myapp.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{/*
Create a default fully qualified app name.
*/}}
{{- 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 }}
{{/*
Common labels
*/}}
{{- define "myapp.labels" -}}
helm.sh/chart: {{ include "myapp.chart" . }}
{{ include "myapp.selectorLabels" . }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{/*
Selector labels
*/}}
{{- define "myapp.selectorLabels" -}}
app.kubernetes.io/name: {{ include "myapp.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
Helm Befehle
# Repository hinzufügen helm repo add bitnami https://charts.bitnami.com/bitnami helm repo update # Chart suchen helm search repo nginx helm search hub wordpress # Chart installieren helm install myapp ./myapp # Lokaler Chart helm install myapp bitnami/nginx # Aus Repo helm install myapp ./myapp -f production.yaml # Mit Values-Datei helm install myapp ./myapp --set replicaCount=5 # Mit Override # Namespace angeben helm install myapp ./myapp -n production --create-namespace # Dry-Run (nur anzeigen, nicht anwenden) helm install myapp ./myapp --dry-run --debug # Template rendern (ohne Installation) helm template myapp ./myapp # Upgrade helm upgrade myapp ./myapp helm upgrade myapp ./myapp --set image.tag=v2.0.0 helm upgrade --install myapp ./myapp # Install oder Upgrade # Rollback helm rollback myapp 1 # Zur Revision 1 # Liste aller Releases helm list helm list -A # Alle Namespaces # Release Status helm status myapp # History helm history myapp # Deinstallieren helm uninstall myapp
Values überschreiben
# values-production.yaml
replicaCount: 5
image:
tag: "v2.3.1"
resources:
limits:
cpu: 1000m
memory: 512Mi
requests:
cpu: 500m
memory: 256Mi
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
ingress:
hosts:
- host: app.production.com
paths:
- path: /
pathType: Prefix
# Mehrere Values-Dateien kombinieren # (später überschreibt frühere) helm install myapp ./myapp \ -f values.yaml \ -f values-production.yaml \ --set secrets.databasePassword=$DB_PASSWORD
Dependencies verwalten
# Dependencies herunterladen helm dependency update ./myapp # Erstellt charts/ Ordner mit: # charts/ # ├── postgresql-12.1.0.tgz # └── redis-17.0.0.tgz # Chart.lock wird erstellt (Versionen einfrieren) # Dependencies auflisten helm dependency list ./myapp
Chart testen
# Lint (Syntax prüfen)
helm lint ./myapp
# Template rendern und prüfen
helm template myapp ./myapp | kubectl apply --dry-run=client -f -
# Tests im Chart (templates/tests/)
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "myapp.fullname" . }}-test"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: wget
image: busybox
command: ['wget']
args: ['{{ include "myapp.fullname" . }}:{{ .Values.service.port }}']
restartPolicy: Never
# Tests ausführen
helm test myapp
Chart veröffentlichen
# Chart packen helm package ./myapp # Erstellt: myapp-1.0.0.tgz # Index erstellen (für Repository) helm repo index . --url https://charts.example.com # GitHub Pages als Helm Repo # 1. charts/ Ordner mit .tgz Dateien # 2. index.yaml generieren # 3. GitHub Pages aktivieren # OCI Registry (moderne Methode) helm push myapp-1.0.0.tgz oci://registry.example.com/charts # Aus OCI Registry installieren helm install myapp oci://registry.example.com/charts/myapp --version 1.0.0
Hooks
# templates/job-migrate.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "myapp.fullname" . }}-migrate
annotations:
"helm.sh/hook": pre-upgrade,pre-install
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": hook-succeeded
spec:
template:
spec:
containers:
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
command: ["./migrate.sh"]
restartPolicy: Never
backoffLimit: 1
# Hook Types:
# pre-install, post-install
# pre-upgrade, post-upgrade
# pre-delete, post-delete
# pre-rollback, post-rollback
💡 Best Practices:
1. Sinnvolle Defaults in values.yaml
2. Alle konfigurierbaren Werte dokumentieren
3. Chart.lock committen für reproduzierbare Builds
4. Helm Tests für kritische Funktionen
5. Semantic Versioning für Chart-Versionen
2. Alle konfigurierbaren Werte dokumentieren
3. Chart.lock committen für reproduzierbare Builds
4. Helm Tests für kritische Funktionen
5. Semantic Versioning für Chart-Versionen