E-NO
Kubernetes 11 min de lecture

CronJobs Kubernetes : Erreurs de configuration courantes et comment les corriger

calendar_today Publié : 2026-08-01
update Dernière mise à jour : 2026-08-01
analytics Efficacité SEO : 97%
Illustration du guide technique pour « CronJobs Kubernetes : Erreurs de configuration courantes et comment les corriger ».

Les CronJobs Kubernetes sont excellents pour les tâches récurrentes telles que les exports de données nocturnes, la rotation des logs ou le nettoyage périodique. Pourtant, de petites erreurs de configuration peuvent provoquer des exécutions chevauchantes, des planifications manquées, des objets d'historique bruyants ou des jobs qui ne démarrent jamais. Ce guide montre des méthodes pratiques et sûres pour configurer, vérifier et dépanner les CronJobs avec des exemples concrets YAML et kubectl. Vous apprendrez à inventorier votre environnement, choisir des valeurs par défaut sûres, déployer les changements sans surprise, valider le comportement, récupérer après des échecs et adopter une liste de vérification qui rend les opérations reproductibles.

Inventaire des versions et de l'environnement

Avant de modifier quoi que ce soit, capturez une vue minimale mais complète de votre environnement. La version et la topologie déterminent souvent quels champs sont disponibles et comment le contrôleur se comporte.

Commandes

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

Éléments à capturer (exemples construits ; vérifiez dans votre environnement)

Élément à capturerCommande exempleValeur exemple (construite)
Version serveur Kuberneteskubectl version --shortServer Version: v1.28.3
API CronJobkubectl api-resourcesbatch/v1 CronJob
Prise en charge du fuseau horairekubectl explain cronjob.spec.timeZoneChamp présent depuis v1.27+
Espace de noms et nomn/amyns/my-cron
Santé du contrôleurkubectl get deploy -n kube-systemcontrôleur cronjob disponible

Notes

  • batch/v1 CronJob est largement disponible dans les clusters modernes. Si votre cluster est très ancien, confirmez si vous êtes sur batch/v1beta1 et planifiez une migration.
  • Le champ timeZone est disponible depuis Kubernetes 1.27+. S'il n'apparaît pas dans la sortie de kubectl explain, ne l'utilisez pas.

Parcours de configuration sûr

Cette section couvre les erreurs de configuration courantes et les choix sûrs, avec du YAML pratique que vous pouvez copier et adapter.

Erreur 1 : Autoriser les exécutions chevauchantes par défaut

Symptôme : Une nouvelle exécution démarre tandis que la précédente est encore active, causant un travail en double ou une contention de ressources.

Pourquoi cela arrive : concurrencyPolicy vaut Allow par défaut.

Choix sûr : Préférez Forbid pour les tâches idempotentes qui ne doivent pas se chevaucher. Utilisez Replace seulement 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 s'écoule alors que l'exécution précédente dort encore, la nouvelle exécution est ignorée. Vérifiez avec :

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

Erreur 2 : restartPolicy invalide dans le modèle de Job

Symptôme : Le Job ne planifie jamais de Pods ; vous voyez des erreurs de validation comme restartPolicy: Always is not allowed for Jobs.

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

Extrait de correctif :

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

Erreur 3 : Planifications manquées à cause d'un startingDeadlineSeconds trop petit

Symptôme : Le CronJob ne crée pas de Job après un incident temporaire du control-plane, une lenteur du registre d'images ou une dérive d'horloge.

Pourquoi cela arrive : startingDeadlineSeconds limite la fenêtre dans laquelle les exécutions manquées sont démarrées. Trop petit signifie que le CronJob abandonne vite. Par exemple, si un job quotidien à 02h00 rate sa fenêtre parce que l'API server était injoignable pendant 15 minutes, un startingDeadlineSeconds de 600 (10 minutes) fera que l'exécution de ce jour sera définitivement ignorée.

Choix sûr : Définissez une fenêtre raisonnable. Pour des jobs horaires, utilisez 3600 secondes (1 heure). Pour des jobs quotidiens, utilisez 86400 secondes (24 heures) ou au moins 3600.

Exemple de correctif pour un job horaire :

spec:
  schedule: "0 * * * *"
  startingDeadlineSeconds: 3600 # autoriser le rattrapage dans l'heure

Erreur 4 : Encoder le fuseau horaire dans l'expression cron ou dépendre de l'heure du nœud

Symptôme : Les jobs se déclenchent à la mauvaise heure locale ou dérivent lors des transitions d'heure d'été/hiver. Par exemple, un job planifié à 0 2 * pour 2h HNE s'exécutera à 2h UTC (21h HNE la veille) en hiver et 3h UTC (22h HNE) en été si le cluster utilise UTC.

Choix sûr :

  • Si votre cluster le prend en charge (Kubernetes 1.27+), utilisez spec.timeZone pour définir explicitement le fuseau horaire du job.
  • Sinon, planifiez en UTC et convertissez les heures métier en UTC dans votre planification.

Exemple avec timeZone :

spec:
  schedule: "0 2 * * *"
  timeZone: "America/New_York" # utiliser seulement si supporté dans votre version de cluster

Question rapide 1 sur 2

Quelle est la valeur par défaut de concurrencyPolicy dans un CronJob Kubernetes ?

Selon l'article, concurrencyPolicy est par défaut Allow, ce qui peut conduire à des exécutions qui se chevauchent.

Erreur 5 : Sur-rétention ou sous-rétention de l'historique des jobs

Symptôme : Bruit API dû à des centaines d'anciens objets Job ou, inversement, pas assez d'historique pour dépanner un échec de la semaine dernière.

Choix sûr : Ajustez les limites par CronJob selon la fréquence de planification. Pour un job quotidien, gardez 7 réussis et 10 échoués. Pour un job horaire, gardez 24 réussis et 48 échoués.

Exemple :

spec:
  successfulJobsHistoryLimit: 7
  failedJobsHistoryLimit: 10
  jobTemplate:
    spec:
      ttlSecondsAfterFinished: 86400 # optionnel dans le spec du Job quand le contrôleur TTL est activé

Erreur 6 : Relances non bornées sur Pods en échec

Symptôme : Les Pods relancent indéfiniment et chevauchent les planifications suivantes, surtout quand restartPolicy: OnFailure se combine sans backoffLimit.

Choix sûr : Limitez les relances et la durée d'exécution. Définissez backoffLimit pour plafonner les redémarrages de Pod, et activeDeadlineSeconds pour plafonner la durée totale du Job.

Exemple :

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

Avec backoffLimit: 2, un Pod en échec redémarre au maximum deux fois (3 tentatives au total). Ensuite, le Job est marqué comme échoué et le contrôleur CronJob ne relancera pas avant la prochaine planification.

Erreur 7 : Service account ou permissions manquantes

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

Choix sûr : Assignez un ServiceAccount minimal et les Role/RoleBinding requis dans le même espace de noms.

Exemple d'extrait :

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 : Utiliser Always pour l'image pull sur des images stables

Symptôme : Tirages d'images inutiles augmentent la latence ou échouent quand le registre est down.

Choix sûr : Si vous pinez sur un digest ou un tag immuable, utilisez IfNotPresent.

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

Habitudes de déploiement plus sûres

  • Exécutions de test : Utilisez kubectl create job --from=cronjob/ pour simuler un job planifié immédiatement.
  • Validation dry-run : Utilisez kubectl apply --dry-run=server -f cron.yaml pour attraper les erreurs de schéma.
  • Changement progressif : Introduisez un nouveau CronJob avec le suffixe -v2, exécutez-le en parallèle mais suspendez l'ancien (suspend: true) pour une seule fenêtre, puis finalisez le basculement.
  • Contrôle de suspension : Mettez temporairement un CronJob en pause si nécessaire :
kubectl patch cronjob my-cron -p '{"spec":{"suspend":true}}'

Vérification et diagnostics

Utilisez ces vérifications pour confirmer le comportement attendu et isoler rapidement les problèmes.

Vérifications de base

  • Confirmer la santé du contrôleur et l'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 des Pods pour le Job le plus récent :
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 l'analyse de l'expression cron et les champs :
kubectl apply --dry-run=server -f cron.yaml
kubectl explain cronjob.spec # confirmer les champs disponibles

Erreurs courantes, symptômes, vérifications et correctifs

ErreurCe que vous voyezVérifier avecCorrectif recommandé
Exécutions chevauchantes (Allow par défaut)Plusieurs Jobs actifskubectl get jobs -l cronjob-name=NAMEDéfinir concurrencyPolicy: Forbid ou Replace
restartPolicy invalideJob a 0 Pods ; erreur de validationkubectl apply --dry-run=server -fDéfinir restartPolicy: OnFailure ou Never
startingDeadlineSeconds trop petitPlanifications manquées non rattrapéeskubectl describe cronjobAugmenter startingDeadlineSeconds
Support timeZone manquantChamp ignoré ou apply échouekubectl explain cronjob.spec.timeZoneUtiliser planifications UTC ou mettre à jour le cluster
Rétention d'historique excessiveCentaines d'objets Jobkubectl get jobs -l cronjob-name=NAMEBaisser les limites successful/failed history
Relances non bornéesÉchecs longs ou chevauchantskubectl describe job ; regarder backoffDéfinir backoffLimit et activeDeadlineSeconds
RBAC manquantLogs Pod montrent erreurs Forbiddenkubectl logs ; kubectl auth can-iAttacher ServiceAccount minimal et Role

Résultats attendus pour des CronJobs sains

  • kubectl get cronjob affiche LAST SCHEDULE avec un timestamp récent qui correspond à votre planification et stratégie de fuseau horaire.
  • kubectl get jobs montre soit un job réussi pour chaque période attendue, soit un job en cours d'exécution. Les statuts passent de 0/1 à 1/1 completions.
  • kubectl logs du Pod le plus récent contiennent la sortie attendue sans boucles de crash répétées.

Question rapide 2 sur 2

Selon l'article, quel est un choix sûr pour concurrencyPolicy pour des tâches idempotentes qui ne doivent pas se chevaucher ?

L'article recommande de préférer Forbid pour les tâches idempotentes qui ne doivent pas se chevaucher.

Déclenchement manuel et backfill

Quand vous devez tester la logique sans attendre la planification :

  • Créer un job one-off à partir du modèle CronJob :
kubectl create job --from=cronjob/my-cron my-cron-adhoctest -n myns
  • Étiqueter et suivre le job ad-hoc distinctement :
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 d'échec et récupération

Comprenez ce qui échoue, comment cela se présente et comment récupérer en toute sécurité.

Indisponibilité du contrôleur ou de l'API

  • Symptôme : Aucun nouveau Job créé aux heures attendues. LAST SCHEDULE cesse d'avancer.
  • Cause : Perturbation du control-plane ou contrôleur CronJob non en cours d'exécution.
  • Récupération : Après la récupération du control-plane, assurez-vous que startingDeadlineSeconds est assez grand pour rattraper les exécutions manquées. Confirmez que le déploiement du contrôleur est sain.

Dérive d'horloge et confusion de fuseau horaire

  • Symptôme : Les planifications dérivent par rapport à l'heure métier ou à l'heure d'été/hiver.
  • Récupération : Préférez les planifications UTC ou utilisez spec.timeZone si votre version le supporte. Validez en comparant LAST SCHEDULE à une horloge UTC connue.

Erreurs de tirage d'image

  • Symptôme : ImagePullBackOff sur les Pods.
  • Récupération : Vérifiez imagePullSecrets, la disponibilité du registre, et envisagez IfNotPresent pour les images immuables. Relancez avec un job ad-hoc pour confirmer.

Échecs RBAC

  • Symptôme : Erreurs Forbidden dans les logs lors de l'accès aux ressources API.
  • Récupération : Attachez un ServiceAccount minimal, Role et RoleBinding. Testez les permissions avec :
kubectl auth can-i get configmaps --as=system:serviceaccount:myns:cron-sa -n myns

Boucles de crash de Pod ou timeouts

  • Symptôme : Les Pods redémarrent répétitivement ou dépassent les fenêtres d'exécution.
  • Récupération : Définissez backoffLimit à un nombre raisonnable, ajoutez activeDeadlineSeconds, et assurez-vous que le job est idempotent. Étudiez les logs du conteneur.

Encombrement d'historique

  • Symptôme : Grand nombre de Jobs terminés ralentissent les opérations de listage.
  • Récupération : Baissez successfulJobsHistoryLimit et failedJobsHistoryLimit ; activez ttlSecondsAfterFinished dans le modèle de Job si le contrôleur TTL est disponible.

Arrêt d'urgence et reprise

  • Suspendre temporairement la planification :
kubectl patch cronjob my-cron -n myns -p '{"spec":{"suspend":true}}'
  • Reprendre après atténuation :
kubectl patch cronjob my-cron -n myns -p '{"spec":{"suspend":false}}'

Stratégie de rollback

  • Conservez un manifeste connu-bon pour chaque CronJob. Pour faire un rollback, réappliquez le fichier précédent explicitement :
kubectl apply -f cronjob-prev.yaml
  • Si un changement de champ nécessite une recréation (rare pour les CronJobs), suspendez le job actuel, créez le remplacement avec un nom distinct, validez une exécution de test, puis supprimez l'ancien.

Vérification après récupération

  • Confirmez que LAST SCHEDULE avance à nouveau.
  • Assurez-vous qu'un seul Job s'exécute par période quand concurrencyPolicy est Forbid.
  • Vérifiez que les limites d'historique conservent assez de contexte pour la revue post-incident sans encombrement.

Liste de vérification des opérations

Utilisez cette liste concise lors des revues et avant/après les changements.

Inventaire et prérequis

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

Sécurité de la configuration

  • [ ] concurrencyPolicy défini sur Forbid (ou Replace avec justification)
  • [ ] restartPolicy défini sur OnFailure ou Never
  • [ ] startingDeadlineSeconds dimensionné à la fenêtre de tolérance attendue
  • [ ] successfulJobsHistoryLimit et failedJobsHistoryLimit ajustés
  • [ ] backoffLimit et activeDeadlineSeconds raisonnables
  • [ ] serviceAccountName défini si accès API/secret nécessaire, RBAC minimal
  • [ ] Référence d'image immuable, imagePullPolicy approprié
  • [ ] suspend défini appropriément pendant le déploiement ou les fenêtres de pause

Étapes de validation

  • [ ] kubectl apply --dry-run=server passe
  • [ ] kubectl describe cronjob montre l'heure de prochaine planification attendue
  • [ ] Job ad-hoc manuel créé et complété pour les changements nouveaux ou risqués

Observation et diagnostics

  • [ ] LAST SCHEDULE se met à jour comme attendu après le changement
  • [ ] Seul le nombre attendu de Jobs actifs par période
  • [ ] Logs des Pods inspectés pour signal de succès

Récupération et rollback

  • [ ] Manifeste connu-bon sous la main pour rollback immédiat
  • [ ] Capacité à suspendre/reprendre vérifiée
  • [ ] Nettoyage des jobs ad-hoc ou échoués effectué

Signaux de référence et actions

SignalCe qu'il suggèreAction suivante
LAST SCHEDULE n'avance pasProblème contrôleur ou planificationVérifier santé contrôleur ; revoir startingDeadlineSeconds
Plusieurs Jobs concurrentsChevauchement autoriséDéfinir concurrencyPolicy: Forbid ou Replace
ImagePullBackOffProblème registre ou pull policyVérifier secrets ; envisager IfNotPresent pour tags immuables
Forbidden dans logsLacune RBACAttacher ServiceAccount ; ajouter Role/Binding minimal
Jobs ne finissent jamaisRelances non bornées ou tâche longueDéfinir backoffLimit et activeDeadlineSeconds

Conclusion

Les CronJobs sont fiables quand ils sont configurés délibérément. Le parcours le plus sûr consiste à inventorier les versions et champs, adopter l'exécution non chevauchante par défaut, dimensionner les limites de relance et de délai, et définir une rétention qui garde l'historique utile sans causer d'encombrement. Validez les changements avec un dry-run côté serveur et un job one-off avant d'activer les planifications, et gardez un plan de rollback simple en conservant les manifestes connus-bons. Avec ces pratiques et la liste de vérification ci-dessus, vous pouvez réduire les surprises opérationnelles et maintenir les tâches récurrentes prévisibles.

Recherches connexes

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