
Votre application a besoin de télécharger une config avant de démarrer ? Ou de collecter ses logs vers un système centralisé ? Les init containers et les sidecars répondent à ces besoins sans modifier votre code applicatif.
Ce guide vous montre comment utiliser ces deux patterns, quand les choisir, et comment éviter les erreurs courantes.
Prérequis : concepts des Pods Kubernetes et un cluster fonctionnel.
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »- Créer un init container qui prépare des données avant le démarrage
- Configurer un sidecar qui tourne en parallèle de votre application
- Distinguer le pattern sidecar du sidecar natif Kubernetes
- Comprendre quand utiliser (et quand éviter) chaque approche
- Diagnostiquer les problèmes avec les bonnes commandes
Ce que partagent les conteneurs d’un Pod
Section intitulée « Ce que partagent les conteneurs d’un Pod »Avant d’entrer dans les détails, rappelons pourquoi init containers et sidecars sont utiles : tous les conteneurs d’un même Pod partagent :
| Ressource | Ce qui est partagé |
|---|---|
| Réseau | Même adresse IP, même espace réseau (localhost fonctionne entre conteneurs) |
| Volumes | Mêmes volumes montés selon la configuration |
| Scheduling | Même nœud, même unité de déploiement |
| Cycle de vie | Démarrent et s’arrêtent ensemble |
C’est ce partage qui rend les patterns init container et sidecar possibles et puissants.
Comprendre les init containers
Section intitulée « Comprendre les init containers »Un init container est un conteneur qui s’exécute avant les conteneurs principaux du Pod. Il doit se terminer avec succès pour que l’application démarre.
Comportement des init containers
Section intitulée « Comportement des init containers »Les init containers ont un comportement strict :
- Ils s’exécutent séquentiellement, dans l’ordre de déclaration
- Chaque init container doit réussir (exit code 0) avant le suivant
- En cas d’échec, le kubelet relance l’init container selon la
restartPolicy - Les conteneurs applicatifs ne démarrent qu’après la réussite de tous les init containers
Cas d’usage des init containers
Section intitulée « Cas d’usage des init containers »| Cas d’usage | Exemple concret |
|---|---|
| Télécharger des fichiers | Récupérer une config depuis S3 ou un dépôt Git |
| Attendre un service | Vérifier que MySQL répond avant de lancer l’app |
| Initialiser des données | Appliquer des migrations de base de données |
| Préparer le filesystem | Créer des répertoires, décompresser des archives |
Créer un init container
Section intitulée « Créer un init container »Exemple : préparer une configuration
Section intitulée « Exemple : préparer une configuration »Cet init container écrit un fichier de configuration que le conteneur principal utilise :
apiVersion: v1kind: Podmetadata: name: init-demospec: initContainers: - name: init-download image: busybox:1.36 command: ['sh', '-c', 'echo "Config chargée à $(date)" > /data/config.txt && sleep 2'] volumeMounts: - name: shared-data mountPath: /data containers: - name: app image: busybox:1.36 command: ['sh', '-c', 'cat /data/config.txt && sleep 3600'] volumeMounts: - name: shared-data mountPath: /data volumes: - name: shared-data emptyDir: {}kubectl apply -f init-container-demo.yamlObserver le démarrage
Section intitulée « Observer le démarrage »kubectl get pod init-demo -wSortie pendant l’initialisation :
NAME READY STATUS RESTARTS AGEinit-demo 0/1 Init:0/1 0 2sinit-demo 0/1 PodInitializing 0 4sinit-demo 1/1 Running 0 5sLe statut Init:0/1 indique que l’init container n’est pas encore terminé.
Vérifier que l’init a fonctionné
Section intitulée « Vérifier que l’init a fonctionné »kubectl logs init-demo -c appSortie attendue :
Config chargée à Sun Mar 22 08:44:45 UTC 2026Le conteneur principal a bien lu le fichier créé par l’init container.
Init container : attendre un service
Section intitulée « Init container : attendre un service »Un cas très courant est d’attendre qu’un service soit disponible :
apiVersion: v1kind: Podmetadata: name: webappspec: initContainers: - name: wait-for-db image: busybox:1.36 command: ['sh', '-c', 'until nc -z mysql 3306; do echo "Attente MySQL..."; sleep 2; done'] containers: - name: app image: nginx:alpineL’init container boucle jusqu’à ce que MySQL réponde sur le port 3306.
Ajouter un timeout
Section intitulée « Ajouter un timeout »Sans limite de temps, un init container peut bloquer indéfiniment :
command: ['sh', '-c', 'timeout 60 sh -c "until nc -z mysql 3306; do sleep 2; done"']Deux façons de parler de sidecar
Section intitulée « Deux façons de parler de sidecar »Il existe deux réalités qu’il faut distinguer :
Pattern sidecar (conceptuel)
Section intitulée « Pattern sidecar (conceptuel) »Historiquement, un sidecar désigne simplement un second conteneur dans
spec.containers qui accompagne le conteneur principal. C’est un pattern
d’architecture, pas une fonctionnalité Kubernetes.
spec: containers: - name: app image: myapp:1.0 - name: log-collector # Sidecar "classique" image: fluentbit:2.0Les deux conteneurs démarrent ensemble, sans ordre garanti.
Sidecar natif (fonctionnalité Kubernetes)
Section intitulée « Sidecar natif (fonctionnalité Kubernetes) »Depuis Kubernetes v1.29, une fonctionnalité dédiée permet de déclarer
des sidecars avec un cycle de vie contrôlé. Un sidecar natif est un
init container avec restartPolicy: Always.
spec: initContainers: - name: log-agent image: fluentbit:2.0 restartPolicy: Always # C'est un sidecar natif !Différences entre les deux approches
Section intitulée « Différences entre les deux approches »| Aspect | Pattern classique | Sidecar natif |
|---|---|---|
| Déclaration | spec.containers | spec.initContainers avec restartPolicy: Always |
| Ordre de démarrage | Pas garanti | Démarre avant le conteneur principal |
| Arrêt | Pas d’ordre | S’arrête après le conteneur principal |
| Redémarrage | Peut crasher le Pod | Redémarre indépendamment |
Créer un sidecar classique
Section intitulée « Créer un sidecar classique »Exemple : collecteur de logs
Section intitulée « Exemple : collecteur de logs »Le sidecar lit les logs écrits par l’application principale dans un fichier partagé :
apiVersion: v1kind: Podmetadata: name: sidecar-demospec: containers: - name: app image: busybox:1.36 command: ['sh', '-c', 'while true; do echo "$(date) - Requête traitée" >> /var/log/app.log; sleep 5; done'] volumeMounts: - name: logs mountPath: /var/log - name: log-collector image: busybox:1.36 command: ['sh', '-c', 'tail -f /var/log/app.log'] volumeMounts: - name: logs mountPath: /var/log volumes: - name: logs emptyDir: {}kubectl apply -f sidecar-demo.yamlVérifier le sidecar
Section intitulée « Vérifier le sidecar »kubectl get pod sidecar-demoSortie :
NAME READY STATUS RESTARTS AGEsidecar-demo 2/2 Running 0 15s2/2 Running confirme que les deux conteneurs tournent.
kubectl logs sidecar-demo -c log-collectorSortie :
Sun Mar 22 08:45:07 UTC 2026 - Requête traitéeSun Mar 22 08:45:12 UTC 2026 - Requête traitéeCréer un sidecar natif (v1.29+)
Section intitulée « Créer un sidecar natif (v1.29+) »Les sidecars natifs offrent un meilleur contrôle du cycle de vie :
apiVersion: v1kind: Podmetadata: name: native-sidecarspec: initContainers: - name: log-agent image: busybox:1.36 restartPolicy: Always # Sidecar natif ! command: ['sh', '-c', 'tail -f /var/log/app.log 2>/dev/null || sleep infinity'] volumeMounts: - name: logs mountPath: /var/log containers: - name: app image: busybox:1.36 command: ['sh', '-c', 'while true; do echo "$(date) - Log" >> /var/log/app.log; sleep 5; done'] volumeMounts: - name: logs mountPath: /var/log volumes: - name: logs emptyDir: {}Avantages du sidecar natif :
- Démarre avant le conteneur principal (comme un init container)
- Tourne pendant toute la vie du Pod (comme un sidecar classique)
- S’arrête proprement après le conteneur principal
- Peut redémarrer sans faire crasher le Pod entier
Quand choisir init container ou sidecar
Section intitulée « Quand choisir init container ou sidecar »Tableau de décision
Section intitulée « Tableau de décision »| Besoin | Init container | Sidecar |
|---|---|---|
| Préparer des fichiers avant démarrage | ✅ Oui | ❌ Non |
| Attendre une dépendance | ✅ Oui (avec timeout) | ⚠️ Rarement |
| Collecter des logs pendant la vie du Pod | ❌ Non | ✅ Oui |
| Proxy réseau local au Pod | ❌ Non | ✅ Oui |
| Exécuter une migration ponctuelle | ✅ Oui | ❌ Non |
| Synchroniser des fichiers en continu | ❌ Non | ✅ Oui |
| Exporter des métriques | ❌ Non | ✅ Oui |
Cas d’usage des sidecars
Section intitulée « Cas d’usage des sidecars »| Pattern | Exemple |
|---|---|
| Log collector | Fluent Bit, Filebeat → Elasticsearch/Loki |
| Proxy | Envoy, Istio pour le service mesh |
| Sync | Git-sync pour fichiers de config |
| Monitoring | Exporter des métriques Prometheus |
Quand éviter un sidecar
Section intitulée « Quand éviter un sidecar »Un sidecar n’est pas toujours la bonne solution :
| Situation | Pourquoi éviter | Alternative |
|---|---|---|
| Fonction mutualisable | Un sidecar par Pod = N instances | DaemonSet (1 par nœud) |
| Besoin uniquement au build | Pas besoin en runtime | Job CI/CD |
| Fonction indépendante du Pod | Couplage inutile | Deployment séparé |
| Logs vers stdout | Le nœud collecte déjà | Aucun sidecar nécessaire |
| Proxy cluster-wide | Duplication massive | Ingress ou service mesh |
Impact sur les ressources
Section intitulée « Impact sur les ressources »Chaque conteneur supplémentaire consomme des ressources :
- CPU et mémoire : l’init container allonge le démarrage, le sidecar consomme en continu
- I/O disque : si le sidecar écrit beaucoup (logs, métriques)
- Bande passante : si le sidecar envoie des données vers l’extérieur
Bonnes pratiques
Section intitulée « Bonnes pratiques »initContainers:- name: init-download image: busybox:1.36 resources: requests: cpu: "50m" memory: "32Mi" limits: cpu: "100m" memory: "64Mi"Déclarez aussi les resources de vos sidecars pour éviter les surprises en
production.
Combiner init containers et sidecars
Section intitulée « Combiner init containers et sidecars »Un Pod peut avoir les deux :
apiVersion: v1kind: Podmetadata: name: full-stackspec: initContainers: - name: download-config image: busybox:1.36 command: ['sh', '-c', 'echo "DB_HOST=mysql" > /config/env'] volumeMounts: - name: config mountPath: /config containers: - name: app image: busybox:1.36 command: ['sh', '-c', 'cat /config/env && while true; do echo "$(date) - Request" >> /logs/app.log; sleep 5; done'] volumeMounts: - name: config mountPath: /config - name: logs mountPath: /logs - name: log-shipper image: busybox:1.36 command: ['sh', '-c', 'tail -f /logs/app.log'] volumeMounts: - name: logs mountPath: /logs volumes: - name: config emptyDir: {} - name: logs emptyDir: {}Flux d’exécution :
download-config(init) prépare la configurationappetlog-shipperdémarrent ensemblelog-shippertransmet les logs en continu
Anti-patterns à éviter
Section intitulée « Anti-patterns à éviter »| Anti-pattern | Conséquence | Solution |
|---|---|---|
| Attendre sans timeout | Pod bloqué indéfiniment | Ajouter timeout à la commande |
| Logique métier lourde en init | Démarrage très long | Externaliser dans un Job |
| Port ouvert = service prêt | Faux positifs | Test fonctionnel léger |
| Sidecar pour fonction mutualisable | Gaspillage de ressources | DaemonSet |
| chmod/chown en init container | Symptôme de mauvaise config | Utiliser securityContext |
Oublier resources sur les sidecars | Consommation non contrôlée | Déclarer requests/limits |
| Plusieurs conteneurs = plus de couplage | Maintenance complexe | Évaluer si vraiment nécessaire |
Dépannage
Section intitulée « Dépannage »Commandes essentielles
Section intitulée « Commandes essentielles »-
Voir l’état du Pod et des conteneurs
Fenêtre de terminal kubectl get pod mon-pod -o widekubectl get pod mon-pod -o yaml | grep -A 30 "containerStatuses" -
Examiner les détails des init containers
Fenêtre de terminal kubectl describe pod mon-pod | grep -A 30 "Init Containers" -
Lire les logs d’un init container
Fenêtre de terminal kubectl logs mon-pod -c nom-init-containerkubectl logs mon-pod -c nom-init-container --previous # Si redémarré -
Lire les logs d’un sidecar
Fenêtre de terminal kubectl logs mon-pod -c nom-sidecar -
Voir les événements récents
Fenêtre de terminal kubectl get events --sort-by=.lastTimestamp | grep mon-pod
Problèmes courants
Section intitulée « Problèmes courants »| Symptôme | Cause probable | Solution |
|---|---|---|
Init:0/1 qui persiste | Init container bloqué ou en échec | Vérifier les logs : kubectl logs mon-pod -c init-xxx |
Init:CrashLoopBackOff | Commande qui échoue (exit code ≠ 0) | Corriger la commande ou l’image |
Init:ImagePullBackOff | Image introuvable | Vérifier le nom et le registry |
READY 1/2 | Un des conteneurs ne démarre pas | kubectl describe pod pour les événements |
| Sidecar natif qui ne tourne pas | restartPolicy: Always oublié | Ajouter le champ dans l’init container |
Exemple de diagnostic
Section intitulée « Exemple de diagnostic »kubectl describe pod init-demoEvents: Type Reason Age Message ---- ------ ---- ------- Normal Scheduled 1m Successfully assigned default/init-demo to node1 Normal Pulling 1m Pulling image "busybox:1.36" Normal Pulled 55s Successfully pulled image Normal Created 55s Created container init-download Normal Started 55s Started container init-download Normal Pulled 50s Container init-download completed successfully Normal Created 50s Created container app Normal Started 50s Started container appRéflexes CKAD
Section intitulée « Réflexes CKAD »En examen, voici le workflow efficace :
# 1. Créer le manifestkubectl run mypod --image=nginx --dry-run=client -o yaml > pod.yaml
# 2. Éditer pour ajouter initContainers (même niveau que containers)vim pod.yaml
# 3. Appliquerkubectl apply -f pod.yaml
# 4. Vérifier l'étatkubectl get pod mypod -w
# 5. Voir les logs de l'init containerkubectl logs mypod -c init-container-name
# 6. Voir les logs du conteneur principalkubectl logs mypod -c nginxStructure YAML minimale
Section intitulée « Structure YAML minimale »apiVersion: v1kind: Podmetadata: name: mypodspec: initContainers: # Même niveau que containers - name: init-xxx image: busybox:1.36 command: ['sh', '-c', 'echo done'] volumeMounts: - name: data mountPath: /data containers: - name: app image: nginx volumeMounts: - name: data mountPath: /data volumes: # Partagé entre tous les conteneurs - name: data emptyDir: {}À retenir
Section intitulée « À retenir »- Init container : s’exécute et se termine AVANT le conteneur principal
- Sidecar classique : conteneur dans
containers, tourne EN PARALLÈLE - Sidecar natif : init container avec
restartPolicy: Always(stable v1.33) - Les init containers s’exécutent séquentiellement, chacun doit réussir
- Les init containers ne supportent pas les probes ni lifecycle hooks
- Un port TCP ouvert ne garantit pas qu’un service est prêt
- Les conteneurs d’un Pod partagent réseau et volumes
- Chaque conteneur supplémentaire consomme des ressources
- Un sidecar qui peut être mutualisé devrait être un DaemonSet
- Commandes clés :
kubectl logs -c,kubectl describe,kubectl get events