Vous cherchez a monter un cluster Kubernetes de zero sur des serveurs Debian ? Dans ce tutoriel, nous allons deployer pas a pas un cluster Kubernetes fonctionnel sous Debian 13 (Trixie) a l’aide de kubeadm, en utilisant containerd comme moteur de conteneurs (Container Runtime) et Flannel comme plugin reseau (CNI).

Au moment de la redaction, la derniere version stable est Kubernetes 1.36 : c’est celle que nous installerons depuis les depots communautaires officiels pkgs.k8s.io. La procedure reste valable pour les versions ulterieures, il suffit d’adapter le numero de version du depot.

Presentation de l’architecture

Un cluster Kubernetes se compose d’au moins un noeud de controle (control plane / master) qui pilote le cluster, et d’un ou plusieurs noeuds de travail (workers) qui executent les conteneurs applicatifs. Pour cet exemple, nous utilisons trois machines virtuelles sous Debian 13 :

Role Nom d’hote Adresse IP Ressources mini
Control plane (master) k8s-master 192.168.50.10 2 vCPU / 2 Go RAM
Worker 1 k8s-worker1 192.168.50.11 2 vCPU / 2 Go RAM
Worker 2 k8s-worker2 192.168.50.12 2 vCPU / 2 Go RAM

1) Prerequis

  • Au moins 2 machines sous Debian 13 (1 control plane + 1 worker), 3 dans cet exemple.
  • Minimum 2 vCPU et 2 Go de RAM par noeud (exige par kubeadm init).
  • Le paquet sudo installe et un utilisateur disposant des droits sudo.
  • Une connectivite reseau complete entre tous les noeuds et des noms d’hote uniques.
  • L’horloge synchronisee (chrony / systemd-timesyncd) sur tous les noeuds.

Important : sauf mention contraire, les etapes 2 a 6 doivent etre executees a l’identique sur TOUS les noeuds (master ET workers). Les etapes 7 et suivantes precisent ou les jouer.


2) Mise a jour et dependances (tous les noeuds)

On met le systeme a jour et on installe les quelques utilitaires necessaires a Kubernetes :

sudo apt update && sudo apt -y full-upgrade
sudo apt -y install apt-transport-https ca-certificates curl gpg socat conntrack ipset

3) Configuration systeme (tous les noeuds)

3.1) Desactiver le swap

Le kubelet refuse de demarrer si le swap est actif (comportement par defaut). On le desactive immediatement puis on le commente dans /etc/fstab pour qu’il reste desactive au redemarrage :

sudo swapoff -a
sudo sed -i '/ swap / s/^/#/' /etc/fstab

Verifiez avec swapon --show : la commande ne doit plus rien afficher. Si votre installation utilise un swap gere par systemd (unite .swap), masquez-la avec systemctl mask plutot que de modifier fstab.

3.2) Charger les modules du noyau

Kubernetes a besoin des modules overlay (systeme de fichiers des conteneurs) et br_netfilter (filtrage du trafic ponte) :

printf 'overlay\nbr_netfilter\n' | sudo tee /etc/modules-load.d/k8s.conf
sudo modprobe overlay
sudo modprobe br_netfilter

3.3) Parametres reseau du noyau (sysctl)

On active le routage IPv4 et la prise en compte du trafic ponte par iptables, indispensables au bon fonctionnement du reseau des pods et de kube-proxy :

printf 'net.bridge.bridge-nf-call-iptables = 1\nnet.bridge.bridge-nf-call-ip6tables = 1\nnet.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/k8s.conf
sudo sysctl --system

4) Installation du Container Runtime : containerd (tous les noeuds)

Kubernetes ne gere pas directement les conteneurs : il s’appuie sur un Container Runtime. Nous utilisons containerd, installe depuis le depot officiel Docker pour disposer d’une version recente et compatible. On utilise le format moderne deb822 (.sources) pour les depots APT, recommande sous Debian 13.

4.1) Ajouter le depot Docker et installer containerd

sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/debian/gpg | sudo tee /etc/apt/keyrings/docker.asc > /dev/null
sudo chmod a+r /etc/apt/keyrings/docker.asc

On declare le depot au format deb822 puis on installe containerd.io :

printf 'Types: deb\nURIs: https://download.docker.com/linux/debian\nSuites: trixie\nComponents: stable\nSigned-By: /etc/apt/keyrings/docker.asc\n' | sudo tee /etc/apt/sources.list.d/docker.sources
sudo apt update
sudo apt -y install containerd.io

4.2) Configurer containerd avec le driver cgroup systemd

On genere la configuration par defaut puis on active le pilote de cgroups systemd (obligatoire pour que kubelet et containerd s’accordent sur la gestion des ressources) :

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd

5) Installation de Kubernetes 1.36 (tous les noeuds)

5.1) Ajouter la cle et le depot Kubernetes

On recupere la cle de signature du depot communautaire Kubernetes (branche stable v1.36) :

curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.36/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

Puis on declare le depot, toujours au format deb822 (notez le Suites: /, specifique aux depots dits plats) :

printf 'Types: deb\nURIs: https://pkgs.k8s.io/core:/stable:/v1.36/deb/\nSuites: /\nSigned-By: /etc/apt/keyrings/kubernetes-apt-keyring.gpg\n' | sudo tee /etc/apt/sources.list.d/kubernetes.sources

Remarque : pour installer une autre version, remplacez v1.36 par la version voulue (ex. v1.35) dans la cle ET dans le depot.

5.2) Installer kubelet, kubeadm et kubectl

On installe les trois composants, puis on fige leur version (apt-mark hold) pour qu’une mise a jour systeme ne casse pas le cluster de maniere incontrolee :

sudo apt update
sudo apt -y install kubelet kubeadm kubectl
sudo apt-mark hold kubelet kubeadm kubectl
sudo systemctl enable --now kubelet

6) Initialisation du control plane (sur le master uniquement)

Cette etape ne se lance que sur k8s-master. On initialise le cluster en precisant le sous-reseau des pods attendu par Flannel (10.244.0.0/16) et l’adresse d’annonce de l’API server :

sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.50.10

Au bout d’une a deux minutes, kubeadm affiche un message de succes se terminant par la commande de jonction a conserver precieusement (elle contient le token et l’empreinte du certificat CA) :

Your Kubernetes control-plane has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

  mkdir -p $HOME/.kube
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 192.168.50.10:6443 --token abcdef.0123456789abcdef \
    --discovery-token-ca-cert-hash sha256:HASH

6.1) Configurer kubectl pour votre utilisateur

Toujours sur le master, on copie le fichier d’identification d’administration pour pouvoir utiliser kubectl sans sudo :

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

7) Installer le plugin reseau (CNI) Flannel (sur le master)

Tant qu’aucun CNI n’est installe, les noeuds restent en etat NotReady. Flannel est l’un des plus simples a deployer ; il s’applique en une seule commande depuis le master :

kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml

Apres quelques dizaines de secondes, les pods systeme et reseau doivent passer en Running, et le master en Ready :

kubectl get pods -n kube-flannel
kubectl get nodes -o wide

8) Ajouter les noeuds workers au cluster

Sur chaque worker (k8s-worker1, k8s-worker2), executez la commande kubeadm join fournie a la fin de l’etape 6, en root (ou avec sudo) :

sudo kubeadm join 192.168.50.10:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:HASH

Token perdu ou expire ? Le token de jonction n’est valable que 24 h. Pour en regenerer un et obtenir la commande complete, lancez sur le master :

kubeadm token create --print-join-command

9) Verification du cluster

De retour sur le master, verifiez que tous les noeuds sont Ready et que les pods systeme tournent :

kubectl get nodes -o wide
kubectl get pods -A

Les trois noeuds doivent apparaitre en Ready. Si vous travaillez sur un cluster a un seul noeud (master = worker), retirez la taint du control plane pour autoriser l’ordonnancement de pods applicatifs dessus :

kubectl taint nodes --all node-role.kubernetes.io/control-plane-

10) Tester avec un premier deploiement

Pour valider le bon fonctionnement, deployons un serveur Nginx et exposons-le via un service de type NodePort :

kubectl create deployment nginx --image=nginx
kubectl expose deployment nginx --type=NodePort --port=80
kubectl get svc nginx
kubectl get pods -o wide

Recuperez le port attribue (dans la plage 30000-32767) dans la sortie de kubectl get svc, puis testez depuis n’importe quel noeud : curl http://192.168.50.11:PORT. La page d’accueil Nginx doit s’afficher.

Bonus : autocompletion de kubectl

kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null
echo 'alias k=kubectl' >> ~/.bashrc
echo 'complete -o default -F __start_kubectl k' >> ~/.bashrc

Points de vigilance

  • nftables sous Debian 13 : Trixie utilise nftables par defaut. kube-proxy en mode iptables fonctionne grace a la couche de compatibilite iptables-nft deja en place, rien a faire. En revanche, si vous activez un pare-feu, pensez a ouvrir les ports requis (voir tableau ci-dessous).
  • Swap : verifiez bien qu’il est desactive (swapon --show vide). C’est la cause numero un d’echec de demarrage du kubelet.
  • Versions figees : les paquets sont en hold. Pour mettre a jour Kubernetes, retirez le hold (sudo apt-mark unhold ...), montez de version mineure par mineure, et utilisez kubeadm upgrade.
  • Sous-reseau des pods : le --pod-network-cidr doit correspondre au CNI choisi (10.244.0.0/16 pour Flannel). Un mauvais CIDR empeche la communication entre pods.
  • Pour la production : envisagez un CNI plus riche comme Cilium (eBPF) ou Calico (politiques reseau avancees), plusieurs control planes pour la haute disponibilite, et une solution de stockage persistant.

Ports a ouvrir si un pare-feu est actif

Noeud Ports Usage
Control plane 6443/TCP API server Kubernetes
Control plane 2379-2380/TCP etcd
Control plane 10257/TCP, 10259/TCP controller-manager, scheduler
Tous les noeuds 10250/TCP API kubelet
Tous les noeuds 8472/UDP Flannel (VXLAN)
Workers 30000-32767/TCP Services NodePort

Recapitulatif des commandes

Les commandes essentielles, communes a tous les noeuds puis specifiques au master :

# --- Sur TOUS les noeuds ---
sudo swapoff -a && sudo sed -i '/ swap / s/^/#/' /etc/fstab
printf 'overlay\nbr_netfilter\n' | sudo tee /etc/modules-load.d/k8s.conf
sudo modprobe overlay && sudo modprobe br_netfilter
printf 'net.bridge.bridge-nf-call-iptables = 1\nnet.bridge.bridge-nf-call-ip6tables = 1\nnet.ipv4.ip_forward = 1\n' | sudo tee /etc/sysctl.d/k8s.conf
sudo sysctl --system
sudo apt -y install containerd.io
sudo systemctl enable --now containerd kubelet

# --- Sur le MASTER uniquement ---
sudo kubeadm init --pod-network-cidr=10.244.0.0/16 --apiserver-advertise-address=192.168.50.10
kubectl apply -f https://github.com/flannel-io/flannel/releases/latest/download/kube-flannel.yml
kubeadm token create --print-join-command

# --- Sur chaque WORKER ---
sudo kubeadm join 192.168.50.10:6443 --token TOKEN --discovery-token-ca-cert-hash sha256:HASH

Conclusion

Vous disposez desormais d’un cluster Kubernetes 1.36 fonctionnel sous Debian 13, avec containerd comme runtime et Flannel comme reseau. C’est une base ideale pour experimenter : deploiements, services, Ingress, volumes persistants, Helm… La meme procedure se transpose telle quelle a un environnement de production, a condition d’y ajouter la haute disponibilite du control plane, un CNI orienté politiques reseau et une supervision adaptee.