Files
Blog/content/post/8-create-manual-kubernetes-cluster-kubeadm.fr.md
Gitea Actions f272a529ee
All checks were successful
Blog Deployment / Check-Rebuild (push) Successful in 5s
Blog Deployment / Build (push) Has been skipped
Blog Deployment / Deploy-Staging (push) Successful in 9s
Blog Deployment / Test-Staging (push) Successful in 2s
Blog Deployment / Merge (push) Successful in 6s
Blog Deployment / Deploy-Production (push) Successful in 9s
Blog Deployment / Test-Production (push) Successful in 3s
Blog Deployment / Clean (push) Has been skipped
Blog Deployment / Notify (push) Successful in 2s
Auto-update blog content from Obsidian: 2025-07-18 11:38:30
2025-07-18 11:38:30 +00:00

12 KiB
Raw Blame History

slug, title, description, date, draft, tags, categories
slug title description date draft tags categories
create-manual-kubernetes-cluster-kubeadm Template true

Intro

Dans cet [article précédent]({{< ref "post/7-terraform-create-proxmox-module" >}}), j'expliquais comment déployer 6 VMs avec Terraform sur Proxmox, 3 nœuds masters et 3 nœuds workers, en m'appuyant sur un [template cloud-init]({{< ref "post/1-proxmox-cloud-init-vm-template" >}}).

Maintenant que l'infrastructure est prête, passons à l'étape suivante : créer manuellement un cluster Kubernetes avec kubeadm.

Dans cet article, je vais détailler chaque étape de l'installation dun cluster Kubernetes simple, depuis la préparation des nœuds jusqu'au déploiement d'une application basique.

Je n'utiliserai pas d'outil d'automatisation pour configurer les nœuds pour le moment, afin de mieux comprendre les étapes impliquées dans le bootstrap dun cluster Kubernetes. L'automatisation sera couverte dans de futurs articles.


Qu'est ce que Kubernetes

Kubernetes est une plateforme open-source qui orchestre des containers sur un ensemble de machines. Elle gère le déploiement, la montée en charge et la santé des applications conteneurisées, ce qui vous permet de vous concentrer sur vos services plutôt que sur linfrastructure sous-jacente.

Un cluster Kubernetes est composé de deux types de nœuds : les nœuds control plane (masters) et les workers. Le control plane assure la gestion globale du cluster, il prend les décisions de planification, surveille létat du système et réagit aux événements. Les workers, eux, exécutent réellement vos applications, dans des containers gérés par Kubernetes.

Dans cet article, nous allons mettre en place manuellement un cluster Kubernetes avec 3 nœuds control plane et 3 workers. Cette architecture reflète un environnement hautement disponible et proche de la production, même si lobjectif ici est avant tout pédagogique.

La documentation officielle se trouve ici, je vais utiliser la version v1.32.


Préparer les Nœuds

Je vais exécuter les étapes suivantes sur les 6 VMs (masters et workers).

Hostname

Chaque VM possède un nom dhôte unique et tous les nœuds doivent pouvoir se résoudre entre eux.

Le nom dhôte est défini à la création de la VM via cloud-init. Mais pour la démonstration, je vais le définir manuellement :

sudo hostnamectl set-hostname <hostname>

Dans mon infrastructure, les nœuds se résolvent via mon serveur DNS sur le domaine lab.vezpi.me. Si vous navez pas de DNS, vous pouvez inscrire manuellement les IPs des nœuds dans le fichier /etc/hosts :

192.168.66.168 apex-worker
192.168.66.167 apex-master
192.168.66.166 zenith-master
192.168.66.170 vertex-worker
192.168.66.169 vertex-master
192.168.66.172 zenith-worker

Mises à jour Système

Mes VMs tournent sous Ubuntu 24.04.2 LTS. Cloud-init soccupe des mises à jour après le provisionnement, mais on sassure quand même que tout est bien à jour et on installe les paquets nécessaires pour ajouter le dépôt Kubernetes :

sudo apt update && sudo apt upgrade -y
sudo apt install -y apt-transport-https ca-certificates curl gpg

Swap

Par défaut, kubelet ne démarre pas si une mémoire swap est détectée sur un nœud. Il faut donc la désactiver ou la rendre tolérable par kubelet.

Mes VMs ne disposent pas de swap, mais voici comment le désactiver si besoin :

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

Pare-feu

Dans ce lab, je désactive simplement le pare-feu local (à ne pas faire en production) :

sudo systemctl disable --now ufw

En production, vous devez autoriser la communication entre les nœuds sur les ports suivants :

Control Plane

Protocole Direction Ports Usage Utilisé par
TCP Entrant 6443 API server Kubernetes Tous
TCP Entrant 2379-2380 API client etcd kube-apiserver, etcd
TCP Entrant 10250 API Kubelet Plan de contrôle
TCP Entrant 10259 kube-scheduler Lui-même
TCP Entrant 10257 kube-controller-manager Lui-même

Worker

Protocole Direction Ports Usage Utilisé par
TCP Entrant 10250 API Kubelet Control plane
TCP Entrant 10256 kube-proxy Load balancers
TCP Entrant 30000-32767 Services NodePort Tous

Modules noyau et paramètres sysctl

Kubernetes requiert lactivation de deux modules noyau :

  • overlay : pour permettre lempilement de systèmes de fichiers.
  • br_netfilter : pour activer le filtrage des paquets sur les interfaces bridge.

Activation des modules :

cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

Appliquer les paramètres noyau nécessaires pour la partie réseau :

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

Runtime de Containers

Chaque nœud du cluster doit disposer dun runtime de containers pour pouvoir exécuter des Pods. Jutilise ici containerd :

sudo apt install -y containerd

Créer la configuration par défaut :

sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null

Utiliser systemd comme pilote de cgroup :

sudo sed -i 's/^\(\s*SystemdCgroup\s*=\s*\)false/\1true/' /etc/containerd/config.toml

Redémarrer et activer le service containerd :

sudo systemctl restart containerd
sudo systemctl enable containerd

Paquets Kubernetes

Dernière étape : installer les paquets Kubernetes. On commence par ajouter le dépôt officiel et sa clé de signature.

Ajouter la clé :

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

Ajouter le dépôt :

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list

Installer ensuite les paquets nécessaires :

  • kubeadm : loutil pour initier un cluster Kubernetes.
  • kubelet : lagent qui sexécute sur tous les nœuds et qui gère les pods/containers.
  • kubectl : loutil en ligne de commande pour interagir avec le cluster.

Sur les nœuds, on installe kubelet et kubeadm, puis on les fige :

sudo apt-get update
sudo apt-get install -y kubelet kubeadm
sudo apt-mark hold kubelet kubeadm

Je ne gérerai pas le cluster depuis les nœuds eux-mêmes, jinstalle kubectl sur mon contrôleur LXC à la place :

sudo apt-get update
sudo apt-get install -y kubectl
sudo apt-mark hold kubectl

Initialiser le Cluster

Une fois tous les nœuds préparés, on peut initialiser le plan de contrôle Kubernetes sur le premier nœud master.

Initialisation

Exécutez la commande suivante pour amorcer le cluster:

sudo kubeadm init \
  --control-plane-endpoint "k8s-lab.lab.vezpi.me:6443" \
  --upload-certs \
  --pod-network-cidr=10.10.0.0/16

Explications :

  • --control-plane-endpoint : Nom DNS pour votre plan de contrôle.
  • --upload-certs : Télécharge les certificats qui doivent être partagés entre toutes les masters du cluster.
  • --pod-network-cidr : Sous-réseau à utiliser pour le CNI.

Le nom DNS k8s-lab.lab.vezpi.me est géré dans mon homelab par Unbound DNS, cela résout sur mon interface d'OPNsense où un service HAProxy écoute sur le port 6443 et équilibre la charge entre les 3 nœuds du plan de contrôle.

Cette étape va :

  • Initialiser la base etcd et les composants du plan de contrôle.
  • Configurer RBAC et les tokens damorçage.
  • Afficher deux commandes kubeadm join importantes : une pour les workers, lautre pour les masters supplémentaires.

Vous verrez aussi un message indiquant comment configurer laccès kubectl.

Configurer kubectl

Si vous préférez gérer votre cluster depuis le nœud master, vous pouvez simplement copier-coller depuis la sortie de la commande kubeadm init :

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

Si vous préférez contrôler le cluster depuis autre part, dans mon cas depuis mon bastion LXC :

mkdir -p $HOME/.kube
scp <master node>:/etc/kubernetes/admin.conf $HOME/.kube/config
chmod 600 ~/.kube/config

Vérifiez l'accès :

kubectl get nodes

You devriez voir seulement le premier master listé (dans l'état NotReady jusqu'à ce que le CNI soit déployé).

Installer le Plugin CNI Cilium

Depuis la documentation Cilium, Il y a 2 manières principales pour installer le CNI : utiliser la CLI Cilium ou Help, pour ce lab je vais utiliser l'outil CLI.

Installer la CLI Cilium

La CLI Cilium peut être utilisée pour installer Cilium, inspecter l'état de l'installation Cilium et activer/désactiver diverses fonctionnalités (ex : clustermesh, Hubble) :

CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-amd64.tar.gz{,.sha256sum}
sha256sum --check cilium-linux-amd64.tar.gz.sha256sum
sudo tar xzvfC cilium-linux-amd64.tar.gz /usr/local/bin
rm cilium-linux-amd64.tar.gz{,.sha256sum}

Installer Cilium

Installer Cilium dans le cluster Kubernetes pointé par le contexte kubectl :

cilium install --version 1.17.6

Valider l'Installation

Pour valider que Cilium a été installé correctement :

cilium status --wait

Pour vérifier que votre cluster dispose d'une connectivité réseau appropriée :

cilium connectivity test

Une fois installé, le nœud master doit passer au statut Ready.


Join Additional Nodes

Join Masters

Creating the control-plane join command

Syncing PKI and etcd certs

Running kubeadm join on master 2 and 3

Join Workers

Generating and running the worker kubeadm join command

Verifying node status

Deploying a Sample Application

Creating a simple Deployment and Service

Exposing it via NodePort or LoadBalancer

Verifying functionality

Conclusion

Summary of the steps

When to use this manual method
sudo apt update && sudo apt upgrade -y
sudo apt install -y apt-transport-https ca-certificates curl gpg
sudo systemctl disable --now ufw
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system
sudo apt install -y containerd
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml > /dev/null
sudo sed -i 's/^\(\s*SystemdCgroup\s*=\s*\)false/\1true/' /etc/containerd/config.toml
sudo systemctl restart containerd
sudo systemctl enable containerd
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.32/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.32/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
sudo apt-get update
sudo apt-get install -y kubelet kubeadm
sudo apt-mark hold kubelet kubeadm