## Introduction

Les CronJobs Kubernetes exécutent des Pods de courte durée pour effectuer des travaux planifiés. Contrairement aux Deployments de longue durée, ces Pods échouent souvent silencieusement entre deux exécutions. Les erreurs de configuration réseau sont une cause principale : résolution DNS, Services et ports du cluster, NetworkPolicies, ou contrôles de sortie (egress) au niveau des nœuds ou du cloud. Comme les CronJobs sont éphémères, il est plus difficile de les surprendre en flagrant délit.

Ce guide montre aux praticiens comment dépanner le réseau des CronJobs avec un rayon d'impact minimal. Vous allez inventorier l'environnement, créer un parcours diagnostique sûr, exécuter des tests ciblés pour le DNS et les ports, vérifier les résultats et récupérer proprement si un changement tourne mal. Tout est conçu pour être pratique et reproductible.

## Inventaire des versions et de l'environnement

Avant de modifier quoi que ce soit, collectez les faits. Cela évite les suppositions et aide à trier au bon niveau.

Prérequis :

- Accès kubectl au cluster et aux espaces de noms concernés

- Capacité de créer un espace de noms temporaire et d'appliquer des manifestes

- Familiarité de base avec les concepts CronJob, Job, Pod

Commandes d'inventaire :

- Identifier les versions de Kubernetes et kubectl :

kubectl version --short 

- Lister les nœuds et indices CNI (les étiquettes du fournisseur peuvent indiquer le CNI et le mode réseau) :

 kubectl get nodes -o wide 

- Confirmer la présence de CoreDNS et noter sa version d'image :

 kubectl -n kube-system get deploy coredns -o yaml | grep -i image 

- Vérifier si NetworkPolicy est appliqué (Calico, Cilium, etc. étiquettent généralement leurs composants) :

 kubectl get pods -A | grep -Ei "calico|cilium|weave|ovn|antrea" 

- Noter les espaces de noms et les CronJobs existants :

 kubectl get ns
kubectl get cronjobs -A 
 Pour chaque CronJob cible, capturez sa spécification comme sauvegarde avant toute modification :

kubectl -n VOTRE_NS get cronjob VOTRE_CRON -o yaml > VOTRE_CRON.backup.yaml 
 Enregistrez les éléments suivants :

- Version de Kubernetes et localisation cloud/on-prem

- Version de CoreDNS

- Présence de contrôleurs NetworkPolicy

- Contrôle de la sortie sortante : NetworkPolicy, pare-feu nœud, ou groupes de sécurité cloud

## Parcours de configuration sûr

Utilisez un pilote étroit et mesurable pour observer les résultats sans impacter les charges de production. Les étapes ci-dessous créent un parcours diagnostique à faible risque.

- Créez un espace de noms de test isolé :

kubectl create ns jobs-test 

- Créez un CronJob de sondage minimal avec des étiquettes explicites et des politiques conservatrices. Cet exemple construit effectue des recherches DNS, une requête HTTPS externe, et une sonde de port vers un nom de Service. Ajustez les cibles selon votre environnement.

 Manifeste d'exemple :

apiVersion: batch/v1
kind: CronJob
metadata:
 name: net-check
 namespace: jobs-test
spec:
 schedule: "*/10 * * * *"
 concurrencyPolicy: Forbid
 startingDeadlineSeconds: 60
 successfulJobsHistoryLimit: 1
 failedJobsHistoryLimit: 1
 jobTemplate:
 spec:
 backoffLimit: 0
 template:
 metadata:
 labels:
 app: net-check
 spec:
 restartPolicy: Never
 containers:
 - name: busybox
 image: busybox:1.36
 command: ["sh","-lc
t args:
 - |
 set -eu
 echo "Test DNS..."
 nslookup kubernetes.default.svc.cluster.local || exit 12
 nslookup example.com || exit 13
 echo "Test HTTP..."
 wget -q --spider --timeout=5 https://example.com || exit 14
 echo "Test de port vers un Service..."
 nc -vz -w5 my-service.my-namespace.svc.cluster.local 5432 || true
 echo "Tous les tests tentés" 
 Notes :

- L'image est choisie pour sa simplicité. Si une commande manque dans votre image de base, changez d'outils ou lancez des diagnostics ad-hoc (voir ci-dessous).

- Le test de port utilise un nom de Service et un port hypothétiques. Remplacez par une cible réelle dans le cluster (par exemple postgres.database.svc.cluster.local 5432 ).

- backoffLimit: 0 empêche les relances automatiques qui pollueraient les logs.

- concurrencyPolicy: Forbid évite les exécutions chevauchantes lors de tests répétés.

- Ajoutez optionnellement une NetworkPolicy ciblée pour prouver ou infirmer les hypothèses DNS/sortie. Commencez étroit, puis élargissez. Cet exemple autorise le DNS vers CoreDNS (par espace de noms) et le TCP/443 sortant vers Internet. Restreignez ipBlock à vos vrais CIDR de sortie quand possible.

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
 name: allow-dns-and-https
 namespace: jobs-test
spec:
 podSelector:
 matchLabels:
 app: net-check
 policyTypes:
 - Egress
 egress:
 - to:
 - namespaceSelector:
 matchLabels:
 kubernetes.io/metadata.name: kube-system
 ports:
 - protocol: UDP
 port: 53
 - protocol: TCP
 port: 53
 - to:
 - ipBlock:
 cidr: 0.0.0.0/0
 ports:
 - protocol: TCP
 port: 443 

- Appliquez et lancez un Job unique basé sur le modèle du CronJob pour ne pas attendre la planification :

 kubectl -n jobs-test apply -f net-check.yaml
kubectl -n jobs-test create job --from=cronjob/net-check net-check-now 

- Observez la sortie et le code de sortie :

 kubectl -n jobs-test logs job/net-check-now
kubectl -n jobs-test get job net-check-now -o jsonpath='{.status.succeeded}{"\n"}' 

- Pour une sonde interactive, lancez un Pod diagnostique ad-hoc et testez la résolution de noms et la connectivité dans le cluster :

 kubectl -n jobs-test run diag --rm -it --image=busybox:1.36 --restart=Never -- sh 
 À l'intérieur du shell :

cat /etc/resolv.conf
nslookup kubernetes.default.svc.cluster.local
nslookup example.com
wget -q --spider --timeout=5 https://example.com
nc -vz -w5 my-service.my-namespace.svc.cluster.local 5432 

## Vérification et diagnostics

 Interprétez ce que vous voyez avec une séquence de vérifications ciblées. Ne changez qu'une variable à la fois.

### 1. Confirmer que le Job a réellement démarré

Attendu en cas de succès : status.succeeded=1 , pas de dépassement de backoff, phase du Pod à Succeeded.

kubectl -n jobs-test get jobs
kubectl -n jobs-test describe job net-check-now 

### 2. Vérifier les événements et logs du Pod

 Cherchez les timeouts, connexions refusées, ou erreurs de résolution de nom.

kubectl -n jobs-test get pods -l job-name=net-check-now
kubectl -n jobs-test describe pod NOM_DU_POD
kubectl -n jobs-test logs NOM_DU_POD 

### 3. Vérifications DNS

 Attendu : peu ou pas de lignes SERVFAIL ou timeout corrélées à l'heure de démarrage de votre Job.

- Inspecter la configuration du résolveur depuis un Pod similaire :

kubectl -n jobs-test exec -it DEPLOYMENT_OU_POD -- cat /etc/resolv.conf 

- Le ndots=5 typique signifie qu'un nom court comme example.com déclenche plusieurs recherches dans le chemin de recherche d'abord. Utilisez un point final pour les noms absolus ( example.com. ) ou des FQDN complets pour éviter les délais du chemin de recherche dans les Pods de courte durée.

- Vérifier la santé de CoreDNS et les erreurs de requête :

 kubectl -n kube-system logs deploy/coredns --tail=200 | grep -Ei "timeout|servfail|refused|dns" || true 

### 4. Vérifications Service et Endpoints (cibles dans le cluster)

 Attendu : le Service a au moins un endpoint. Si les endpoints sont vides, les Pods de support ne sont pas prêts ou les sélecteurs sont incorrects.

kubectl -n mon-namespace get svc mon-service -o wide
kubectl -n mon-namespace get endpoints mon-service -o wide 

### 5. Vérifications NetworkPolicy

 Attendu : s'il y a une politique de refus par défaut en sortie, vous devez autoriser explicitement le DNS et les destinations requises.

- Lister les politiques dans l'espace de noms du CronJob et l'espace de noms cible :

kubectl -n jobs-test get networkpolicy
kubectl -n mon-namespace get networkpolicy 

- Examiner les règles qui pourraient sélectionner les Pods du CronJob par étiquette ou espace de noms :

 kubectl -n jobs-test describe networkpolicy NOM 

### 6. Sortie sortante et pare-feux nœud ou cloud

 Attendu : les nœuds peuvent atteindre les adresses externes requises sur les ports nécessaires.

- Si le DNS fonctionne mais que HTTPS vers Internet échoue, vérifiez si votre environnement restreint la sortie :

- Cloud : vérifiez que le groupe de sécurité du nœud ou les règles de pare-feu autorisent le TCP/443 et UDP/TCP/53 sortants.

- On-prem : confirmez que les pare-feux nœuds autorisent UDP/TCP/53 vers CoreDNS et les ports externes requis, et que le NAT est disponible.

### 7. Santé de kube-proxy et routage

Attendu : pas d'erreurs répétées de synchronisation ou iptables/ipvs au moment de l'exécution du Job.

- Si un Service ClusterIP est inaccessible mais que les endpoints existent, le problème peut venir de kube-proxy ou du routage nœud. Vérifiez les logs kube-proxy pour erreurs (espace de noms généralement kube-system) :

kubectl -n kube-system logs -l k8s-app=kube-proxy --tail=200 

### Symptômes courants, causes probables, et quoi vérifier

 Symptôme ou chaîne de log Cause probable Quoi vérifier 
 no such host Échec DNS ou sortie DNS bloquée nslookup dans le Pod ; logs CoreDNS ; NetworkPolicy pour UDP/TCP 53 
 i/o timeout Sortie bloquée ou endpoint distant inaccessible Pare-feu cloud/nœud ; règles ipBlock ; alternative traceroute (curl/wget -m) 
 connection refused Port cible fermé ou mauvais Service/port Service .spec.ports, Endpoints, listener de l'application cible 
 Endpoints vides Sélecteurs incompatibles ou Pods pas Ready Sélecteur Service ; étiquettes Pod ; readiness gates 
 BackoffLimitExceeded Job n'a pas réussi dans les relances Défaillance réseau sous-jacente ; timeout trop court dans le script 

### Sorties attendues (exemples construits)

- Succès DNS :

 nslookup example.com
Server: 10.96.0.10
Address: 10.96.0.10:53
Name: example.com
Address: 93.184.216.34 

- Succès HTTPS :

 wget -q --spider --timeout=5 https://example.com retourne le code de sortie 0 

- Sonde de port Service (hypothétique) :

 nc -vz -w5 postgres.database.svc.cluster.local 5432 affiche succeeded ou timeout si bloqué 

### Resserrer ou élargir la portée en toute sécurité

- Si le DNS échoue, autorisez d'abord seulement UDP/TCP 53 vers kube-system (CoreDNS). N'ouvrez pas 0.0.0.0/0 tant que vous n'avez pas prouvé que c'est nécessaire.

- Si le HTTPS externe est requis, autorisez seulement les CIDR ou noms d'hôtes connus via un proxy si disponible.

- Étiquetez toujours le template de Pod de votre CronJob (par exemple app: net-check ) pour que les NetworkPolicies puissent cibler précisément.

## Modes de défaillance et récupération

 Préparez des sorties sûres pendant les tests et le déploiement.

### 1. Mettre en pause ou arrêter les exécutions rapidement

- Suspendre un CronJob pour empêcher de nouveaux Jobs pendant l'investigation :

kubectl -n jobs-test patch cronjob net-check -p '{"spec": {"suspend": true}}' 

- Supprimer les Jobs en attente créés par la planification :

 kubectl -n jobs-test delete job -l job-name=net-check 

### 2. Restaurer les manifestes

- Restaurer un CronJob depuis la sauvegarde créée plus tôt :

 kubectl -n VOTRE_NS apply -f VOTRE_CRON.backup.yaml 

- Revenir sur la NetworkPolicy en supprimant la politique de test ou en réappliquant la version antérieure :

 kubectl -n jobs-test delete networkpolicy allow-dns-and-https 

### 3. Contenir le rayon d'impact

- Utilisez backoffLimit: 0 et des timeouts courts (par exemple wget --timeout=5 ) dans les Jobs de test pour éviter les attentes longues.

- Préférez concurrencyPolicy: Forbid pour bloquer les chevauchements qui pourraient stresser les services en aval.

### 4. Vérifier la récupération

- Après un rollback, relancez un Job unique pour confirmer que le système se comporte comme avant :

 kubectl -n jobs-test create job --from=cronjob/net-check net-check-verify
kubectl -n jobs-test logs job/net-check-verify 

- Assurez-vous que vos CronJobs de production critiques ne sont pas affectés :

 kubectl -n NS_PROD get jobs --sort-by=.metadata.creationTimestamp | tail -n 5 

### Causes racines typiques et remèdes

 Cause racine Remède minimal Étape de vérification 
 Politique de refus par défaut en sortie bloque le DNS Autoriser sortie UDP/TCP 53 vers kube-system nslookup kubernetes.default.svc.cluster.local réussit 
 Mauvais nom de Service ou port Corriger le DNS ou le port du Service et redéployer nc -vz vers le nom:port corrigé réussit 
 Sortie externe bloquée Ouvrir TCP/443 (ou port requis) vers CIDR autorisés wget --spider https://cible.exemple retourne code 0 
 Délais du chemin de recherche du résolveur Utiliser FQDN ou point final ; réduire les recherches Latence requête DNS chute ; Job sort plus tôt 
 Endpoints manquants à cause des étiquettes Corriger le sélecteur Service pour matcher les Pods kubectl get endpoints montre des adresses prêtes 

## Liste de contrôle opérationnelle

 Utilisez ceci comme runbook reproductible. Remplacez les placeholders par vos valeurs.

<div class="my-stack-md overflow-x-auto">
<table class="w-full min-w-[42rem] border-collapse text-left">
<thead><tr><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Étape</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Commande ou action</th><th scope="col" class="border border-outline-variant bg-surface-container-low px-4 py-3 text-left font-label-md font-semibold text-on-surface">Résultat attendu</th></tr></thead>
<tbody><tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Sauvegarder CronJob</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n NS get cronjob NAME -o yaml &gt; NAME.bak.yaml</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Fichier de sauvegarde créé</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Créer ns test</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl create ns jobs-test</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Espace de noms existe</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Appliquer CronJob test</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test apply -f net-check.yaml</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">CronJob créé</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Exécution unique</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test create job --from=cronjob/net-check net-check-now</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Job créé</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Obtenir logs</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test logs job/net-check-now</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifications DNS/HTTP visibles</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Inspecter événements Pod</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test describe pod POD</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Erreurs ou succès clairs</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifier logs CoreDNS</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n kube-system logs deploy/coredns --tail=200</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Pas de timeouts DNS ou SERVFAIL à l&#39;exécution</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Vérifier endpoints Service</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n NS_APP get endpoints SVC</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Endpoints non vides</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Appliquer politique sortie</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test apply -f allow-dns-and-https.yaml</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Politique en place</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Relancer et vérifier</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test create job --from=cronjob/net-check net-check-again</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Succède ou échec plus clair</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Suspendre si besoin</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test patch cronjob net-check -p &#39;{&quot;spec&quot;:{&quot;suspend&quot;:true}}&#39;</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Nouveaux Jobs arrêtés</td></tr>
<tr><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Annuler politique</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">kubectl -n jobs-test delete networkpolicy allow-dns-and-https</td><td class="border border-outline-variant px-4 py-3 align-top text-body-md text-on-surface-variant">Politique supprimée</td></tr></tbody>
</table>
</div>

## Conclusion

Les CronJobs sont particulièrement sensibles aux frictions réseau car ils sont de courte durée et planifiés. Le chemin le plus rapide vers la cause racine est de commencer par un pilote étroit et observable : inventoriez votre environnement, lancez un CronJob diagnostique sûr, et testez le DNS, les endpoints de Service, et la sortie dans cet ordre. Ajoutez ou ajustez les NetworkPolicies avec précision, préférez les noms de domaine absolus pour éviter les pièges du résolveur, et gardez le backoff et les timeouts conservateurs pendant les tests. Si un changement se retourne contre vous, suspendez le CronJob, restaurez la politique ou la spec depuis la sauvegarde, et vérifiez avec une exécution unique.

Adoptez la liste de contrôle de ce guide comme votre runbook. Chaque fois que vous ajoutez un nouveau CronJob avec des dépendances réseau, créez une variante diagnostique courte, prouvez la connectivité en isolation, et seulement alors planifiez-le. Cela maintient les incidents petits, les correctifs rapides, et les résultats prévisibles.