- Authors

- Name
- Phillip Pham
- @ddppham
Jobs und CronJobs: Batch-Workloads auf Kubernetes
TL;DR
- Kubernetes Jobs führen Aufgaben einmalig bis zum erfolgreichen Abschluss aus -- im Gegensatz zu Deployments, die dauerhaft laufen.
- Drei Job-Typen: Einzelner Pod, parallele Verarbeitung mit fester Completion-Anzahl und Indexed Jobs für partitionierte Workloads.
- CronJobs erstellen Jobs nach einem Zeitplan im Cron-Format und unterstützen Concurrency-Policies (Allow, Forbid, Replace).
- TTL-Controller räumt abgeschlossene Jobs automatisch auf, damit der Cluster nicht mit alten Pods volläuft.
- Häufigster Fehler: CronJobs mit
concurrencyPolicy: Allowerzeugen bei langsamen Jobs parallele Instanzen, die sich gegenseitig blockieren.
Jobs: Einmalige Aufgaben ausführen
Ein Deployment startet Pods und hält sie am Laufen. Ein Job startet Pods und wartet, bis sie erfolgreich beendet werden. Typische Einsatzgebiete: Datenbank-Migrationen, Batch-Imports, Report-Generierung, ML-Training-Runs.
apiVersion: batch/v1
kind: Job
metadata:
name: db-migration
spec:
ttlSecondsAfterFinished: 3600
backoffLimit: 3
activeDeadlineSeconds: 600
template:
spec:
containers:
- name: migrate
image: myapp:1.5
command: ["python", "manage.py", "migrate"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
restartPolicy: Never
Die wichtigsten Felder im Überblick:
| Feld | Bedeutung | Empfehlung |
|---|---|---|
backoffLimit | Max. Neustarts bei Fehler | 3-6 für idempotente Jobs |
activeDeadlineSeconds | Max. Laufzeit gesamt | Immer setzen als Sicherheitsnetz |
ttlSecondsAfterFinished | Aufräumzeit nach Abschluss | 3600 (1h) für Debugging-Fenster |
restartPolicy | Never oder OnFailure | Never für bessere Fehleranalyse |
restartPolicy: Never erstellt bei Fehlern neue Pods (bis backoffLimit). restartPolicy: OnFailure startet den Container im selben Pod neu. Never ist besser für Debugging, weil die Logs alter Pods erhalten bleiben.
Parallele Jobs
Für Workloads, die sich aufteilen lassen, unterstützt Kubernetes parallele Ausführung.
Feste Completion-Anzahl
apiVersion: batch/v1
kind: Job
metadata:
name: video-encoding
spec:
completions: 10
parallelism: 3
backoffLimit: 5
template:
spec:
containers:
- name: encoder
image: encoder:2.1
command: ["encode", "--chunk-from-queue"]
resources:
requests:
cpu: "2"
memory: "4Gi"
limits:
cpu: "4"
memory: "8Gi"
restartPolicy: Never
Dieser Job braucht 10 erfolgreiche Completions und startet maximal 3 Pods gleichzeitig. Kubernetes erstellt neue Pods, sobald einer fertig ist, bis alle 10 Durchläufe abgeschlossen sind.
Indexed Jobs
Seit Kubernetes 1.24 stabil. Jeder Pod bekommt einen eindeutigen Index über die Umgebungsvariable JOB_COMPLETION_INDEX. Damit lassen sich Daten partitionieren.
apiVersion: batch/v1
kind: Job
metadata:
name: data-processing
spec:
completionMode: Indexed
completions: 5
parallelism: 5
template:
spec:
containers:
- name: processor
image: processor:1.0
command:
- "sh"
- "-c"
- |
echo "Processing partition $JOB_COMPLETION_INDEX of 5"
python process.py --partition=$JOB_COMPLETION_INDEX --total=5
restartPolicy: Never
Pod 0 verarbeitet Partition 0, Pod 1 Partition 1 und so weiter. Kein externer Koordinationsmechanismus nötig.
CronJobs: Zeitgesteuerte Ausführung
CronJobs erstellen Jobs nach einem Cron-Zeitplan. Die Syntax entspricht dem klassischen Unix-Cron-Format.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-backup
spec:
schedule: "0 2 * * *"
timeZone: "Europe/Berlin"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
startingDeadlineSeconds: 300
suspend: false
jobTemplate:
spec:
ttlSecondsAfterFinished: 86400
backoffLimit: 2
template:
spec:
containers:
- name: backup
image: backup-tool:3.0
command:
- "sh"
- "-c"
- |
pg_dump $DATABASE_URL | gzip > /backups/db-$(date +%Y%m%d).sql.gz
aws s3 cp /backups/db-$(date +%Y%m%d).sql.gz s3://backups/
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef:
name: db-credentials
key: url
restartPolicy: OnFailure
Concurrency-Policies
Die concurrencyPolicy bestimmt, was passiert, wenn ein neuer CronJob-Lauf fällig ist, während der vorherige noch läuft.
# Aktive CronJobs auflisten
kubectl get cronjobs
# Letzte Job-Laeufe eines CronJobs anzeigen
kubectl get jobs --selector=job-name=nightly-backup
# CronJob manuell ausloesen (zum Testen)
kubectl create job --from=cronjob/nightly-backup manual-backup-test
| Policy | Verhalten | Einsatz |
|---|---|---|
Allow (Default) | Mehrere Jobs laufen parallel | Unabhängige, idempotente Tasks |
Forbid | Neuer Lauf wird übersprungen | Datenbank-Backups, Locks |
Replace | Alter Job wird abgebrochen | Reports, bei denen nur der neueste zählt |
Wichtig: Allow ist der Default. Wenn ein Backup-Job 3 Stunden läuft und stündlich geplant ist, laufen ohne Forbid drei Backup-Prozesse gleichzeitig -- das kann die Datenbank überlasten.
Suspend und Resume
CronJobs lassen sich pausieren, ohne sie zu löschen. Das ist nützlich bei Wartungsfenstern oder wenn ein nachgelagertes System nicht verfügbar ist.
# CronJob pausieren
kubectl patch cronjob nightly-backup -p '{"spec":{"suspend":true}}'
# CronJob wieder aktivieren
kubectl patch cronjob nightly-backup -p '{"spec":{"suspend":false}}'
# Alle CronJobs im Namespace pausieren
kubectl get cronjobs -o name | xargs -I {} kubectl patch {} -p '{"spec":{"suspend":true}}'
Auch laufende Jobs lassen sich nachträglich suspendieren (seit Kubernetes 1.24):
# Laufenden Job pausieren
kubectl patch job video-encoding -p '{"spec":{"suspend":true}}'
# Job fortsetzen
kubectl patch job video-encoding -p '{"spec":{"suspend":false}}'
Beim Suspendieren eines Jobs werden aktive Pods beendet. Beim Fortsetzen erstellt Kubernetes neue Pods. Der Job-Controller merkt sich, wie viele Completions bereits erreicht wurden.
TTL-Cleanup: Alte Jobs aufräumen
Ohne Cleanup sammeln sich abgeschlossene Jobs und deren Pods im Cluster an. Der TTL-Controller löscht sie automatisch.
# Am Job:
spec:
ttlSecondsAfterFinished: 3600 # 1 Stunde nach Abschluss loeschen
# Am CronJob (History-Limits):
spec:
successfulJobsHistoryLimit: 3 # Nur die letzten 3 erfolgreichen behalten
failedJobsHistoryLimit: 5 # Nur die letzten 5 fehlgeschlagenen behalten
Für bestehende Cluster mit vielen alten Jobs hilft ein einmaliger Cleanup:
# Abgeschlossene Jobs aelter als 24h loeschen
kubectl get jobs --field-selector status.successful=1 \
-o jsonpath='{.items[?(@.status.completionTime)].metadata.name}' | \
tr ' ' '\n' | xargs -I {} kubectl delete job {}
Häufige Fehler und Lösungen
Verpasste Schedules
Wenn der CronJob-Controller ausfällt oder der Cluster neustartet, können Schedules verpasst werden. startingDeadlineSeconds steuert, wie lange ein verpasster Lauf noch nachgeholt wird.
Fehlt das Feld, werden verpasste Läufe unbegrenzt nachgeholt. Bei 100 verpassten Läufen startet Kubernetes 100 Jobs gleichzeitig. Das Feld immer setzen -- 300 Sekunden sind ein guter Wert.
BackoffLimit erreicht
Wenn ein Job backoffLimit Mal fehlschlägt, markiert Kubernetes ihn als Failed. Die Backoff-Zeiten steigen exponentiell: 10s, 20s, 40s bis maximal 6 Minuten. Logs der fehlgeschlagenen Pods prüfen:
# Fehlgeschlagene Pods des Jobs finden
kubectl get pods --selector=job-name=db-migration --field-selector=status.phase=Failed
# Logs des letzten fehlgeschlagenen Pods
kubectl logs job/db-migration --tail=50
Ressourcen-Limits vergessen
Jobs ohne Ressourcen-Limits können den gesamten Node belegen. Besonders bei parallelen Jobs mit parallelism: 10 wichtig. Immer requests und limits setzen -- oder LimitRanges und ResourceQuotas auf Namespace-Ebene konfigurieren.
FAQ
Was ist der Unterschied zwischen Jobs und Deployments?
Deployments halten Pods dauerhaft am Laufen und starten sie bei Ausfällen neu. Jobs führen Pods bis zum erfolgreichen Abschluss aus und stoppen dann. Jobs eignen sich für einmalige oder wiederkehrende Batch-Aufgaben, Deployments für langlebige Services.
Kann ich einen fehlgeschlagenen Job neu starten?
Nicht direkt. Ein fehlgeschlagener Job bleibt im Failed-Status. Man muss den Job löschen und neu erstellen. Bei CronJobs passiert das automatisch beim nächsten Zeitplan-Lauf. Für manuelle Jobs: kubectl delete job my-job && kubectl apply -f job.yaml.
Wie überwache ich CronJobs in Produktion?
Mit Prometheus und dem kube-state-metrics Exporter. Die Metrik kube_cronjob_next_schedule_time zeigt den nächsten geplanten Lauf. kube_job_failed zählt fehlgeschlagene Runs. Alerting-Regel: Alarm wenn kube_cronjob_next_schedule_time - time() < 0 -- der CronJob hat seinen Zeitplan verpasst.
Unterstützen CronJobs Zeitzonen?
Ja, seit Kubernetes 1.27 stabil. Das Feld timeZone akzeptiert IANA-Zeitzonen wie Europe/Berlin. Ohne dieses Feld nutzt der Controller die Zeitzone des kube-controller-manager -- das ist in Cloud-Umgebungen meist UTC.
Wie viele parallele Jobs verträgt ein Cluster?
Das hängt von den Cluster-Ressourcen ab. Jeder Job-Pod braucht CPU und Memory. Als Faustregel: parallelism so setzen, dass die Gesamtlast der parallelen Pods 60-70% der verfügbaren Node-Kapazität nicht übersteigt. ResourceQuotas auf Namespace-Ebene verhindern, dass ein einzelner CronJob den Cluster überlastet.
Kubernetes-Expertise gesucht?
Managed Services, Beratung, Training oder Security – wir unterstützen deutsche Unternehmen bei allen Kubernetes-Themen.
Kubernetes-Beratung gesucht?
Wir helfen deutschen Unternehmen bei der Kubernetes-Implementierung, Migration und Optimierung. DSGVO-konform und praxiserprobt.
📖 Verwandte Artikel
Weitere interessante Beiträge zu ähnlichen Themen
Kubernetes Batch Production in der Fertigung: Ihr Weg zur modernen Produktion in Deutschland
Erfahren Sie, wie Kubernetes Batch Production in der diskreten und Prozessfertigung revolutioniert. Optimieren Sie Ihre Fertigungsprozesse mit Kubernetes für präzises Rezept-Management, automatisierte Skalierung und gesteigerte Wettbewerbsfähigkeit – entscheidend für die Kubernetes Production in Deutschland.
Kubernetes Scheduling: Affinity, Taints und Tolerations
Kubernetes Scheduling mit Node Affinity, Taints und Tolerations steuern. Praktische Beispiele für GPU-Nodes, Zone-Spreading und Co-Location.
Windows Container auf Kubernetes betreiben
Windows Container in Kubernetes-Clustern betreiben: Node Pools konfigurieren, Taints und nodeSelector richtig setzen und Limitierungen kennen.
CKA Scheduling: Node Affinity, Taints und Resources
Kubernetes Scheduling für die CKA-Prüfung meistern: Node Affinity, Taints, Tolerations, Resource Requests und Limits mit praktischen YAML-Beispielen.
CKAD Pod Design: Deployments, Jobs und CronJobs meistern
Alle Pod-Design-Themen für die CKAD-Prüfung: Deployments, Rolling Updates, ReplicaSets, Jobs, CronJobs, Labels und Selektoren mit Übungen.