Kubernetes (souvent abrégé en K8s) est une plateforme open source conçue pour automatiser le déploiement, la mise à l’échelle et la gestion d’applications conteneurisées. Grâce à Kubernetes, il est possible d’orchestrer des conteneurs (comme ceux créés avec Docker) sur un ensemble de machines appelées nœuds (ou nodes), en assurant haute disponibilité, résilience et portabilité.
Aujourd’hui, je vais vous montrer comment installer un petit cluster Kubernetes avec 3 nœuds : 1 master et 2 workers. Dans cet exemple je vous montrer comment configurer sans configuration DNS serveur, seulement avec le fichier hosts sur chaque node.
Prérequis
Pour cette démonstration, j’utilise la configuration suivante.
Systèmes d’exploitation :
– Ubuntu Server 22.04 LTS est installée sur 3 VM sur Proxmox.
– SSH est configuré et fonctionnel.
– Des adresses IP statiques sont attribuées à chaque nœud
Configuration des IP :
– Kubernetes Master (Control Plane) : 192.168.0.211, hostname : k8sm
– Kubernetes Worker 1 : 192.168.0.212, hostname : k8sw1
– Kubernetes Worker 2 : 192.168.0.213, hostname : k8sw2
Comptes utilisateurs :
Utilisateur : oleks (vous pouvez utiliser autre 🙂 )
Mot de passe : un mot de passe robuste et sécurisé
👉 Adaptez-la à votre propre environnement : utilisez vos adresses IP et un mot de passe fort et unique pour chaque machine.
Pare-feu (UFW) :
Le pare-feu UFW sera temporairement désactivé pendant l’installation pour éviter les blocages de communication entre les nœuds :
sudo ufw disable
On va le réactiver et le reconfigurer à la fin du processus.
Étape 1 : Configuration des noms d’hôte
Sur chaque nœud, il faut d’abord configurer le nom d’hôte (si ce n’est pas déjà fait pendant l’installation).
Par exemple, sur le nœud master :
sudo hostnamectl set-hostname "<k8sm>"
Sur les nœuds workers :
sudo hostnamectl set-hostname "<k8sw1>" sudo hostnamectl set-hostname "<k8sw2>"
Modification du fichier /etc/hosts
Ensuite, sur chaque nœud, il faut ajouter les noms d’hôte associés aux adresses IP pour permettre la résolution locale, en éditant le fichier /etc/hosts :
sudo nano /etc/hosts
Ajoutez à la fin du fichier les lignes suivantes :
192.168.0.211 k8sm.lan 192.168.0.212 k8sw1.lan 192.168.0.213 k8sw2.lan
Vous pouvez aussi utiliser cette commande pour les ajouter automatiquement :
sudo tee -a /etc/hosts > /dev/null <<EOF # k8s 192.168.0.211 k8sm.lan 192.168.0.212 k8sw1.lan 192.168.0.213 k8sw2.lan EOF
Une fois les modifications faites, redémarrer le service de nommage peut être utile (optionnel mais recommandé) :
sudo systemctl restart systemd-hostnamed
Étape 2 : Désactivation de SWAP
Sur chaque nœud, il faut désactiver le SWAP. Kubernetes ne fonctionne pas correctement si le SWAP est activé.
1. Désactiver temporairement (jusqu’au redémarrage) :
sudo swapoff -a
2. Désactiver de manière permanente :
Méthode automatique (ligne SWAP commentée dans /etc/fstab) :
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab
OU bien manuellement :
sudo nano /etc/fstab
Puis ajoutez un # au début de la ligne correspondant à la partition de SWAP.
Vérification
Vous pouvez vérifier que le SWAP est bien désactivé avec les commandes suivantes :
free -h
et
swapon --show
Si aucune ligne n’est affichée avec swapon –show, c’est que le SWAP est désactivé.
Étape 3 : Chargement et activation des modules du noyau (Kernel)
Sur chaque nœud, il faut s’assurer que certains modules du noyau Linux sont chargés pour que Kubernetes fonctionne correctement, en particulier pour le réseau.
1. Créer le fichier de configuration des modules nécessaires
sudo tee /etc/modules-load.d/containerd.conf <<EOF overlay br_netfilter EOF
2. Charger les modules immédiatement
sudo modprobe overlay sudo modprobe br_netfilter
3. S’assurer qu’ils seront chargés au démarrage
echo -e "overlay\nbr_netfilter" | sudo tee -a /etc/modules
4. Configurer les paramètres du noyau pour Kubernetes
sudo tee /etc/sysctl.d/kubernetes.conf <<EOF net.bridge.bridge-nf-call-ip6tables = 1 net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1 EOF
5. Appliquer les changements immédiatement
sudo sysctl --system
Étape 4 : Installation et configuration de containerd (sur chaque node)
Kubernetes a besoin d’un runtime de conteneurs. Ici, on utilise containerd, une solution légère, performante et recommandée.
1. Ajouter la clé GPG officielle de Docker
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmour -o /etc/apt/trusted.gpg.d/docker.gpg
2. Ajouter le dépôt Docker
Ce dépôt permet d’installer la version officielle et à jour de containerd.io, qui n’est pas toujours disponible dans les dépôts standards d’Ubuntu.
On n’utilise ici que containerd, sans installer Docker Engine (docker-ce), comme recommandé par Kubernetes.
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
3. Mettre à jour les dépôts et installer les paquets nécessaires
sudo apt update sudo apt install -y curl gnupg2 software-properties-common apt-transport-https ca-certificates containerd.io
4. Générer la configuration par défaut de containerd
sudo containerd config default | sudo tee /etc/containerd/config.toml >/dev/null 2>&1
5. Modifier la configuration pour activer le mode SystemdCgroup
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/g' /etc/containerd/config.toml
6. Redémarrer et activer containerd
sudo systemctl restart containerd sudo systemctl enable containerd
7. Vérifier que containerd fonctionne correctement
systemctl status containerd
Étape 5 : Installation de Kubernetes (kubelet, kubeadm, kubectl)
On va maintenant installer les composants essentiels de Kubernetes sur chaque nœud :
– kubelet : l’agent qui tourne sur chaque nœud du cluster.
– kubeadm : l’outil pour initialiser et configurer le cluster.
– kubectl : l’outil en ligne de commande pour interagir avec le cluster.
1. Mise à jour des dépôts
sudo apt-get update
2. Installer les paquets nécessaires pour gérer les dépôts
sudo apt-get install -y curl ca-certificates gnupg
3. Créer le répertoire pour les clés APT (s’il n’existe pas)
sudo mkdir -p -m 755 /etc/apt/keyrings
4. Télécharger et ajouter la clé de signature Kubernetes
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.31/deb/Release.key | \ sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg sudo chmod 644 /etc/apt/keyrings/kubernetes-apt-keyring.gpg
5. Ajouter le dépôt Kubernetes
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.31/deb/ /' | \ sudo tee /etc/apt/sources.list.d/kubernetes.list sudo chmod 644 /etc/apt/sources.list.d/kubernetes.list
6. Mettre à jour à nouveau les dépôts
sudo apt-get update
7. Installer kubelet, kubeadm et kubectl
sudo apt-get install -y kubelet kubeadm kubectl
8. Bloquer leur mise à jour automatique (recommandé)
sudo apt-mark hold kubelet kubeadm kubectl
Vérification de l’installation
Pour vérifier que les trois composants sont bien installés :
which kubelet && which kubeadm && which kubectl
Si les chemins s’affichent, c’est bon !
Pour vérifier leurs versions :
kubelet --version kubeadm version kubectl version --client
Pour confirmer que le dépôt Kubernetes est bien ajouté :
grep kubernetes /etc/apt/sources.list.d/*.list
Étape 6 : Initialisation du Cluster Kubernetes (sur le Master)
Sur le nœud master (k8sm.lan), on va initialiser le cluster à l’aide de kubeadm.
🟡 Très important : la plage réseau utilisée pour les pods Kubernetes doit être différente de celle de ton réseau physique (dans mon cas 192.168.0.0/24).
Sinon, les pods ne pourront pas communiquer avec l’extérieur (conflits de routage).
Commande d’initialisation
sudo kubeadm init \ --control-plane-endpoint=k8sm.lan \ --pod-network-cidr=192.168.100.0/24
Variante possible (sans –control-plane-endpoint) si vous ne gérez pas de haute disponibilité :
sudo kubeadm init --pod-network-cidr=192.168.100.0/24
Configuration de kubectl pour l’utilisateur actuel (par exemple oleks)
Après l’initialisation, il faut configurer kubectl pour pouvoir gérer le cluster sans utiliser sudo :
mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config
Vérifiez que le cluster a été bien initialisé
Lance cette commande pour vérifier que le cluster est bien initialisé :
kubectl cluster-info
Si tout fonctionne, tu devrais voir une URL pointant vers le serveur d’API Kubernetes.
Étape 7 : Ajout des Workers au Cluster
Dans cette étape, je vais vous montrer comment intégrer les deux nœuds workers (k8sw1 et k8sw2) dans le cluster initialisé sur le master k8sm.
1. Sur le nœud master (k8sm)
Exécutez la commande suivante pour générer la ligne de jointure du cluster. Cette ligne contient un token et un hash de certificat nécessaires à l’authentification :
kubeadm token create --print-join-command
Cela affichera une commande comme celle-ci :
sudo kubeadm join k8sm.lan:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Gardez cette commande bien copiée, car elle sera utilisée dans les prochaines étapes sur les workers
2. Sur chaque nœud worker (k8sw1 puis k8sw2)
Collez et exécutez la commande générée à l’étape précédente. Exemple :
sudo kubeadm join k8sm.lan:6443 --token abcdef.0123456789abcdef \ --discovery-token-ca-cert-hash sha256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Après cette étape, les workers vont tenter de rejoindre le cluster.
3. De retour sur le nœud master (k8sm)
Vérifiez que les nœuds sont bien enregistrés dans le cluster :
kubectl get nodes
Vous devriez voir une sortie similaire à :
Pourquoi les workers sont en NotReady ?
Pas de panique 😄 — c’est normal !
Les nœuds sont bien connectés, mais ils apparaissent NotReady car aucun plugin CNI (réseau) n’est encore installé.
On va régler ça dans la prochaine étape !
Étape 8 : Installation de Calico (CNI)
À exécuter uniquement sur le nœud master (k8sm)
Pourquoi cette étape est essentielle :
Par défaut, Kubernetes ne fournit aucun plugin réseau.
Sans CNI (Container Network Interface), les nœuds ne peuvent pas communiquer, ce qui les laisse en statut NotReady.
Nous allons installer Calico, un plugin populaire, simple à mettre en œuvre pour les clusters sur machines virtuelles.
Installation des plugins CNI (obligatoire)
Avant d’installer Calico, vous devez installer les plugins CNI, nécessaires pour permettre la communication entre les pods :
CNI_VERSION="v1.3.0" ARCH="amd64" PLATFORM="linux" sudo mkdir -p /opt/cni/bin curl -L -o cni-plugins.tgz https://github.com/containernetworking/plugins/releases/download/v1.3.0/cni-plugins-linux-amd64-v1.3.0.tgz sudo tar -C /opt/cni/bin -xzf cni-plugins.tgz rm cni-plugins.tgz
Téléchargez et appliquez le manifeste Calico :
curl -O https://raw.githubusercontent.com/projectcalico/calico/v3.25.0/manifests/calico.yaml
Ce fichier contient la configuration complète de Calico pour Kubernetes.
Modification de la plage d’adresses des pods
Par défaut, Calico utilise le bloc 192.168.0.0/16.
Dans notre cas, pour éviter les conflits avec le réseau physique 192.168.0.0/24, nous avons défini la plage de pods comme 192.168.100.0/24.
Nous devons donc adapter ce fichier.
Ouvrez le fichier téléchargé :
nano calico.yaml
Cherchez la ligne suivante (vers la fin du fichier) :
- name: CALICO_IPV4POOL_CIDR
value: "192.168.0.0/16"
Et remplacez-la par :
- name: CALICO_IPV4POOL_CIDR
value: "192.168.100.0/24"
Appliquez le manifeste Calico:
kubectl apply -f calico.yaml
Cela déploie les pods nécessaires dans l’espace de noms kube-system.
Vérifiez le déploiement de Calico :
kubectl get pods -n kube-system
Les pods suivants doivent apparaître et passer en statut Running, notamment :
– calico-kube-controllers
– calico-node
🟡 Si certains restent en Pending ou CrashLoopBackOff, il peut y avoir un problème de configuration du réseau ou des modules noyau.
Vérifier que tous les nœuds sont Ready
kubectl get nodes
Tous les nœuds (k8sm, k8sw1, k8sw2) devraient passer en statut Ready.
Test DNS dans le cluster
kubectl run testdns --image=busybox:1.28 --rm -it --restart=Never -- nslookup kubernetes.default
Bonus : vérifier un fichier YAML avant de l’appliquer
1. Vérification avec kubectl (mode dry-run)
kubectl apply --dry-run=client -f calico.yaml
Vérifie la syntaxe et la structure du fichier sans l’exécuter.
✅ 2. Vérification avec yamllint
Installation:
sudo apt install yamllint
Puis :
yamllint calico.yaml
Cela permet de repérer des erreurs d’indentation, d’espacement ou de caractères invisibles.
✅ 3. Vérification avec Python (conversion YAML → JSON)
Très utile pour repérer des erreurs de structure qui feraient planter kubectl.
python3 -c "import yaml, sys, json; json.dump(yaml.safe_load(open('calico.yaml')), sys.stdout)"
Script bash pour valider un fichier YAML
J’ai publié un script pratique sur mon GitHub pour valider un fichier YAML avant de l’appliquer avec kubectl.
À quoi sert ce script ?
Le script permet de :
– Vérifier la syntaxe YAML avec yamllint
– Tester la validité Kubernetes avec kubectl apply –dry-run=client
– Afficher des messages clairs en cas de succès ou d’erreur
Comment utiliser k8s_yaml_validator.sh
Installer yamllint si ce n’est pas encore fait :
sudo apt install yamllint
Télécharger le script depuis GitHub ou créer un fichier k8s_yaml_validator.sh avec ce contenu.
Rendre le script exécutable :
chmod +x k8s_yaml_validator.sh
Lancer la vérification :
./k8s_yaml_validator.sh calico.yaml
Exemple de sortie attendue
✔️ Si tout va bien :
🔍 Vérification avec yamllint... 🔄 Test dry-run avec kubectl... ✅ Tout est OK.
❌ En cas d’erreur, le message indiquera si elle vient :
– d’un problème de structure YAML
– ou d’un problème de ressource Kubernetes
Étape 9 : Réactivation du Pare-feu (UFW)
Une fois le cluster opérationnel, il est recommandé de réactiver le pare-feu pour sécuriser les communications entre les nœuds.
Nous allons configurer UFW :
– sur le nœud master (k8sm)
– sur les nœuds workers (k8sw1, k8sw2)
1 Configuration du Master Node
1.1 Vérifiez l’état actuel de UFW :
Avant d’activer UFW, vérifiez son état pour éviter toute interruption :
sudo ufw status verbose
1.2 Autorisez le port SSH (22) :
Pour maintenir l’accès SSH, ajoutez la règle suivante en priorité :
sudo ufw allow 22
1.3 Autoriser le port API Kubernetes (6443) et BGP (179)
Le port 6443 est essentiel pour la communication entre kubectl et les workers :
sudo ufw allow 6443 sudo ufw allow 179
1.4 Activez UFW :
Une fois les règles ajoutées, activez UFW :
sudo ufw enable
1.5 Vérifier les règles appliquées
Assurez-vous que les ports 22 et 6443 sont bien ouverts :
sudo ufw status
2. Configuration des Worker Nodes
2.1 Vérifiez l’état actuel de UFW :
Comme pour le master node, vérifiez l’état de UFW avant de commencer :
sudo ufw status verbose
2.2 Autorisez le port SSH (22) :
Pour maintenir l’accès SSH, ajoutez la règle suivante :
sudo ufw allow 22
2.3 2.3 Autoriser les ports pour kubelet (10250) et BGP (179)
Le port 10250 est utilisé pour la communication entre le master et les workers :
sudo ufw allow 10250 sudo ufw allow 179
2.4 Activez UFW :
Activez UFW une fois les règles nécessaires ajoutées :
sudo ufw enable
2.5 Vérifier les règles appliquées
Assurez-vous que les ports 22 et 10250 sont bien ouverts :
sudo ufw status
3. Vérifications finales
3.1 Vérifiez l’état des nœuds depuis le master :
Sur le master node, exécutez la commande suivante pour vérifier que les workers sont bien connectés :
kubectl get nodes
3.2 Testez la connectivité entre les nœuds :
Depuis le master, ping les deux workers pour s’assurer qu’ils sont accessibles :
ping 192.168.0.212 # Worker 1 ping 192.168.0.213 # Worker 2
Félicitations, ton cluster Kubernetes est maintenant entièrement configuré, sécurisé, et prêt à l’emploi
Bonne chance!