Kubernetes Jobs exécutent des charges de travail de courte durée jusqu'à leur terminaison ; les CronJobs planifient ces Jobs selon un calendrier récurrent. Lorsqu'un des deux échoue, vous avez besoin d'une méthode reproductible pour identifier la cause racine rapidement. Ce guide explique le fonctionnement des relances et de backoffLimit , où chercher les Pods en échec, comment lire les logs et les événements, et comment dépanner en toute sécurité dans des clusters proches de la production. Vous disposerez également de manifests et de commandes copiables‑collables que vous pourrez adapter dès aujourd'hui.

## Vue d'ensemble du flux de travail

Suivez ce parcours pour diagnostiquer la majorité des problèmes de Job et de CronJob :

- Observer le contrôleur

- kubectl get job

- kubectl get cronjob -o wide

- Repérez les champs d'état : Succeeded , Failed , Active , Last Schedule , Suspend , ConcurrencyPolicy

- Trouver les Pods

- Pour un Job : kubectl get pods -l job-name=<nom-du-job>

- Pour une exécution de CronJob : listez les Jobs possédés par le CronJob ( kubectl get jobs --selector=job-name=<nom-cronjob>- ou par motif de nom), puis listez leurs Pods.

- Décrire pour obtenir les événements et les raisons

- kubectl describe job/<nom>

- kubectl describe pod/<nom-du-pod> (cherchez Reason / Message comme ImagePullBackOff , OOMKilled , Error , FailedScheduling )

- Lire les logs :

- kubectl logs <nom-du-pod> --all-containers=true

- Si le conteneur a planté, ajoutez --previous

- Pour tous les Pods d'un Job : kubectl logs -l job-name=<nom> --all-containers=true

- Vérifier les pièges de la spec

- Jobs : backoffLimit , activeDeadlineSeconds , parallelism , completions , restartPolicy

- CronJobs : schedule , startingDeadlineSeconds , concurrencyPolicy , suspend , successfulJobsHistoryLimit , failedJobsHistoryLimit

- Agir en toute sécurité

- Mettre en pause le CronJob : kubectl patch cronjob/<nom> -p '{"spec":{"suspend":true}}'

- Reproduire en créant un Job ad‑hoc à partir du CronJob : kubectl create job --from=cronjob/<nom> <job-temporaire>

- Appliquer une petite modification, observer événements et logs, puis réactiver.

## Jobs vs CronJobs en pratique

Les Jobs orchestrent les Pods jusqu'à ce que le nombre souhaité de succès soit atteint. Les CronJobs créent des Jobs selon un calendrier. Les différences clés pour le dépannage :

- Jobs : concentrez‑vous sur le cycle de vie des Pods, les codes de sortie, backoffLimit et les problèmes de ressources.

- CronJobs : ajoutez l'évaluation du calendrier, concurrencyPolicy , les exécutions manquées ( startingDeadlineSeconds ) et le nettoyage de l'historique. Vous déboguez d'abord le Job engendré, puis revenez à la spec du CronJob si le problème vient de la planification.

## Dépannage d'un Job qui échoue

- Confirmer l'état

kubectl get job <nom> -o wide 
 Regardez Succeeded , Failed , Active .

- Vérifier les Pods

kubectl get pods -l job-name=<nom> 
 S'il n'y en a pas, inspectez FailedScheduling ou les quotas avec kubectl describe job et kubectl get events .

- Inspecter les événements et le statut

kubectl describe pod <nom-du-pod> 
 Signaux courants :

- ImagePullBackOff : image incorrecte ou secret de pull manquant.

- ErrImagePull : erreur de registre ou d'authentification.

- OOMKilled : limite mémoire trop basse pour le processus.

- Error / Completed : regardez le exitCode dans le statut du conteneur.

- Lire les logs

kubectl logs <nom-du-pod> --all-containers=true 
 Si le conteneur redémarre dans le même Pod ( restartPolicy: OnFailure ), ajoutez --previous .

- Comprendre les relances et backoffLimit

- backoffLimit : nombre maximal de relances de Pod avant que le Job ne soit marqué Failed. Exemple : backoffLimit: 2 autorise deux relances après le premier échec (trois tentatives au total).

- activeDeadlineSeconds : limite de temps dure pour le Job ; son dépassement fait échouer le Job.

- Patterns de correction

- Erreurs d'image : corrigez le tag ou ajoutez imagePullSecrets .

- Pression ressources : augmentez les limites mémoire/CPU ou optimisez la charge.

- Code de sortie non‑zéro : gérez les erreurs dans l'application, ajoutez des relances ou ajustez les entrées.

- Jobs lents : prolongez activeDeadlineSeconds ou réduisez parallelism pour alléger la pression.

## Dépannage d'un CronJob qui échoue

- Lister les CronJobs

kubectl get cronjob -o wide 
 Vérifiez SCHEDULE , SUSPEND , ACTIVE , LAST SCHEDULE .

Si ACTIVE reste 0 et LAST SCHEDULE ne change pas, le contrôleur peut être bloqué ou des filtres de calendrier s'appliquent. Inspectez :

- Est‑il en train de créer des Jobs ?

- suspend: true empêche toute création d'exécution.

- startingDeadlineSeconds : les calendriers manqués plus anciens que cette valeur sont ignorés.

- concurrencyPolicy : Forbid empêche un nouveau lancement si le précédent est encore actif ; Replace annule l'exécution active.

- Inspecter le dernier Job engendré

kubectl get jobs --sort-by=.metadata.creationTimestamp 
 Prenez le Job le plus récent appartenant au CronJob et déboguez‑le comme n'importe quel Job (événements, Pods, logs).

- Opérations sûres

- Mettre en pause temporairement : kubectl patch cronjob/<nom> -p '{"spec":{"suspend":true}}'

- Tester les changements en créant un Job one‑off à partir du template : kubectl create job --from=cronjob/<nom> <job-temporaire>

- Réactiver après validation : kubectl patch cronjob/<nom> -p '{"spec":{"suspend":false}}'

## Exemples pratiques

### Exemple 1 : Un Job qui échoue deux fois puis réussit

apiVersion: batch/v1
kind: Job
metadata:
 name: demo-backoff
spec:
 backoffLimit: 2
 template:
 spec:
 restartPolicy: OnFailure
 containers:
 - name: worker
 image: bash:5
 command: ["bash", "-lc", "if [ ! -f /tmp/ok ]; then echo first or second fail; touch /tmp/ok; exit 1; else echo success; fi" ] 
 Ce qu'il faut observer :

- Le premier Pod sort avec le code 1 ; le contrôleur relance jusqu'à backoffLimit .

- La deuxième tentative échoue aussi ; la troisième affiche success .

- kubectl describe job/demo-backoff montre l'incrémentation de Failed avant Succeeded .

### Exemple 2 : CronJob bloqué par concurrencyPolicy=Forbid

apiVersion: batch/v1
kind: CronJob
metadata:
 name: report-job
spec:
 schedule: "*/5 * * * *"
 concurrencyPolicy: Forbid
 successfulJobsHistoryLimit: 2
 failedJobsHistoryLimit: 2
 jobTemplate:
 spec:
 backoffLimit: 1
 template:
 spec:
 restartPolicy: OnFailure
 containers:
 - name: reporter
 image: bash:5
 command: ["bash", "-lc", "echo starting; sleep 400; echo done" ] 
 Pourquoi il ne planifie pas toutes les 5 min :

- Chaque exécution dure ~6,6 min (400 s). Avec Forbid , le déclencheur de 5 min qui arrive pendant qu'une exécution est active sera ignoré. LAST SCHEDULE n'avance pas à chaque tick.

- Solutions : passer à concurrencyPolicy: Allow , réduire le temps d'exécution, ou augmenter l'intervalle.

### Exemple 3 : ImagePullBackOff dans un Job

apiVersion: batch/v1
kind: Job
metadata:
 name: bad-image
spec:
 template:
 spec:
 restartPolicy: OnFailure
 containers:
 - name: c
 image: example.com/private/app:does-not-exist 
 Dépannage :

- kubectl describe pod affiche ErrImagePull / ImagePullBackOff .

- Corrigez le tag ou configurez imagePullSecrets et l'URL du registre correcte.

### Exemple 4 : OOMKilled dans un Job

apiVersion: batch/v1
kind: Job
metadata:
 name: mem-tight
spec:
 template:
 spec:
 restartPolicy: OnFailure
 containers:
 - name: c
 image: python:3.11
 resources:
 requests:
 memory: "64Mi"
 cpu: "100m"
 limits:
 memory: "64Mi"
 cpu: "200m"
 command: ["python", "-c", "a='x'*200_000_000; print(len(a)) 
 Dépannage :

- kubectl describe pod montre OOMKilled dans le dernier état.

- Augmentez la limite mémoire (par exemple 256Mi ) ou réduisez la consommation mémoire du programme.

## Plan pilote local

Commencez petit et mesurable :

- Choisir un Job aux critères de succès clairs

- Exemple : transformer un petit fichier d'entrée et écrire un checksum.

- Définir la réussite comme code de sortie 0 et présence d'une ligne de sortie attendue.

- Rendre l'inspection facile

- Ajoutez des logs structurés et un message final de succès.

- Réglez backoffLimit à 1 et activeDeadlineSeconds à une borne supérieure sûre.

- Valider dans un cluster local

- Appliquez le Job, surveillez les événements et lisez les logs de bout en bout.

- Enregistrez le temps d'exécution et la consommation de ressources.

- L'embarquer dans un CronJob (optionnel)

- Choisissez d'abord un calendrier conservateur (par exemple toutes les heures).

- Mettez concurrencyPolicy à Forbid jusqu'à preuve d'idempotence.

- Étendre progressivement

- Augmentez la taille des entrées, puis parallelism .

- Ajoutez des alertes sur les échecs de Job et les calendriers manqués.

Cette approche réduit le risque et raccourcit la boucle de rétroaction.

## Conclusion

Les Jobs et CronJobs échouent pour des raisons compréhensibles : images incorrectes, pression sur les ressources, codes de sortie non‑zéro ou règles de planification. Le chemin le plus rapide est constant : vérifier l'état du contrôleur, localiser les Pods, lire les événements, inspecter les logs, et valider les champs de spec tels que backoffLimit , activeDeadlineSeconds , schedule et concurrencyPolicy . Utilisez suspend et les Jobs ad‑hoc pour tester en toute sécurité, puis déployez par petites étapes. Gardez les exécutions courtes, les sorties claires et les critères de succès évidents. C'est ainsi que vous dépannerez avec confiance.