Aller au contenu

Jobs et CronJobs

Tout ne mérite pas un Deployment qui tourne en permanence. Pour une tâche qui s’exécute puis se termine — migration de base, import, purge, dump — Kubernetes propose le Job (exécution unique) et le CronJob (planifiée). Et comme seuls les pods Running sont facturés, à l’heure entamée, une tâche quotidienne ne coûte qu’une heure par jour — environ 25 fois moins qu’un pod permanent.

Job : une exécution unique

Cas d’usage type : une migration de schéma avant une mise en production.

apiVersion: batch/v1
kind: Job
metadata:
name: migrate-v2
spec:
backoffLimit: 3 # nb de tentatives en cas d'échec
ttlSecondsAfterFinished: 3600 # auto-nettoyage 1 h après la fin (important !)
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: registry.exemple.com/acme/mon-app:2.0.0
command: ["./migrate.sh"]
env:
- name: DATABASE_URL
valueFrom:
secretKeyRef: {name: ma-base-app, key: uri}
resources:
requests: {cpu: 100m, memory: 256Mi}
Fenêtre de terminal
kubectl apply -f migrate.yaml -n <namespace>
kubectl wait --for=condition=complete job/migrate-v2 -n <namespace> --timeout=300s
kubectl logs job/migrate-v2 -n <namespace>

CronJob : l’exécution planifiée

Cas d’usage type : un dump de base quotidien (exemple complet), une purge de fichiers, un rapport hebdomadaire.

apiVersion: batch/v1
kind: CronJob
metadata:
name: purge-quotidienne
spec:
schedule: "30 4 * * *" # tous les jours à 4h30 (heure UTC)
concurrencyPolicy: Forbid # jamais deux exécutions en parallèle
successfulJobsHistoryLimit: 3 # ne garder que les 3 derniers pods réussis
failedJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: Never
containers:
- name: purge
image: registry.exemple.com/acme/mon-app:2.0.0
command: ["./purge-old-files.sh"]
resources:
requests: {cpu: 100m, memory: 128Mi}
Fenêtre de terminal
kubectl get cronjobs -n <namespace>
# Déclencher manuellement sans attendre l'horaire (pour tester)
kubectl create job purge-test --from=cronjob/purge-quotidienne -n <namespace>

Les HistoryLimit jouent le même rôle que le TTL des Jobs : ils bornent le nombre de pods terminés conservés — gardez-les bas.

Ce qui s’applique aussi aux Jobs

Un pod de Job est un pod comme un autre sur Kontainers :

  • Requests injectées si absentes — déclarez-les ;
  • Limite mémoire = request : un job de build ou d’import gourmand doit demander sa vraie consommation, sinon OOMKilled ;
  • Quotas : 20 Jobs et 10 CronJobs par namespace (référence), et les pods actifs comptent dans les 20 pods ;
  • Le coût : la facturation est à l’heure entamée — un CronJob quotidien de quelques minutes à 1 bundle ≈ 1 h facturée par jour, soit ≈ 0,12 € par mois. Comparez au même script dans un Deployment qui dort : 2,88 €/mois. Et des exécutions rapprochées dans la même heure ne s’additionnent pas tant qu’elles ne se chevauchent pas (la base horaire est le maximum observé).