E-NO
Kubernetes 11 min de lecture

Erreurs courantes de configuration des Kubernetes CronJobs (avec exemples pratiques)

calendar_today Publié : 2026-08-01
update Dernière mise à jour : 2026-08-01
analytics Efficacité SEO : 97%
Illustration du guide technique pour « Erreurs courantes de configuration des Kubernetes CronJobs (avec exemples pratiques) ».

Intro

Cette version française explique Kubernetes CronJobs configuration mistakes with practical examples avec le même objectif pratique que l article source : aider le lecteur à comprendre le contexte, les décisions à prendre et les points à vérifier avant de passer à l action.

Les Kubernetes CronJobs sont parfaits pour des tâches récurrentes comme des exports nocturnes, la rotation de logs ou des nettoyages périodiques. Pourtant, de petites erreurs de configuration peuvent provoquer des exécutions qui se chevauchent, des horaires manqués, un trop-plein d'objets d'historique, ou encore des Jobs qui ne démarrent jamais. Ce guide pratique propose des manières sûres de configurer, vérifier et dépanner les CronJobs, avec des exemples concrets en YAML et des commandes kubectl. Vous apprendrez à inventorier votre environnement, choisir des valeurs par défaut prudentes, déployer des changements sans surprise, valider le comportement, récupérer après un échec et appliquer une checklist pour rendre les opérations répétables.

Inventaire de version et d'environnement

Avant tout changement, capturez une vue minimale mais complète de l'environnement. La version et la topologie déterminent les champs disponibles et le comportement du contrôleur.

Commandes

  • Vérifier les versions client et serveur :
  kubectl version --short
  • Lister les groupes d'API CronJob pour confirmer le support :
  kubectl api-resources | grep -i cronjob
  • Inventorier les espaces de noms et les CronJobs existants :
  kubectl get cronjobs.batch -A
  • Inspecter en profondeur un CronJob précis :
  kubectl get cronjob my-cron -n myns -o yaml

Ce qu'il faut capturer (exemples construits ; à vérifier sur votre cluster) :

Élément à capturerCommande d'exempleValeur d'exemple
Version serveur Kuberneteskubectl version --shortServer Version: v1.28.3
API CronJobkubectl api-resourcesbatch/v1 CronJob
Support du fuseau horairekubectl explain cronjob.spec.timeZoneChamp présent en v1.28
Namespace et nomn/amyns/my-cron
Santé du contrôleurkubectl get deploy -n kube-systemcronjob controller available

Notes

  • batch/v1 CronJob est largement disponible dans les clusters modernes. Si votre cluster est très ancien, confirmez si vous êtes en batch/v1beta1 et planifiez une migration.
  • Le champ timeZone est disponible dans les versions récentes. S'il n'apparaît pas dans kubectl explain, ne l'utilisez pas.

Chemin de configuration sûr

Cette section couvre des erreurs fréquentes de configuration et des choix sûrs, avec du YAML prêt à copier et adapter.

Erreur 1 : Autoriser par défaut des exécutions qui se chevauchent

Symptôme : une nouvelle exécution démarre alors que la précédente est encore active, entraînant travail en double ou contention.

Pourquoi : concurrencyPolicy vaut Allow par défaut.

Choix sûr : préférez Forbid pour les tâches idempotentes qui ne doivent pas se chevaucher. N'utilisez Replace que si la nouvelle exécution doit préempter l'ancienne.

Mauvais exemple (chevauchements probables) :

apiVersion: batch/v1
kind: CronJob
metadata:
  name: overlap-prone
spec:
  schedule: "* * * * *"  # chaque minute
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: worker
              image: busybox:1.36
              command: ["/bin/sh","-c","echo starting; sleep 90; echo done"]

Correctif :

spec:
  concurrencyPolicy: Forbid
  schedule: "* * * * *"
  jobTemplate:
    spec:
      backoffLimit: 1
      template:
        spec:
          restartPolicy: OnFailure
          containers:
            - name: worker
              image: busybox:1.36
              command: ["/bin/sh","-c","echo starting; sleep 90; echo done"]

Résultat attendu : lorsqu'une minute passe alors que l'exécution précédente dort toujours, la nouvelle exécution est ignorée. Vérifiez avec :

kubectl get jobs -l cronjob-name=overlap-prone

Erreur 2 : restartPolicy invalide dans le template Job

Symptôme : le Job ne programme aucun Pod ; vous voyez des erreurs de validation, par exemple restartPolicy: Always n'est pas autorisé pour les Jobs.

Choix sûr : définissez restartPolicy sur OnFailure (le plus courant) ou Never.

Extrait correctif :

spec:
  jobTemplate:
    spec:
      template:
        spec:
          restartPolicy: OnFailure  # pas Always

Erreur 3 : startingDeadlineSeconds trop petit ⇒ horaires manqués

Symptôme : le CronJob ne crée pas de Job après une brève panne du plan de contrôle, une lenteur du registre d'images ou un décalage d'horloge.

Pourquoi : startingDeadlineSeconds limite la fenêtre pendant laquelle les exécutions manquées sont démarrées. Trop petit ⇒ abandon trop rapide.

Choix sûr : fixez une fenêtre raisonnable, par ex. quelques minutes pour des fréquences élevées, jusqu'à une heure pour les tâches horaires/quotidiennes.

Exemple pour un job horaire :

spec:
  schedule: "0 * * * *"
  startingDeadlineSeconds: 3600  # rattrapage possible sur 1h

Erreur 4 : Encoder le fuseau horaire dans la crontab ou dépendre de l'heure des nœuds

Symptôme : déclenchements à la mauvaise heure locale ou dérive lors du DST.

Choix sûr :

  • Si votre cluster le supporte, utilisez spec.timeZone pour fixer explicitement le fuseau horaire du job.
  • Sinon, programmez en UTC et convertissez les heures métier en UTC dans l'expression.

Exemple avec timeZone :

spec:
  schedule: "0 2 * * *"
  timeZone: "America/New_York"  # à n'utiliser que si supporté par votre version

Erreur 5 : Rétention d'historique excessive ou insuffisante

Symptôme : bruit API dû à des centaines d'anciens Jobs, ou au contraire pas assez d'historique pour dépanner.

Choix sûr : ajustez par CronJob.

Exemple :

spec:
  successfulJobsHistoryLimit: 3
  failedJobsHistoryLimit: 5
  jobTemplate:
    spec:
      ttlSecondsAfterFinished: 86400  # optionnel si le TTL controller est activé

Erreur 6 : Reprises illimitées sur Pods en échec

Symptôme : Pods qui retentent indéfiniment et se chevauchent avec les déclenchements suivants.

Choix sûr : limitez les reprises et la durée d'exécution.

Exemple :

spec:
  jobTemplate:
    spec:
      backoffLimit: 2
      activeDeadlineSeconds: 1200  # 20 minutes de plafond par job
      template:
        spec:
          restartPolicy: OnFailure

Erreur 7 : ServiceAccount ou permissions manquantes

Symptôme : Pods démarrent mais échouent avec des erreurs RBAC lorsqu'ils doivent appeler l'API ou accéder à des secrets.

Choix sûr : assignez un ServiceAccount minimal et un Role/RoleBinding dans le même namespace.

Exemple :

apiVersion: v1
kind: ServiceAccount
metadata:
  name: cron-sa
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: cron-reader
rules:
  - apiGroups: [""]
    resources: ["configmaps"]
    verbs: ["get","list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: cron-reader-binding
subjects:
  - kind: ServiceAccount
    name: cron-sa
roleRef:
  kind: Role
  name: cron-reader
  apiGroup: rbac.authorization.k8s.io
---
apiVersion: batch/v1
kind: CronJob
metadata:
  name: rbac-aware
spec:
  schedule: "*/15 * * * *"
  concurrencyPolicy: Forbid
  jobTemplate:
    spec:
      template:
        spec:
          serviceAccountName: cron-sa
          restartPolicy: OnFailure
          containers:
            - name: worker
              image: busybox:1.36
              command: ["/bin/sh","-c","kubectl get cm || echo no kubectl here"]

Erreur 8 : Toujours tirer l'image (Always) pour des images stables

Symptôme : pulls inutiles augmentant la latence ou échouant si le registre est indisponible.

Choix sûr : si vous pointez vers un digest ou un tag immuable, utilisez IfNotPresent.

containers:
  - name: worker
    image: myrepo/tool@sha256:...
    imagePullPolicy: IfNotPresent

Habitudes de déploiement plus sûres

  • Exécution de test : utilisez kubectl create job --from=cronjob/<name> <test-name> pour simuler immédiatement une exécution planifiée.
  • Validation en dry-run : kubectl apply --dry-run=server -f cron.yaml pour détecter les erreurs de schéma.
  • Changement progressif : introduisez un nouveau CronJob suffixé -v2, faites-le tourner en parallèle avec suspend=false et mettez l'ancien en suspend=true pour une fenêtre contrôlée, puis finalisez le basculement.
  • Suspension temporaire : mettez un CronJob en pause si nécessaire :
kubectl patch cronjob my-cron -p '{"spec":{"suspend":true}}'

Vérification et diagnostics

Contrôles de base

  • Santé du contrôleur et activité de planification :
kubectl get cronjob my-cron -n myns
kubectl describe cronjob my-cron -n myns
  • Lister les Jobs créés par un CronJob :
kubectl get jobs -n myns -l cronjob-name=my-cron
  • Inspecter les événements et logs du Pod du dernier Job :
JOB=$(kubectl get jobs -n myns -l cronjob-name=my-cron -o jsonpath='{.items[-1:].metadata.name}')
kubectl get pods -n myns -l job-name=$JOB
POD=$(kubectl get pods -n myns -l job-name=$JOB -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n myns $POD
  • Valider la crontab et les champs :
kubectl apply --dry-run=server -f cron.yaml
kubectl explain cronjob.spec

Tableau récapitulatif (erreurs, symptômes, vérifs, correctifs)

ErreurCe que vous voyezVérifier avecCorrectif recommandé
Exécutions qui se chevauchent (Allow)Plusieurs Jobs actifskubectl get jobs -l cronjob-name=NAMEconcurrencyPolicy: Forbid ou Replace
restartPolicy invalide0 Pod pour le Jobkubectl apply --dry-run=server -fOnFailure ou Never
startingDeadlineSeconds trop petitPas de rattrapagekubectl describe cronjobAugmenter la fenêtre
timeZone non supportéChamp ignoré / apply échouekubectl explain cronjob.spec.timeZoneUtiliser l'UTC ou mettre à niveau
Historique excessifCentaines de Jobskubectl get jobs -l cronjob-name=NAMERéduire les limites d'historique
Reprises non bornéesLongues erreurs, chevauchementkubectl describe jobbackoffLimit + activeDeadlineSeconds
RBAC manquantForbidden dans les logskubectl logs; kubectl auth can-iServiceAccount + Role minimal

Résultats attendus d'un CronJob sain

  • kubectl get cronjob affiche LAST SCHEDULE avec un horodatage récent conforme à votre stratégie horaire.
  • kubectl get jobs montre un Job réussi par période attendue, ou un en cours. Les statuts passent de 0/1 à 1/1.
  • kubectl logs du dernier Pod contient la sortie prévue, sans boucle de crash.

Déclenchement manuel et rattrapage

Pour tester sans attendre l'horaire :

  • Créer un job ponctuel depuis le template du CronJob :
kubectl create job --from=cronjob/my-cron my-cron-adhoctest -n myns
  • Étiqueter et tracer ce job ad hoc :
kubectl label job my-cron-adhoctest purpose=adhoc -n myns
  • Supprimer le job ad hoc après validation :
kubectl delete job my-cron-adhoctest -n myns

Modes de panne et reprise

Contrôleur ou API indisponibles

  • Symptôme : aucun nouveau Job aux heures prévues. LAST SCHEDULE n'avance plus.
  • Cause : perturbation du plan de contrôle ou contrôleur CronJob à l'arrêt.
  • Reprise : après rétablissement, assurez-vous que startingDeadlineSeconds est suffisant pour rattraper. Vérifiez la santé du déploiement du contrôleur.

Décalage d'horloge et confusion de fuseau

  • Symptôme : dérive par rapport au temps métier ou au DST.
  • Reprise : préférez l'UTC ou utilisez spec.timeZone si supporté. Comparez LAST SCHEDULE à une horloge UTC de référence.

Erreurs de pull d'image

  • Symptôme : ImagePullBackOff sur les Pods.
  • Reprise : vérifiez imagePullSecrets et disponibilité du registre ; envisagez IfNotPresent pour des images immuables. Relancez avec un job ad hoc.

Échecs RBAC

  • Symptôme : erreurs Forbidden dans les logs lors d'accès API.
  • Reprise : attachez un ServiceAccount minimal, un Role et un RoleBinding. Testez avec :
kubectl auth can-i get configmaps --as=system: serviceaccount: myns: cron-sa -n myns

Crash loops ou dépassements de délais

  • Symptôme : Pods redémarrent ou dépassent la fenêtre d'exécution.
  • Reprise : fixez backoffLimit, ajoutez activeDeadlineSeconds, et assurez-vous que la tâche est idempotente. Inspectez les logs du conteneur.

Encombrement de l'historique

  • Symptôme : grand nombre de Jobs terminés ralentissant les listes.
  • Reprise : baissez successfulJobsHistoryLimit et failedJobsHistoryLimit ; activez ttlSecondsAfterFinished si le contrôleur TTL est disponible.

Arrêt d'urgence et reprise

  • Suspendre temporairement :
kubectl patch cronjob my-cron -n myns -p '{"spec":{"suspend":true}}'
  • Reprendre :
kubectl patch cronjob my-cron -n myns -p '{"spec":{"suspend":false}}'

Stratégie de rollback

  • Conservez un manifeste de référence pour chaque CronJob. Pour revenir en arrière, réappliquez explicitement le fichier précédent :
kubectl apply -f cronjob-prev.yaml
  • Si un champ impose une recréation (rare pour les CronJobs), suspendez l'objet actuel, créez le remplaçant avec un nom distinct, validez une exécution de test, puis supprimez l'ancien.

Vérifications après reprise

  • LAST SCHEDULE avance de nouveau.
  • Un seul Job par période lorsque concurrencyPolicy vaut Forbid.
  • L'historique conserve assez de contexte pour l'analyse sans excès.

Checklist d'exploitation

Inventaire et prérequis

  • [ ] kubectl version --short capturé (client et serveur)
  • [ ] Groupe d'API CronJob confirmé (batch/v1)
  • [ ] Présence de timeZone vérifiée via kubectl explain
  • [ ] Namespace et noms consignés

Sécurité de la configuration

  • [ ] concurrencyPolicy = Forbid (ou Replace avec justification)
  • [ ] restartPolicy = OnFailure ou Never
  • [ ] startingDeadlineSeconds dimensionné à la tolérance
  • [ ] successfulJobsHistoryLimit et failedJobsHistoryLimit ajustés
  • [ ] backoffLimit et activeDeadlineSeconds raisonnables
  • [ ] serviceAccountName défini si besoin API/secret, RBAC minimal
  • [ ] Référence d'image immuable, imagePullPolicy approprié
  • [ ] suspend positionné pour les fenêtres de pause/rollout

Étapes de validation

  • [ ] kubectl apply --dry-run=server passe
  • [ ] kubectl describe cronjob montre la prochaine échéance attendue
  • [ ] Job ad hoc créé et terminé pour les nouveautés/risques

Observation et diagnostic

  • [ ] LAST SCHEDULE se met à jour après changement
  • [ ] Nombre prévu de Jobs actifs par période uniquement
  • [ ] Logs des Pods inspectés et cohérents

Récupération et rollback

  • [ ] Manifeste connu-bon disponible pour rollback immédiat
  • [ ] Capacité à suspendre/reprendre vérifiée
  • [ ] Nettoyage des Jobs ad hoc ou en échec effectué

Signaux et actions (exemples)

SignalInterprétationAction suivante
LAST SCHEDULE n'avance pasProblème de contrôleur/horaireVérifier la santé du contrôleur ; revoir startingDeadlineSeconds
Nombreux Jobs concurrentsChevauchement autoriséconcurrencyPolicy: Forbid ou Replace
ImagePullBackOffRegistre/policy de pullVérifier secrets ; IfNotPresent pour tags immuables
Forbidden dans les logsManque RBACServiceAccount ; Role/Binding minimal
Jobs sans finReprises non bornéesbackoffLimit + activeDeadlineSeconds

Conclusion

Les CronJobs sont fiables lorsqu'ils sont configurés avec méthode. L'approche la plus sûre consiste à inventorier les versions et champs disponibles, empêcher les chevauchements par défaut, borner les reprises et les délais, et régler la rétention pour conserver un historique utile sans l'encombrement. Validez chaque changement avec le dry-run côté serveur et un job ponctuel avant d'activer l'horaire, et conservez un plan de rollback simple en gardant des manifestes connus-bons. Avec ces pratiques et la checklist ci-dessus, vous réduisez les surprises opérationnelles et gardez des tâches récurrentes prévisibles.

Score de qualité de l’article

Utilité pour le lecteur 97%
  • check_circle Guide prêt à lire
  • check_circle Exemples pratiques inclus
  • check_circle URL d’article optimisée pour le SEO