
Kubespray déploie des clusters Kubernetes en utilisant Ansible. Ce guide construit un lab KVM reproductible servant de base à des déploiements plus robustes. Contrairement à kubeadm qui nécessite des commandes manuelles sur chaque nœud, Kubespray automatise tout depuis votre poste de travail.
Kubespray vs autres solutions
Section intitulée « Kubespray vs autres solutions »| Critère | Kubespray | kubeadm | k0s | k3s | RKE2 |
|---|---|---|---|---|---|
| Type | Playbooks Ansible | Bootstrap tool | Distribution | Distribution | Distribution |
| Orientation | Prod, multi-cloud | Standard upstream | Edge, prod, CI | Edge, IoT, dev | Enterprise, sécurité |
| Installation | Ansible | Commandes | k0sctl (YAML) | Script unique | Script |
| CNI défaut | Configurable | Aucun | kube-router | Flannel | Canal |
| HA native | ✅ Ansible | Manuel | ✅ Multi-controller | ✅ Multi-server | ✅ Intégrée |
| Profil CIS | Selon config | Manuel | Manuel | Manuel | ✅ Intégré |
| Cas d’usage | Prod automatisée | Bare metal, formation | Edge, CI/CD, prod | Edge, IoT, dev | Conformité, prod |
Ce que vous allez apprendre
Section intitulée « Ce que vous allez apprendre »À la fin de ce guide, vous saurez :
- Provisionner des VMs KVM configurées via cloud-init pour un cluster Kubernetes
- Préparer l’environnement Kubespray avec les bonnes versions d’Ansible et dépendances
- Créer un inventaire personnalisé définissant la topologie du cluster
- Déployer un cluster complet avec Calico, containerd et CoreDNS en une seule commande
- Valider que tous les composants fonctionnent correctement
- Personnaliser les options (CNI, runtime, addons) selon vos besoins
Prérequis
Section intitulée « Prérequis »Ressources matérielles
Section intitulée « Ressources matérielles »Kubespray déploie les mêmes composants que kubeadm mais automatise la configuration. Les besoins sont donc identiques :
| Rôle | CPU | RAM (min) | RAM (recommandé) | Disque | Quantité |
|---|---|---|---|---|---|
| Control plane | 2 vCPU | 2 Go | 2 Go | 20 Go | 1 (ou 3+ pour HA) |
| Worker | 2 vCPU | 1 Go | 2 Go | 20 Go | 2+ |
| Poste Ansible | 1 vCPU | 1 Go | 1 Go | 5 Go | Votre machine locale |
Le minimum Kubespray pour les workers est 1 Go, mais ce guide recommande 2 Go pour éviter les problèmes lors du téléchargement parallèle des images.
Logiciels requis
Section intitulée « Logiciels requis »Sur votre poste de travail (machine de contrôle Ansible) :
- Python 3.10+ avec pip
- Git pour cloner le repository Kubespray
- SSH avec une clé configurée (les VMs doivent être accessibles sans mot de passe)
Sur les VMs cibles :
- Ubuntu 24.04 ou Rocky Linux 9 (distribution supportée par Kubespray)
- Python 3 installé (requis par Ansible)
- Accès sudo sans mot de passe pour l’utilisateur SSH
- Accès Internet pour télécharger images et binaires (sauf configuration offline dédiée)
Versions validées dans ce guide
Section intitulée « Versions validées dans ce guide »Ce guide a été validé avec les versions suivantes :
| Composant | Version |
|---|---|
| Kubespray | v2.26.0 |
| Kubernetes | v1.30.4 |
| Ansible | core 2.16.x |
| CNI | Calico (plugin par défaut) |
Création des machines virtuelles
Section intitulée « Création des machines virtuelles »Architecture cible
Section intitulée « Architecture cible »Nous allons créer un cluster avec 1 control plane et 2 workers sur le réseau libvirt par défaut :
Préparer l’image cloud Ubuntu 24.04
Section intitulée « Préparer l’image cloud Ubuntu 24.04 »Téléchargez l’image cloud Ubuntu 24.04 si elle n’est pas déjà présente :
# Vérifier si l'image existels -lh /var/lib/libvirt/images/ubuntu-24.04-cloud.img
# Si absente, téléchargersudo curl -L -o /var/lib/libvirt/images/ubuntu-24.04-cloud.img \ https://cloud-images.ubuntu.com/noble/current/noble-server-cloudimg-amd64.imgConfiguration cloud-init
Section intitulée « Configuration cloud-init »Créez un fichier user-data pour configurer l’utilisateur SSH sur les VMs. Remplacez VOTRE_CLE_SSH_PUBLIQUE par le contenu de votre ~/.ssh/id_ed25519.pub :
#cloud-confighostname: ${HOSTNAME}manage_etc_hosts: trueusers: - name: kube sudo: ALL=(ALL) NOPASSWD:ALL groups: users, sudo shell: /bin/bash lock_passwd: true ssh_authorized_keys: - VOTRE_CLE_SSH_PUBLIQUE
packages: - qemu-guest-agent - python3
runcmd: - swapoff -a - sed -i '/swap/d' /etc/fstab - systemctl enable qemu-guest-agentConfigurer le réseau statique
Section intitulée « Configurer le réseau statique »Créez un fichier network-config pour chaque VM avec son IP statique :
version: 2ethernets: enp1s0: dhcp4: false addresses: - 192.168.122.50/24 routes: - to: default via: 192.168.122.1 nameservers: addresses: - 192.168.122.1 - 8.8.8.8Création des VMs
Section intitulée « Création des VMs »-
Générer les ISOs cloud-init pour chaque VM :
Fenêtre de terminal # Pour ks-cp1cloud-localds ks-cp1-cloud-init.iso user-data-cp1 \--network-config network-config-cp1# Répéter pour ks-worker1 et ks-worker2 avec leurs fichiers respectifs -
Créer les disques avec backing file :
Fenêtre de terminal for vm in ks-cp1 ks-worker1 ks-worker2; dosudo qemu-img create -f qcow2 \-b /var/lib/libvirt/images/ubuntu-24.04-cloud.img \-F qcow2 \/var/lib/libvirt/images/${vm}.qcow2 20Gdone -
Créer les VMs avec virt-install :
Fenêtre de terminal for vm in ks-cp1 ks-worker1 ks-worker2; dosudo virt-install \--name ${vm} \--memory 2048 \--vcpus 2 \--disk /var/lib/libvirt/images/${vm}.qcow2 \--disk /var/lib/libvirt/images/${vm}-cloud-init.iso,device=cdrom \--os-variant ubuntu24.04 \--network network=default \--graphics none \--console pty,target_type=serial \--noautoconsole \--importdone -
Vérifier la connectivité SSH :
Fenêtre de terminal for ip in 192.168.122.50 192.168.122.51 192.168.122.52; dossh -o StrictHostKeyChecking=accept-new kube@${ip} hostnamedone
Si les trois hostnames s’affichent (ks-cp1, ks-worker1, ks-worker2), vos VMs sont prêtes.
Installation de Kubespray
Section intitulée « Installation de Kubespray »Cloner le repository
Section intitulée « Cloner le repository »Utilisez toujours une version taggée pour la stabilité :
git clone https://github.com/kubernetes-sigs/kubespray.git \ --depth 1 --branch v2.26.0
cd kubesprayCréer l’environnement Python
Section intitulée « Créer l’environnement Python »Kubespray nécessite des versions spécifiques d’Ansible et de ses dépendances :
# Créer un environnement virtuel isolépython3 -m venv venvsource venv/bin/activate
# Installer les dépendancespip install -U pippip install -r requirements.txt
# Vérifier Ansibleansible --versionLa sortie doit indiquer ansible [core 2.16.x] pour Kubespray v2.26.0.
Configuration de l’inventaire
Section intitulée « Configuration de l’inventaire »Copier le template
Section intitulée « Copier le template »Kubespray fournit un inventory sample que vous personnalisez :
cp -r inventory/sample inventory/myclusterCréer le fichier hosts.yaml
Section intitulée « Créer le fichier hosts.yaml »Remplacez le contenu de inventory/mycluster/hosts.yaml par votre topologie :
all: hosts: ks-cp1: ansible_host: 192.168.122.50 ip: 192.168.122.50 access_ip: 192.168.122.50 ks-worker1: ansible_host: 192.168.122.51 ip: 192.168.122.51 access_ip: 192.168.122.51 ks-worker2: ansible_host: 192.168.122.52 ip: 192.168.122.52 access_ip: 192.168.122.52 children: kube_control_plane: hosts: ks-cp1: kube_node: hosts: ks-worker1: ks-worker2: etcd: hosts: ks-cp1: k8s_cluster: children: kube_control_plane: kube_node: calico_rr: hosts: {}Tester la connectivité Ansible
Section intitulée « Tester la connectivité Ansible »Avant le déploiement, vérifiez que Ansible peut se connecter à tous les nœuds :
ansible all -i inventory/mycluster/hosts.yaml -m ping -u kubeRésultat attendu :
ks-cp1 | SUCCESS => { "ping": "pong" }ks-worker1 | SUCCESS => { "ping": "pong" }ks-worker2 | SUCCESS => { "ping": "pong" }Personnalisation (optionnel)
Section intitulée « Personnalisation (optionnel) »Avant de déployer, vous pouvez ajuster les paramètres dans inventory/mycluster/group_vars/.
Ce que vous pouvez changer sans risque
Section intitulée « Ce que vous pouvez changer sans risque »Éditez inventory/mycluster/group_vars/k8s_cluster/k8s-cluster.yml :
# Version Kubernetes (dans la plage supportée par votre release Kubespray)kube_version: v1.30.4
# Nom DNS du clustercluster_name: cluster.localCe qui mérite un guide dédié
Section intitulée « Ce qui mérite un guide dédié »Options de référence
Section intitulée « Options de référence »| Variable | Fichier | Valeur par défaut | Description |
|---|---|---|---|
kube_version | k8s-cluster.yml | v1.30.4 | Version Kubernetes |
kube_network_plugin | k8s-cluster.yml | calico | CNI — garder par défaut en lab |
container_manager | k8s-cluster.yml | containerd | Runtime — containerd est le standard actuel |
kube_proxy_mode | k8s-cluster.yml | ipvs | Mode kube-proxy (iptables, ipvs) |
cluster_name | k8s-cluster.yml | cluster.local | Nom DNS du cluster |
kube_pods_subnet | k8s-cluster.yml | 10.233.64.0/18 | CIDR des pods |
kube_service_addresses | k8s-cluster.yml | 10.233.0.0/18 | CIDR des services |
Déploiement du cluster
Section intitulée « Déploiement du cluster »Le déploiement s’effectue avec le playbook cluster.yml. Comptez 10-20 minutes selon votre connexion Internet (téléchargement des images) :
ansible-playbook -i inventory/mycluster/hosts.yaml cluster.yml \ -u kube -b --become-user=rootProgression attendue
Section intitulée « Progression attendue »Le playbook exécute plusieurs phases :
- Préparation : configuration système, désactivation swap, modules kernel
- Téléchargement : binaires (kubectl, kubeadm, kubelet) et images conteneurs
- etcd : installation et configuration du cluster etcd
- Control plane : initialisation avec kubeadm, certificats
- Workers : jointure au cluster
- Réseau : déploiement de Calico (ou CNI choisi)
- Addons : CoreDNS, metrics-server (si activé)
Exemple de sortie finale
Section intitulée « Exemple de sortie finale »PLAY RECAP *********************************************************************ks-cp1 : ok=624 changed=135 unreachable=0 failed=0 skipped=1090ks-worker1 : ok=413 changed=82 unreachable=0 failed=0 skipped=640ks-worker2 : ok=413 changed=82 unreachable=0 failed=0 skipped=636failed=0 sur tous les nœuds indique un déploiement réussi.
Validation du cluster
Section intitulée « Validation du cluster »Récupérer le kubeconfig
Section intitulée « Récupérer le kubeconfig »Le fichier kubeconfig se trouve sur le control plane. Récupérez-le sur votre poste :
# Méthode simple avec scp (recommandée)ssh kube@192.168.122.50 "sudo cat /etc/kubernetes/admin.conf" > ~/.kube/kubespray-config
# Remplacer l'adresse localhost par l'IP du control planesed -i 's/127.0.0.1/192.168.122.50/g' ~/.kube/kubespray-config
# Configurer kubectlexport KUBECONFIG=~/.kube/kubespray-configVérifier les nœuds
Section intitulée « Vérifier les nœuds »kubectl get nodes -o wideSortie attendue :
NAME STATUS ROLES AGE VERSION INTERNAL-IP OS-IMAGE RUNTIMEks-cp1 Ready control-plane 19m v1.30.4 192.168.122.50 Ubuntu 24.04.3 LTS containerd://1.7.21ks-worker1 Ready <none> 19m v1.30.4 192.168.122.51 Ubuntu 24.04.3 LTS containerd://1.7.21ks-worker2 Ready <none> 19m v1.30.4 192.168.122.52 Ubuntu 24.04.3 LTS containerd://1.7.21Les trois nœuds doivent être Ready.
Vérifier les pods système
Section intitulée « Vérifier les pods système »kubectl get pods -ATous les pods doivent être Running :
| Namespace | Pods attendus |
|---|---|
| kube-system | calico-node (3), calico-kube-controllers |
| kube-system | coredns (2), dns-autoscaler |
| kube-system | kube-apiserver, kube-controller-manager, kube-scheduler |
| kube-system | kube-proxy (3), nodelocaldns (3) |
| kube-system | nginx-proxy (workers uniquement) |
Test de déploiement applicatif
Section intitulée « Test de déploiement applicatif »Validez que vous pouvez déployer une application :
# Créer un déploiement nginxkubectl create deployment nginx --image=nginx:alpine
# Exposer en NodePortkubectl expose deployment nginx --port=80 --type=NodePort
# Attendre que le pod soit prêtkubectl wait --for=condition=Ready pod -l app=nginx --timeout=60s
# Vérifierkubectl get pods,svcRésultat attendu :
NAME READY STATUS RESTARTS AGEpod/nginx-6f564d4fd9-xxxxx 1/1 Running 0 30s
NAME TYPE CLUSTER-IP PORT(S) AGEservice/kubernetes ClusterIP 10.233.0.1 443/TCP 20mservice/nginx NodePort 10.233.33.101 80:30965/TCP 10sLe service nginx est accessible sur http://<IP_WORKER>:30965.
Nettoyez après le test :
kubectl delete deployment nginxkubectl delete svc nginxTest DNS et connectivité inter-pods
Section intitulée « Test DNS et connectivité inter-pods »Le test nginx valide peu de choses. Pour vérifier la résolution DNS et la connectivité inter-pods :
# Lancer un pod de testkubectl run dnstest --image=busybox:1.36 --rm -it --restart=Never -- \ nslookup kubernetes.default.svc.cluster.localRésultat attendu : une adresse IP dans le range 10.233.0.x (service ClusterIP).
Dépannage
Section intitulée « Dépannage »Le déploiement échoue avec “UNREACHABLE”
Section intitulée « Le déploiement échoue avec “UNREACHABLE” »Ansible ne peut pas se connecter aux VMs :
# Vérifier la connectivité SSHssh -v kube@192.168.122.50
# Vérifier que la clé est autoriséessh kube@192.168.122.50 "cat ~/.ssh/authorized_keys"
# Vérifier que Python est installéansible all -i inventory/mycluster/hosts.yaml -m raw -a "which python3" -u kubeErreur “Unable to connect to the server”
Section intitulée « Erreur “Unable to connect to the server” »kubectl ne peut pas joindre l’API server :
# Vérifier que l'adresse est correcte dans kubeconfiggrep server ~/.kube/kubespray-config
# Tester la connectivité réseaunc -zv 192.168.122.50 6443
# Vérifier que l'API server tournessh kube@192.168.122.50 "sudo crictl ps | grep kube-apiserver"Pods bloqués en “Pending”
Section intitulée « Pods bloqués en “Pending” »Généralement un problème de ressources ou de taints :
# Décrire le pod pour voir les événementskubectl describe pod <pod-name>
# Vérifier les ressources disponibleskubectl describe nodes | grep -A5 "Allocated resources"
# Vérifier les taintskubectl get nodes -o custom-columns=NAME:.metadata.name,TAINTS:.spec.taintsRelancer un déploiement partiel
Section intitulée « Relancer un déploiement partiel »Si le déploiement a échoué à mi-chemin, relancez simplement la même commande. Ansible est idempotent et reprendra où il s’est arrêté :
ansible-playbook -i inventory/mycluster/hosts.yaml cluster.yml \ -u kube -b --become-user=rootOpérations courantes
Section intitulée « Opérations courantes »Ajouter un worker
Section intitulée « Ajouter un worker »- Provisionner la nouvelle VM avec cloud-init
- Ajouter l’entrée dans
hosts.yamlsouskube_node - Exécuter le playbook
scale.yml:
ansible-playbook -i inventory/mycluster/hosts.yaml scale.yml \ -u kube -b --become-user=root --limit=nouveau-workerSupprimer un nœud
Section intitulée « Supprimer un nœud »Kubespray fournit un playbook dédié pour la suppression propre :
# Méthode recommandée : playbook remove-nodeansible-playbook -i inventory/mycluster/hosts.yaml remove-node.yml \ -u kube -b --become-user=root \ -e "node=ks-worker2"Ce playbook effectue automatiquement le drain, la suppression des composants Kubernetes sur le nœud et le nettoyage. Après exécution, retirez manuellement le nœud de votre fichier hosts.yaml.
Mettre à jour Kubernetes
Section intitulée « Mettre à jour Kubernetes »- Modifier
kube_versiondansgroup_vars/k8s_cluster/k8s-cluster.yml - Exécuter le playbook
upgrade-cluster.yml:
ansible-playbook -i inventory/mycluster/hosts.yaml upgrade-cluster.yml \ -u kube -b --become-user=rootNettoyage du cluster
Section intitulée « Nettoyage du cluster »Pour supprimer complètement Kubernetes des nœuds :
ansible-playbook -i inventory/mycluster/hosts.yaml reset.yml \ -u kube -b --become-user=rootCe playbook :
- Arrête et supprime tous les conteneurs
- Supprime les binaires Kubernetes
- Nettoie les règles iptables
- Supprime les fichiers de configuration
Pour supprimer aussi les VMs :
for vm in ks-cp1 ks-worker1 ks-worker2; do sudo virsh destroy ${vm} sudo virsh undefine ${vm} --remove-all-storagedoneÀ retenir
Section intitulée « À retenir »Kubespray industrialise le déploiement de clusters Kubernetes :
- Infrastructure as Code : votre cluster est défini dans des fichiers YAML versionnables
- Reproductibilité : le même inventory produit le même cluster à chaque exécution
- Automatisation : upgrades, scaling, suppression de nœuds via playbooks dédiés
- Base solide : ce lab constitue un socle pour des déploiements plus robustes
Ce guide vous a permis de déployer un lab reproductible. Pour passer en production, il faut encore :
- 3 control planes + load balancer devant l’API server
- Backup etcd externalisé et testé régulièrement
- Monitoring, alerting et logs centralisés
- Sécurité réseau (NetworkPolicies, firewall configuré)
- Plan de reprise d’activité (PRA) documenté