Aller au contenu
Conteneurs & Orchestration medium

Kind : clusters Kubernetes en conteneurs Docker

32 min de lecture

logo kind

Vous voulez tester Kubernetes sans installer une infrastructure complexe ? Kind (Kubernetes IN Docker) crée des clusters Kubernetes complets en utilisant des conteneurs Docker comme nœuds. Là où une vraie installation Kubernetes demande plusieurs machines ou VMs, Kind simule tout ça dans des conteneurs — un cluster démarre en moins de 30 secondes.

L’idée est simple : chaque “machine” de votre cluster Kubernetes est en fait un conteneur Docker. Le control-plane tourne dans un conteneur, les workers dans d’autres conteneurs. Docker gère l’isolation et le réseau entre eux. C’est parfait pour les tests CI/CD, le développement local et l’apprentissage.

Ce guide vous montre comment installer Kind, comprendre son fonctionnement interne, créer des clusters de différentes topologies, et résoudre les problèmes courants.

  • Créer un cluster jetable pour dev/CI en quelques secondes
  • Monter un cluster multi-nœuds (workers) pour simuler un environnement réel
  • Configurer un cluster multi-control-planes pour tester la haute disponibilité
  • Exposer vos applications via extraPortMappings et NodePort
  • Charger vos images Docker locales sans passer par un registry
  • Configurer une registry locale pour un workflow de développement fluide
  • Dépanner les problèmes courants

Le bon outil pour le bon usage. Kind, Minikube et k3d résolvent le même problème (Kubernetes local) mais avec des approches différentes. Comprendre ces différences vous évitera des frustrations.

CritèreKindMinikubeK3s
Cas d’usageCI/CD, tests, clusters jetablesDev local, apprentissageEdge / IoT / homelab, prod légère
Datastoreetcd (kubeadm) dans les control-planesetcd (kubeadm), HA stackedSQLite (défaut) ; embedded etcd (HA)
Multi-nœuds✅ via config YAML--nodes✅ Natif (server/agent)
HA control plane✅ multi control-planes (HAProxy)--ha (min. 3 CP) + kube-vip✅ embedded etcd (min. 3 serveurs)
Ressources≥6 GB RAM Docker (8 GB conseillé)2 CPU, 20 GB disque (défaut)Agent ~275 MiB, Server ~1.6 GiB
GPU⚠️ Pas clé en main--gpus (driver Docker)⚠️ À configurer (toolkit + plugin)
Persistance⚠️ Plutôt jetable✅ Profils persistants✅ Cluster système (systemd)
InstallationConteneurs Docker “nodes”VM ou conteneur selon driverBinaire + service (Linux)

Pourquoi choisir Kind ?

Kind a été créé par l’équipe Kubernetes elle-même pour tester Kubernetes. C’est l’outil de référence dans les pipelines CI du projet Kubernetes. Cette origine explique ses forces :

  • Reproductibilité : Même comportement en local et en CI
  • Conformance : Kubernetes vanilla, pas de modifications
  • Multi-topologies : Testez des scénarios réalistes (HA, multi-workers)
  • Légèreté : Pas de VM, pas d’hyperviseur, juste Docker

Quand éviter Kind ?

  • GPU : Kind ne peut pas accéder aux GPU de l’hôte (limitation des conteneurs). Utilisez Minikube avec le driver Docker ou VM.
  • Isolation forte : Les conteneurs partagent le noyau de l’hôte. Pour une isolation VM complète, préférez Minikube avec VirtualBox/KVM.
  • Interface graphique : Kind est CLI-only. Minikube a un dashboard intégré.

Comprendre comment Kind fonctionne vous aidera à diagnostiquer les problèmes et à configurer correctement vos clusters.

Dans un vrai cluster Kubernetes, chaque nœud est une machine (physique ou VM) avec son propre système d’exploitation, son kubelet, son runtime de conteneurs. Kind reproduit cette architecture mais remplace les machines par des conteneurs Docker.

Architecture Kind : nœuds Kubernetes dans des conteneurs Docker

Quand vous créez un cluster Kind, voici ce qui se passe :

  1. Docker crée un conteneur basé sur l’image kindest/node. Cette image contient un système Linux complet avec systemd, kubelet, containerd, et tous les composants Kubernetes pré-installés.

  2. Le conteneur démarre comme une “machine” : systemd lance kubelet, qui à son tour démarre les pods système (kube-apiserver, etcd, etc.) via containerd.

  3. C’est du “Docker in Docker” : Le conteneur Kind exécute containerd, qui lui-même gère les conteneurs de vos applications. Vos pods tournent donc dans des conteneurs… à l’intérieur d’un conteneur Docker.

  • kindnetd : Le CNI (Container Network Interface) fourni par Kind. Il gère le réseau entre les pods. C’est une implémentation simple basée sur ptp et host-local, suffisante pour les tests mais sans les fonctionnalités avancées de Calico ou Cilium.

  • Réseau Docker kind : Kind crée un réseau bridge Docker dédié. Tous les nœuds du cluster communiquent via ce réseau. C’est pourquoi vos conteneurs Kind peuvent se voir entre eux.

  • HAProxy (clusters HA) : Quand vous créez plusieurs control-planes, Kind ajoute automatiquement un conteneur HAProxy devant eux. C’est le point d’entrée unique pour l’API Kubernetes, comme un VIP dans un vrai cluster HA.

Avant d’installer Kind, vérifiez ces prérequis :

  1. Runtime conteneur : Docker, Podman ou nerdctl installé et fonctionnel

    Fenêtre de terminal
    docker --version
    # Docker version 27.5.1, build 9f9e405
  2. kubectl (optionnel mais recommandé) : Pour interagir avec le cluster

    Fenêtre de terminal
    kubectl version --client
    # Client Version: v1.32.1
  3. Ressources système : Au moins 2 GB de RAM libre par nœud

Kind est distribué sous forme de binaire unique. Plusieurs méthodes d’installation sont disponibles.

La méthode la plus fiable, surtout pour la CI.

Fenêtre de terminal
# Télécharger le binaire (AMD64)
[ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-linux-amd64
# Télécharger le binaire (ARM64)
[ $(uname -m) = aarch64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.31.0/kind-linux-arm64
# Rendre exécutable et déplacer dans le PATH
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind
# Vérifier l'installation
kind version
# kind version 0.31.0
Fenêtre de terminal
brew install kind

Commençons par le cas le plus simple : un cluster single-node. C’est suffisant pour la plupart des développements et tests unitaires.

Fenêtre de terminal
kind create cluster --name demo --wait 60s

Décortiquons cette commande :

  • --name demo : Nomme le cluster. Sans ce flag, Kind utilise “kind” par défaut. Toujours nommer vos clusters — ça évite les confusions quand vous en avez plusieurs.

  • --wait 60s : Attend que le cluster soit prêt avant de rendre la main. Indispensable en CI pour éviter les race conditions où vous tentez de déployer avant que l’API server ne réponde.

Creating cluster "demo" ...
✓ Ensuring node image (kindest/node:v1.35.0) 🖼
✓ Preparing nodes 📦
✓ Writing configuration 📜
✓ Starting control-plane 🕹️
✓ Installing CNI 🔌
✓ Installing StorageClass 💾
✓ Waiting ≤ 1m0s for control-plane = Ready ⏳
• Ready after 17s 💚
Set kubectl context to "kind-demo"

Chaque étape correspond à une action concrète :

  1. Ensuring node image : Télécharge l’image kindest/node:v1.35.0 si absente. Cette image contient Kubernetes pré-installé.

  2. Preparing nodes : Crée le conteneur Docker qui sera votre nœud.

  3. Writing configuration : Génère les certificats, le kubeconfig, etc.

  4. Starting control-plane : Démarre kubelet dans le conteneur, qui lance ensuite les pods système (API server, etcd, scheduler, controller-manager).

  5. Installing CNI : Déploie kindnetd pour le réseau entre pods.

  6. Installing StorageClass : Configure le stockage local pour les PersistentVolumes.

Vérifiez que le cluster est prêt :

Fenêtre de terminal
kubectl get nodes
NAME STATUS ROLES AGE VERSION
demo-control-plane Ready control-plane 21s v1.35.0

Le nœud est Ready : le cluster est fonctionnel.

Par défaut, Kind utilise la dernière version supportée. Pour tester la compatibilité avec une version spécifique :

Fenêtre de terminal
kind create cluster --name k8s-1-30 --image kindest/node:v1.30.0

Les images disponibles sont listées sur la page des releases GitHub. Chaque release de Kind supporte plusieurs versions de Kubernetes.

La ligne de commande suffit pour un cluster simple, mais les vrais usages nécessitent une configuration YAML. Cette configuration permet de définir des clusters reproductibles, versionnables dans Git, et partageables entre développeurs.

kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: mon-cluster

C’est équivalent à kind create cluster --name mon-cluster. L’intérêt vient quand on ajoute des options impossibles à exprimer en ligne de commande.

Un cluster single-node ne reflète pas la réalité. En production, vous avez un control-plane et plusieurs workers. Certains comportements n’apparaissent qu’avec plusieurs nœuds :

  • La répartition des pods entre workers (scheduling)
  • Les affinités/anti-affinités de pods
  • Les PodDisruptionBudgets (impossible de drainer un nœud s’il n’y en a qu’un)
  • Le comportement du réseau inter-nœuds
kind-multi-node.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: multi-node
nodes:
- role: control-plane
- role: worker
- role: worker

Ici, on déclare 3 nœuds : 1 control-plane et 2 workers. Kind va créer 3 conteneurs Docker.

Fenêtre de terminal
kind create cluster --config kind-multi-node.yaml --wait 120s
kubectl get nodes -o wide
NAME STATUS ROLES AGE VERSION INTERNAL-IP
multi-node-control-plane Ready control-plane 43s v1.35.0 172.19.0.3
multi-node-worker Ready <none> 34s v1.35.0 172.19.0.2
multi-node-worker2 Ready <none> 34s v1.35.0 172.19.0.4

Notez que les workers n’ont pas de rôle affiché (<none>) — c’est normal, seuls les control-planes ont le label node-role.kubernetes.io/control-plane.

Cluster multi-control-planes (HA) : tester la haute disponibilité

Section intitulée « Cluster multi-control-planes (HA) : tester la haute disponibilité »

En production, un seul control-plane est un SPOF (Single Point of Failure). Si l’API server tombe, plus personne ne peut interagir avec le cluster. Pour la haute disponibilité, on déploie 3 control-planes (ou 5 pour les très grands clusters).

Kind permet de simuler cette architecture :

kind-ha.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: ha-cluster
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker

Pourquoi 3 control-planes ? C’est lié à etcd, la base de données de Kubernetes. Etcd utilise un consensus (Raft) qui nécessite une majorité pour fonctionner. Avec 3 nœuds, vous tolérez 1 panne. Avec 5 nœuds, 2 pannes.

Fenêtre de terminal
kind create cluster --config kind-ha.yaml --wait 180s
Creating cluster "ha-cluster" ...
✓ Ensuring node image (kindest/node:v1.35.0) 🖼
✓ Preparing nodes 📦 📦 📦 📦
✓ Configuring the external load balancer ⚖️
✓ Writing configuration 📜
...

Remarquez l’étape “Configuring the external load balancer”. Kind ajoute automatiquement un conteneur HAProxy devant les 3 control-planes :

Fenêtre de terminal
docker ps --format "table {{.Names}}\t{{.Status}}" | grep ha-cluster
ha-cluster-external-load-balancer Up About a minute
ha-cluster-control-plane3 Up About a minute
ha-cluster-control-plane2 Up About a minute
ha-cluster-control-plane Up About a minute
ha-cluster-worker Up About a minute

Votre kubeconfig pointe vers le load balancer (pas vers un control-plane spécifique). Si un control-plane tombe, HAProxy route vers les autres.

extraPortMappings : exposer des ports vers l’hôte

Section intitulée « extraPortMappings : exposer des ports vers l’hôte »

Problème classique : Vous déployez une application dans Kind, mais comment y accéder depuis votre navigateur ?

Par défaut, les nœuds Kind sont dans un réseau Docker isolé. Votre navigateur (sur l’hôte) ne peut pas atteindre directement les services Kubernetes.

Solution : Mapper un port du conteneur Kind (le “nœud”) vers un port de votre machine hôte. C’est exactement comme le -p 8080:80 de Docker, mais appliqué au conteneur Kind.

kind-with-ports.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: with-ports
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 30080 # Port sur le nœud Kind (NodePort)
hostPort: 8080 # Port sur votre machine
listenAddress: "127.0.0.1" # Écoute uniquement en local
protocol: TCP

Comment ça fonctionne ?

  1. Vous créez un service Kubernetes de type NodePort sur le port 30080
  2. Le nœud Kind écoute sur le port 30080
  3. Docker mappe ce port vers le port 8080 de votre machine
  4. Vous accédez à http://localhost:8080

Exemple complet : Déployer nginx et y accéder

Fenêtre de terminal
# Créer le cluster avec le mapping de ports
kind create cluster --config kind-with-ports.yaml --wait 60s
# Déployer nginx
kubectl create deployment nginx --image=nginx:alpine --port=80
# Exposer sur le NodePort 30080
kubectl expose deployment nginx --type=NodePort --port=80 --target-port=80
# Forcer le NodePort à 30080 (sinon Kubernetes en choisit un aléatoire)
kubectl patch svc nginx -p '{"spec":{"ports":[{"port":80,"nodePort":30080}]}}'
# Attendre que le pod soit prêt
kubectl wait --for=condition=ready pod -l app=nginx --timeout=60s
# Tester l'accès depuis votre machine
curl http://127.0.0.1:8080

extraMounts : partager des fichiers avec les nœuds

Section intitulée « extraMounts : partager des fichiers avec les nœuds »

Cas d’usage : Vous développez une application et voulez tester sans rebuilder l’image à chaque modification. Ou vous avez des fichiers de configuration à injecter dans le cluster.

extraMounts permet de monter un dossier de votre machine dans le conteneur Kind (le “nœud”). Ce dossier sera ensuite accessible aux pods via des hostPath volumes.

kind-with-mounts.yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
name: with-mounts
nodes:
- role: control-plane
extraMounts:
- hostPath: /home/dev/mon-projet/dist
containerPath: /app
- hostPath: /home/dev/configs
containerPath: /configs
readOnly: true # Protection contre les écritures accidentelles

Attention : C’est un montage en 2 étapes :

  1. Hôte → Conteneur Kind : extraMounts fait ça
  2. Conteneur Kind → Pod : Vous devez configurer un hostPath volume dans votre manifest Kubernetes
pod-with-hostpath.yaml
apiVersion: v1
kind: Pod
metadata:
name: mon-app
spec:
containers:
- name: app
image: nginx
volumeMounts:
- name: app-files
mountPath: /usr/share/nginx/html
volumes:
- name: app-files
hostPath:
path: /app # Le chemin DANS le conteneur Kind
type: Directory

Le problème : Vous avez buildé une image Docker localement (docker build -t mon-app:v1 .), mais quand vous la déployez dans Kind, Kubernetes ne la trouve pas.

Pourquoi ? Rappelez-vous l’architecture : les nœuds Kind utilisent containerd, pas Docker. Votre image existe dans le daemon Docker de votre machine, mais les nœuds Kind ont leur propre store d’images (containerd). Ce sont deux mondes séparés.

Deux solutions : kind load (simple) ou une registry locale (recommandé pour le dev intensif).

kind load docker-image copie une image depuis Docker vers les nœuds Kind.

Fenêtre de terminal
# Builder votre image (dans Docker)
docker build -t mon-app:v1 .
# Copier vers le cluster Kind
kind load docker-image mon-app:v1 --name demo

Vérifiez que l’image est bien dans le nœud :

Fenêtre de terminal
docker exec demo-control-plane crictl images | grep mon-app
docker.io/library/mon-app v1 sha256:abc123... 50MB

Quand utiliser kind load ?

  • Vous testez une image ponctuellement
  • Vous êtes en CI et l’image est buildée une seule fois par job
  • Vous avez peu d’images à charger

Quand éviter kind load ?

  • Vous itérez rapidement (rebuild toutes les 5 minutes)
  • Vous avez beaucoup d’images ou des images lourdes
  • Vous voulez que plusieurs développeurs partagent les images

Méthode 2 : Registry locale (recommandé pour le dev)

Section intitulée « Méthode 2 : Registry locale (recommandé pour le dev) »

Le problème avec kind load : Chaque modification de code nécessite un rebuild, puis un kind load. C’est lent et fastidieux.

La solution : Une registry locale. Vous poussez vos images vers localhost:5001, et les nœuds Kind les tirent depuis cette registry. C’est le workflow standard d’un registry cloud (Docker Hub, GCR…) mais en local.

  1. Créer le script de setup :

    Ce script fait 5 choses : crée la registry, crée le cluster, configure containerd pour reconnaître la registry, connecte les réseaux, et documente la registry via une ConfigMap.

    kind-with-registry.sh
    #!/bin/sh
    set -o errexit
    # 1. Créer le conteneur registry (s'il n'existe pas déjà)
    reg_name='kind-registry'
    reg_port='5001'
    if [ "$(docker inspect -f '{{.State.Running}}' "${reg_name}" 2>/dev/null || true)" != 'true' ]; then
    docker run -d --restart=always -p "127.0.0.1:${reg_port}:5000" \
    --network bridge --name "${reg_name}" registry:2
    fi
    # 2. Créer le cluster Kind
    kind create cluster --name with-registry --wait 60s
    # 3. Configurer containerd pour résoudre localhost:5001 vers la registry
    # C'est LA partie cruciale : sans ça, les nœuds ne savent pas où est la registry
    REGISTRY_DIR="/etc/containerd/certs.d/localhost:${reg_port}"
    for node in $(kind get nodes --name with-registry); do
    docker exec "${node}" mkdir -p "${REGISTRY_DIR}"
    cat <<EOF | docker exec -i "${node}" cp /dev/stdin "${REGISTRY_DIR}/hosts.toml"
    [host."http://${reg_name}:5000"]
    EOF
    done
    # 4. Connecter la registry au réseau Kind
    # Sinon les nœuds ne peuvent pas atteindre le conteneur registry
    docker network connect "kind" "${reg_name}" 2>/dev/null || true
    # 5. Documenter la registry (convention KEP-1755)
    cat <<EOF | kubectl apply -f -
    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: local-registry-hosting
    namespace: kube-public
    data:
    localRegistryHosting.v1: |
    host: "localhost:${reg_port}"
    EOF
  2. Exécuter le script :

    Fenêtre de terminal
    chmod +x kind-with-registry.sh
    ./kind-with-registry.sh
  3. Utiliser la registry :

    Fenêtre de terminal
    # Tagger une image pour la registry locale
    docker pull nginx:alpine
    docker tag nginx:alpine localhost:5001/nginx:alpine
    # Pousser vers la registry
    docker push localhost:5001/nginx:alpine
    # Déployer dans Kind — l'image sera tirée depuis la registry locale
    kubectl create deployment nginx --image=localhost:5001/nginx:alpine
Fenêtre de terminal
kind get clusters
demo
ha-cluster
with-registry

Chaque nom correspond à un ensemble de conteneurs Docker préfixés par ce nom.

Kind configure automatiquement votre kubeconfig lors de la création d’un cluster. Mais si vous avez plusieurs clusters, vous devez basculer entre eux :

Fenêtre de terminal
# Voir tous les contextes disponibles
kubectl config get-contexts
# Basculer vers un cluster spécifique
kubectl config use-context kind-demo

Le contexte Kind suit la convention kind-{nom-du-cluster}.

Fenêtre de terminal
kind delete cluster --name demo
Deleting cluster "demo" ...
Deleted nodes: ["demo-control-plane"]

Cette commande supprime les conteneurs Docker et nettoie le kubeconfig. La suppression est idempotente : supprimer un cluster inexistant ne génère pas d’erreur. C’est pratique en CI pour un nettoyage systématique en fin de job.

Quand quelque chose ne fonctionne pas, les logs sont votre meilleur ami. Kind peut exporter tous les logs du cluster en une commande :

Fenêtre de terminal
kind export logs ./kind-logs --name demo
Exporting logs for cluster "demo" to:
./kind-logs

Vous obtenez une structure complète :

kind-logs/
├── docker-info.txt # Infos sur Docker (version, config)
├── kind-version.txt # Version de Kind
└── demo-control-plane/ # Logs par nœud
├── containerd.log # Logs du runtime conteneur
├── containers/ # Logs de chaque conteneur (pods système)
├── inspect.json # État du conteneur Docker
├── journal.log # Journal systemd complet
├── kubelet.log # Logs du kubelet (très utile !)
├── kubernetes-version.txt
└── pods/ # Logs des pods par namespace

Les fichiers les plus utiles :

  • kubelet.log : Erreurs de démarrage des pods, problèmes de scheduling
  • containerd.log : Erreurs de pull d’images
  • pods/kube-system/ : Logs des pods système (API server, etcd…)

Le problème : En production, vous utilisez des services de type LoadBalancer et Kubernetes vous attribue une IP externe. Mais Kind tourne sur votre machine — il n’y a pas de cloud provider pour provisionner des IPs.

Résultat : vos services LoadBalancer restent en EXTERNAL-IP: <pending> indéfiniment.

cloud-provider-kind est un composant qui simule un cloud provider pour Kind. Il attribue des IPs externes aux services LoadBalancer et gère le routage via des conteneurs Envoy.

Fenêtre de terminal
# Installation via Go
go install sigs.k8s.io/cloud-provider-kind@latest

Ou téléchargez le binaire depuis les releases GitHub.

  1. Démarrer cloud-provider-kind (dans un terminal séparé) :

    Fenêtre de terminal
    cloud-provider-kind

    Ce processus doit rester actif. Il surveille les services LoadBalancer et provisionne les IPs.

  2. Créer un service LoadBalancer :

    Fenêtre de terminal
    # Déployer une app de test
    kubectl create deployment echo --image=hashicorp/http-echo:0.2.3 \
    -- -text="Hello from Kind"
    # L'exposer en LoadBalancer
    kubectl expose deployment echo --type=LoadBalancer --port=80 --target-port=5678
  3. Récupérer l’IP externe :

    Fenêtre de terminal
    kubectl get svc echo
    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    echo LoadBalancer 10.96.7.228 172.19.0.4 80:30964/TCP 18s

    L’EXTERNAL-IP est maintenant attribuée — cloud-provider-kind a fait son travail.

  4. Tester l’accès :

    Fenêtre de terminal
    curl http://172.19.0.4
    # Hello from Kind

Si vous ne voulez pas dépendre de cloud-provider-kind, l’approche extraPortMappings décrite plus haut fonctionne aussi. Elle est plus simple mais moins “réaliste” (pas de vraie IP externe).

SymptômeCause probableSolution
Nœuds NotReady longtempsCNI pas encore déployéUtilisez --wait 120s, vérifiez kubectl describe node
connection refused sur l’APIAPI server pas démarrékind export logs, analysez kubelet.log
ErrImagePull pour image localeimagePullPolicy: Always + tag :latestUtilisez un tag explicite (v1) ou IfNotPresent
Port déjà utiliséConflit avec un autre servicenetstat -tlnp | grep <port>, changez le hostPort
Ingress ne marche pas (rootless)Ports < 1024 interdits en rootlesssysctl net.ipv4.ip_unprivileged_port_start=0
kind load échoueCluster inexistant ou mauvais nomVérifiez kind get clusters, utilisez --name

Quand quelque chose ne fonctionne pas, voici la séquence de debug :

Fenêtre de terminal
# 1. L'état des nœuds est-il bon ?
kubectl get nodes -o wide
kubectl describe node <nom-du-noeud> # Cherchez les "Conditions" et "Events"
# 2. Les pods système sont-ils tous Running ?
kubectl get pods -n kube-system
# Si un pod n'est pas Running, décrivez-le :
kubectl describe pod -n kube-system <nom-du-pod>
# 3. Y a-t-il des événements récents anormaux ?
kubectl get events --all-namespaces --sort-by='.lastTimestamp' | tail -20
# 4. Les conteneurs Docker Kind sont-ils sains ?
docker ps --filter "name=mon-cluster"
docker logs mon-cluster-control-plane 2>&1 | tail -50
# 5. En dernier recours : export complet des logs
kind export logs ./debug-logs --name mon-cluster
# Puis analysez kubelet.log et containerd.log

C’est souvent un problème de contexte kubectl ou de cluster supprimé :

Fenêtre de terminal
# Vérifiez le contexte actuel
kubectl config current-context
# Listez les clusters Kind existants
kind get clusters
# Si le cluster a été supprimé mais le contexte existe encore :
kubectl config delete-context kind-mon-ancien-cluster

La CI est le cas d’usage principal de Kind. Quelques recommandations :

  • Binaire de release : Téléchargez une version spécifique, pas go install latest. Vous voulez des builds reproductibles.

  • --wait obligatoire : Sans ce flag, votre script continue avant que le cluster soit prêt. Race condition garantie.

  • Nettoyage systématique : kind delete cluster en fin de job, même si les tests échouent. Utilisez after_script ou finally.

  • Export des logs en cas d’échec : Sans logs, impossible de débugger un échec en CI. Archivez-les comme artifacts.

# Exemple GitLab CI
test-kubernetes:
script:
- kind create cluster --name ci-test --wait 120s
- kubectl apply -f manifests/
- ./integration-tests.sh
after_script:
- kind export logs ./logs || true
- kind delete cluster --name ci-test || true
artifacts:
when: on_failure
paths: [logs/]
  • Registry locale : Si vous itérez fréquemment, la registry évite les kind load répétitifs. L’investissement initial (5 min) est vite rentabilisé.

  • extraMounts : Pour du hot-reload, montez votre code source dans le nœud Kind et utilisez un pod qui watch les fichiers.

  • Nommez vos clusters : Un nom par projet (kind-monprojet). Vous pouvez avoir plusieurs clusters en parallèle sans conflit.

  • Versionnez votre config : Commitez votre fichier kind-config.yaml dans le repo. Tout le monde utilise la même configuration.

  • apiServerAddress: 127.0.0.1 : Par défaut, l’API server écoute uniquement en local. Ne changez pas ça sauf si vous savez ce que vous faites.

  • Kind n’est pas pour la prod : Pas de mises à jour de sécurité in-place, pas de support, pas de SLA. C’est un outil de test.

  • Isolez les clusters : Un cluster par environnement de test. Ne mélangez pas des tests qui pourraient interférer.

  • Kind = Kubernetes IN Docker : Nœuds Kubernetes dans des conteneurs Docker
  • Installation rapide : Binaire unique, démarrage en ~20s
  • Multi-nœuds et HA : Natif via la config YAML
  • extraPortMappings : Pour exposer des NodePorts vers l’hôte
  • kind load : Charge une image locale dans le cluster
  • Registry locale : Meilleur workflow pour le dev intensif
  • kind export logs : Indispensable pour le debug
  • cloud-provider-kind : Active LoadBalancer et Ingress

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracing. Aujourd'hui, ce site ne couvre même pas mes frais d'hébergement, d'électricité, de matériel, de logiciels, mais surtout de cafés.

Un soutien régulier, même symbolique, m'aide à garder ces ressources gratuites et à continuer de produire des guides de qualité. Merci pour votre appui.