Intro
Cette version française explique Kubernetes CronJobs backup and restore 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 CronJobs sont le battement de cœur de nombreux environnements Kubernetes : rapports quotidiens, maintenance de bases de données, purge de cache, ETL, etc. Quand le cluster change, qu'un namespace est reconstruit ou qu'une panne frappe, il faut une méthode sûre, répétable et réversible pour sauvegarder et restaurer ces plannings et leurs dépendances d'exécution. Ce guide praticien livre :
- Une sauvegarde minimale et ciblée que vous pouvez lancer dès aujourd'hui
- Une restauration réversible qui évite les exécutions en double
- Des vérifications observables, des modes de panne courants et leurs correctifs
- Des étapes de reprise après sinistre et de rollback
- Une check-list pratique à adopter telle quelle
Les exemples visent la clarté et utilisent uniquement les outils côur de Kubernetes (kubectl et manifestes simples). Lorsqu'il y a des volumes de données, nous montrons comment copier sûrement le contenu entrant et sortant.
Inventaire de version et d'environnement
Avant de toucher à la production, capturez et figez les détails de l'environnement. Cela réduit la dérive et rend la sauvegarde et la restauration répétables et auditables.
Commandes d'inventaire rapide
- Enregistrer les versions client et serveur :
kubectl version --short
- Lister les nœuds et l'OS/arch (utile pour déboguer des images) :
kubectl get nodes -o wide
- Confirmer les namespaces en portée et le plan de labels :
kubectl get ns
kubectl get cronjob -A --show-labels
- Vérifier que le groupe d'API CronJob est disponible :
kubectl api-resources | grep -i cronjob
Que consigner (exemples construits)
| Élément | Quoi enregistrer | Exemple |
|---|---|---|
| Version Kubernetes | Semver client et serveur | v1.29.3 (client), v1.28.6 (serveur) |
| Namespaces en portée | Lieux of9 vivent les CronJobs | jobs, analytics |
| Labels de sélection | Labels qui définissent le périmètre de sauvegarde | app=reporting, backup=enabled |
| Stockage et PVC | Noms de PVC et chemins de montage | report-pvc monté sur /data |
| Identités RBAC | ServiceAccounts et bindings | SA cron-runner, RoleBinding cron-runner-rb |
Astuce : stockez cet inventaire à côté de vos artefacts de sauvegarde.
Voie de configuration sûre
La voie la plus sûre commence étroite, s'inspecte facilement en local et évite les effets de bord. La séquence ci-dessous fournit des garde-fous et des commandes concrètes pour agir dab abord sur un seul namespace et une seule charge étiquetée.
0) Un CronJob étiqueté que vous pouvez cibler
Manifeste construit pour tester le processus de bout en bout, incluant des labels pour le ciblage, un ServiceAccount, des limites d'historique et un montage PVC pour une sauvegarde de données optionnelle.
apiVersion: batch/v1
kind: CronJob
metadata:
name: report-daily
namespace: jobs
labels:
app: reporting
backup: enabled
spec:
schedule: '0 2 * * *' # 02:00 quotidien (utiliser UTC pour éviter les surprises)
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
suspend: false
jobTemplate:
spec:
backoffLimit: 1
template:
spec:
serviceAccountName: cron-runner
restartPolicy: Never
containers:
- name: report
image: ghcr.io/example/report:1.2.3 # exemple construit
args: ['--generate']
envFrom:
- secretRef:
name: report-secrets
volumeMounts:
- name: report-data
mountPath: /data
volumes:
- name: report-data
persistentVolumeClaim:
claimName: report-pvc
Appliquez-le dab abord dans un namespace non critique :
kubectl apply -f report-daily.cronjob.yaml
1) Sauvegarder les spécifications des CronJobs (YAML)
Sauvegardez seulement le nécessaire, en utilisant des labels pour le périmètre. Remplacez le namespace et les labels par les vôtres.
# Répertoire de sauvegarde
mkdir -p backups/jobs
# CronJobs (ciblés par label)
kubectl get cronjob -n jobs -l backup=enabled -o yaml > backups/jobs/cronjobs.yaml
# Optionnel : ServiceAccounts, Roles, RoleBindings utilisés par les CronJobs
kubectl get sa, role, rolebinding -n jobs -l app=reporting -o yaml > backups/jobs/rbac.yaml
# ConfigMaps et Secrets référencés par les CronJobs
kubectl get configmap, secret -n jobs -l app=reporting -o yaml > backups/jobs/config-secrets.yaml
Notes :
- Les Secrets sont encodés en base64 dans le YAML. Traitez les fichiers de sauvegarde en sécurité (chiffrement au repos et accès restreint).
- Vous avez rarement besoin de sauvegarder les Jobs créés par les CronJobs : ils sont éphémères. Garder un YAML de Job récent peut toutefois aider lors des tests.
2) Sauvegarder le contenu des PVC (optionnel)
Si votre CronJob écrit dans un PVC, capturez une archive ponctuelle. Le Pod ci-dessous monte le PVC et streame un tarball vers votre poste. Remplacez claimName, namespace et chemins pour votre cas.
# pvc-reader.yaml (exemple construit)
apiVersion: v1
kind: Pod
metadata:
name: pvc-reader
namespace: jobs
labels:
app: reporting
spec:
restartPolicy: Never
containers:
- name: reader
image: busybox:1.36
command: ['sleep', '3600']
volumeMounts:
- name: report-data
mountPath: /data
volumes:
- name: report-data
persistentVolumeClaim:
claimName: report-pvc
Lancer la sauvegarde :
kubectl apply -f pvc-reader.yaml
kubectl wait --for=condition=Ready pod/pvc-reader -n jobs --timeout=60s
# Stream d'une archive tar vers le disque local
kubectl exec -n jobs pvc-reader -- tar -C /data -cf - . > backups/jobs/report-pvc-$(date +%F).tar
kubectl delete pod pvc-reader -n jobs --wait=true
3) Séquence de restauration avec garde-fous
Lors de la restauration, évitez les exécutions en double en suspendant temporairement les CronJobs.
# Créer ou vérifier l'existence du namespace cible
kubectl create namespace jobs 2>/dev/null || true
# 3.1 Dry-run pour valider les manifestes par l'API du cluster
kubectl apply --server-side --dry-run=server -f backups/jobs/rbac.yaml
kubectl apply --server-side --dry-run=server -f backups/jobs/config-secrets.yaml
kubectl apply --server-side --dry-run=server -f backups/jobs/cronjobs.yaml
# 3.2 Appliquer d'abord RBAC et configuration
kubectl apply -f backups/jobs/rbac.yaml
kubectl apply -f backups/jobs/config-secrets.yaml
# 3.3 Appliquer les CronJobs, puis les suspendre immédiatement
kubectl apply -f backups/jobs/cronjobs.yaml
kubectl patch cronjob -n jobs -l backup=enabled -p '{\"spec\":{\"suspend\":true}}'
Si vous avez sauvegardé des données PVC, restaurez-les avant de reprendre les plannings :
# pvc-writer.yaml (exemple construit)
apiVersion: v1
kind: Pod
metadata:
name: pvc-writer
namespace: jobs
spec:
restartPolicy: Never
containers:
- name: writer
image: busybox:1.36
command: ['sleep', '3600']
volumeMounts:
- name: report-data
mountPath: /data
volumes:
- name: report-data
persistentVolumeClaim:
claimName: report-pvc
kubectl apply -f pvc-writer.yaml
kubectl wait --for=condition=Ready pod/pvc-writer -n jobs --timeout=60s
# Extraction de l'archive locale dans le PVC monté
cat backups/jobs/report-pvc-*.tar | kubectl exec -i -n jobs pvc-writer -- tar -C /data -xpf -
kubectl delete pod pvc-writer -n jobs --wait=true
Ne reprenez les plannings qu'après la remise en place des données et la validation (voir section suivante).
Vérification et diagnostics
L'objectif est de prouver que chaque CronJob peut s'exécuter une fois à la demande et que la planification fonctionnera à la reprise.
1) Contrôler objets et état
# Confirmer l'existence et la suspension des CronJobs
kubectl get cronjob -n jobs -l backup=enabled -o wide
# Inspecter un CronJob en détail
kubectl describe cronjob -n jobs report-daily
Attendus :
- CronJobs présents dans le bon namespace
- concurrencyPolicy, limites d'historique et serviceAccountName conformes
- suspend à true (temporaire)
2) Lancer un Job ad hoc à partir du template de CronJob
# Créer un job à usage unique d'après le template du CronJob
kubectl create job -n jobs run-once-$(date +%s) --from=cronjob/report-daily
# Observer le statut et les logs
kubectl get jobs -n jobs -o wide
# Récupérer le nom du job et suivre les logs du pod créé
JOB=$(kubectl get jobs -n jobs -o jsonpath='{.items[0].metadata.name}')
POD=$(kubectl get pod -n jobs -l job-name=$JOB -o jsonpath='{.items[0].metadata.name}')
kubectl logs -n jobs $POD -f
Critères de succès :
- Le Job passe en statut Succeeded
- Les logs montrent le résultat attendu
- Si un PVC est utilisé, les sorties apparaissent au chemin monté
3) Inspecter les événements pour des problèmes de scheduling
kubectl get events -n jobs --sort-by=.lastTimestamp | tail -n 20
Cherchez les messages de plannings manqués, backoff ou erreurs de permission.
4) Reprendre les plannings une fois validés
kubectl patch cronjob/report-daily -n jobs -p '{\"spec\":{\"suspend\":false}}'
# Ou reprendre tous les CronJobs étiquetés
kubectl patch cronjob -n jobs -l backup=enabled -p '{\"spec\":{\"suspend\":false}}'
Vérifiez que la prochaine exécution planifiée est dans le futur et que le contrôleur rapporte Active=0 à l'arrêt.
Modes de panne et récupération
Les incidents de restauration tombent souvent dans quelques catégories. Faites correspondre le symptôme, appliquez le correctif rapide, puis revérifiez.
| Symptôme | Cause probable | Correctif rapide |
|---|---|---|
| Échec ImagePull | Tag d'image absent du registre cible | Verrouiller sur un tag ou digest connu, mettre à jour l'image et réappliquer |
| CrashLoopBackOff ou permissions | Secrets ou ConfigMaps manquants/incorrects | Réappliquer config-secrets.yaml, vérifier noms et clés |
| Interdictions RBAC | ServiceAccount ou RoleBinding manquant | Réappliquer rbac.yaml, vérifier serviceAccountName du template |
| Exécutions en double | Reprise des schedules avant données/contrôles d'idempotence | Suspendre, nettoyer les Jobs dupliqués, restaurer les données puis reprendre |
| Jobs qui ne tournent jamais | CronJobs restés suspendus | Patcher suspend=false et vérifier la prochaine exécution |
| PVC vide après restauration | Restauration ignorée ou chemin erroné | Réexécuter l'extraction tar au bon mountPath, vérifier avec kubectl exec ls |
| Trop d'historique de Jobs | Limites d'historique trop hautes | Régler successfulJobsHistoryLimit et failedJobsHistoryLimit |
Garde-fous supplémentaires :
- Utilisez l'UTC dans vos expressions de schedule pour éviter les surprises multi-clusters.
- Définissez startingDeadlineSeconds si vous souhaitez exécuter les jobs manqués au redémarrage du contrôleur ; fixez une valeur raisonnable ou omettez si non souhaité.
- Préférez concurrencyPolicy=Forbid pour les te2ches sensibles à l'idempotence.
Check-list d'exploitation
Adoptez cette check-list comme runbook pour chaque namespace. Vous pouvez l'automatiser avec Bash, Python, ou l'intégrer dans GitLab CI/CD et construire des images Docker ad hoc si besoin.
Inventaire
- [ ] kubectl version --short sauvegardé
- [ ] Namespaces, labels, PVCs consignés
- [ ] ServiceAccounts et Roles identifiés
Sauvegarde (commandes construites)
- [ ] kubectl get cronjob -n <ns> -l backup=enabled -o yaml > cronjobs.yaml
- [ ] kubectl get sa, role, rolebinding -n <ns> -l <labels> -o yaml > rbac.yaml
- [ ] kubectl get configmap, secret -n <ns> -l <labels> -o yaml > config-secrets.yaml
- [ ] Si PVC : déployer pvc-reader, streamer tar vers backups/
- [ ] Stocker les artefacts en sécurité (chiffré, accès restreint)
Restauration
- [ ] kubectl create namespace <ns> (si besoin)
- [ ] kubectl apply --server-side --dry-run=server -f rbac.yaml
- [ ] kubectl apply --server-side --dry-run=server -f config-secrets.yaml
- [ ] kubectl apply --server-side --dry-run=server -f cronjobs.yaml
- [ ] kubectl apply -f rbac.yaml, config-secrets.yaml, cronjobs.yaml
- [ ] kubectl patch cronjob -n <ns> -l backup=enabled -p '{\"spec\":{\"suspend\":true}}'
- [ ] Si PVC : déployer pvc-writer et extraire le tar dans /data
Validation
- [ ] kubectl get/describe cronjob montrent les réglages attendus
- [ ] Lancer : kubectl create job --from=cronjob/<name>
- [ ] Contrôler logs et artefacts ; inspecter les événements
Reprise
- [ ] kubectl patch cronjob/<name> -p '{\"spec\":{\"suspend\":false}}'
- [ ] Confirmer la prochaine échéance, aucun Active inattendu
Rollback / Récupération
- [ ] En cas de souci : suspendre immédiatement
- [ ] Réappliquer l'ancien cronjobs.yaml
- [ ] Supprimer les Jobs non désirés : kubectl delete job <name>
- [ ] Restauration des Secrets/ConfigMaps ou données PVC si besoin
Conclusion
Vous disposez maintenant d'une voie pratique et testée pour la sauvegarde et la restauration des CronJobs Kubernetes :
- Démarrez petit : un namespace, un CronJob étiqueté, et validez le flux de bout en bout.
- Sauvegardez le bon périmètre : spécifications de CronJobs, RBAC, configuration, et contenus PVC si nécessaire.
- Restaurez avec des garde-fous : appliquez dab abord les configs, suspendez les plannings, validez par un Job ad hoc, puis reprenez.
- Anticipez et corrigez rapidement les modes de panne courants et gardez un chemin de rollback court et clair.
Poursuivez en automatisant ces étapes pour chaque namespace, en standardisant vos labels (par exemple backup=enabled) et en planifiant des restaurations de test périodiques. L'association d'un périmètre étroit, d'une validation explicite et de changements réversibles réduit le rétravail et rend les opérations de CronJobs prédictibles, même en incident.
Annexe : Rappel rapide du périmètre de sauvegarde
| Ressource | Pourquoi la sauvegarder | Exemple de commande (construit) |
|---|---|---|
| CronJobs | Définit la planification et le template de job | kubectl get cronjob -n jobs -l backup=enabled -o yaml > cronjobs.yaml |
| RBAC (SA/Role/RoleBinding) | Donne les permissions d'exécution | kubectl get sa, role, rolebinding -n jobs -l app=reporting -o yaml > rbac.yaml |
| ConfigMaps/Secrets | Configuration runtime et secrets | kubectl get configmap, secret -n jobs -l app=reporting -o yaml > config-secrets.yaml |
| Données PVC (optionnel) | Entrées/sorties nécessaires aux jobs | kubectl exec pvc-reader -- tar -C /data -cf - . > report-pvc.tar |