Pourquoi un homelab sur Raspberry Pi ?
512 Mo. C’est tout ce que k3s laisse de marge sur un master à 8 Go de RAM une fois etcd et le kube-apiserver lancés. La question revient souvent : pourquoi s’infliger cette contrainte alors que des crédits cloud sont disponibles gratuitement ? Parce que la contrainte est le meilleur enseignant. Sur un RPi avec 8 Go de RAM partagés entre l’etcd, le kube-apiserver et une dizaine de pods applicatifs, chaque mégaoctet compte. Cette contrainte force une compréhension profonde de ce que consomment réellement les composants Kubernetes.
Ce cluster a été conçu avec un objectif clair : reproduire les pratiques d’une infrastructure cloud-native en production, mais sur du matériel personnel, avec un budget maîtrisé.
Architecture matérielle
Le cluster est composé de 6 nœuds Raspberry Pi :
| Nœud | Modèle | RAM | Rôle | IP |
|---|---|---|---|---|
| master-1 | RPi 4 | 8 GB | control-plane + etcd | 10.0.0.11 |
| master-2 | RPi 4 | 8 GB | control-plane + etcd | 10.0.0.12 |
| master-3 | RPi 4 | 8 GB | control-plane + etcd | 10.0.0.13 |
| worker-1 | RPi 5 | 16 GB | worker principal | 10.0.0.21 |
| worker-2 | RPi 5 | 16 GB | worker principal | 10.0.0.22 |
| worker-3 | RPi 4 | 2 GB | worker auxiliaire | 10.0.0.23 |
Les masters utilisent des cartes SD 32 Go pour le système d’exploitation, avec des SSD NVMe via USB 3.0 pour le stockage Longhorn. Les workers RPi 5 disposent de SSD M.2 via HAT officiel, ce qui offre des performances sensiblement meilleures.
Réseau : tous les nœuds sont connectés en filaire Gigabit Ethernet via un switch non managé. Les IPs sont fixes via réservations DHCP sur le routeur. Pas de VLAN pour cette version — simplicité avant tout.
Choix de k3s
K3s s’est imposé face à kubeadm pour plusieurs raisons :
- Empreinte mémoire réduite : k3s consomme ~512 Mo sur les masters contre ~1,5 Go pour un cluster kubeadm standard.
- Binaire unique : un seul exécutable regroupe tous les composants du control-plane. Moins de moving parts à gérer.
- etcd intégré : k3s embarque une distribution etcd gérée automatiquement, parfaite pour un HA à 3 nœuds.
- ARM64 natif : images officielles pour armv7 et arm64, sans bidouille.
La seule limitation notable : k3s utilise sa propre implémentation de certaines fonctionnalités (notamment le datastore), ce qui peut créer de légères divergences avec un cluster Kubernetes “vanilla”. En pratique, cela n’a jamais posé de problème.
Bootstrap du cluster
Premier master
# Sur master-1
curl -sfL https://get.k3s.io | sh -s - server \
--cluster-init \
--tls-san 10.0.0.11 \
--tls-san k3s.local \
--disable traefik \
--disable servicelb \
--node-label node-type=master
L’option --disable traefik est intentionnelle : Traefik sera installé via Helm avec une configuration personnalisée, pas via le bundle k3s. --cluster-init initialise un nouveau cluster etcd.
# Récupérer le token pour les autres nœuds
sudo cat /var/lib/rancher/k3s/server/node-token
Masters additionnels
# Sur master-2 (adapter --tls-san à chaque nœud : 10.0.0.12 ou 10.0.0.13)
curl -sfL https://get.k3s.io | sh -s - server \
--server https://10.0.0.11:6443 \
--token <TOKEN> \
--tls-san 10.0.0.12 \
--disable traefik \
--disable servicelb \
--node-label node-type=master
Workers
# Sur chaque worker
curl -sfL https://get.k3s.io | K3S_URL=https://10.0.0.11:6443 \
K3S_TOKEN=<TOKEN> sh -s - agent \
--node-label node-type=worker
Après quelques minutes :
$ sudo kubectl get nodes
NAME STATUS ROLES AGE VERSION
master-1 Ready control-plane,etcd,master 5m v1.34.3+k3s1
master-2 Ready control-plane,etcd,master 4m v1.34.3+k3s1
master-3 Ready control-plane,etcd,master 4m v1.34.3+k3s1
worker-1 Ready <none> 3m v1.34.3+k3s1
worker-2 Ready <none> 3m v1.34.3+k3s1
worker-3 Ready <none> 2m v1.34.3+k3s1
Haute disponibilité — comment ça marche ?
Le HA dans k3s repose sur trois mécanismes :
1. Quorum etcd : avec 3 masters, le cluster peut survivre à la perte d’un nœud. etcd requiert (n/2)+1 membres pour atteindre le quorum — soit 2 sur 3. La perte simultanée de 2 masters entraîne une interruption du control-plane (les workloads existants continuent néanmoins de tourner sur les workers).
2. Kube-apiserver distribué : chaque master expose l’API Kubernetes. En cas de panne d’un master, kubectl et les controllers basculent automatiquement sur les masters restants. La configuration KUBECONFIG pointe vers une IP de master, idéalement derrière un load-balancer (ici, non implémenté — amélioration future).
3. Self-healing : le kubelet sur chaque nœud redémarre les pods crashés. k3s lui-même est configuré comme service systemd avec Restart=always.
API server répond API server responds
Les 3 masters votent. Quorum largement atteint. All 3 masters vote. Quorum comfortably reached.
API toujours dispo · requêtes re-routées API still available · requests re-routed
Quorum maintenu (2 ≥ (3/2)+1=2). Le control-plane survit. Quorum maintained (2 ≥ (3/2)+1=2). The control-plane survives.
Quorum perdu · control-plane interrompu Quorum lost · control-plane interrupted
Mais les pods déjà schedulés continuent de tourner sur les workers. But the already scheduled pods keep running on the workers.
2 sur 3.
On survit à 1 master perdu, pas à 2 : au-delà, le control-plane
s’arrête, mais les workloads déjà schedulés tiennent sur les workers.
Configuration de kubectl en local
Pour éviter de se connecter en SSH à chaque commande :
# Copier le kubeconfig depuis master-1
scp [email protected]:/etc/rancher/k3s/k3s.yaml ~/.kube/config
# Modifier l'IP du serveur
sed -i 's/127.0.0.1/10.0.0.11/g' ~/.kube/config
chmod 600 ~/.kube/config
Leçons apprises
Labels de nœuds dès le départ : les nodeSelector dans les manifests dépendent des labels. Définir node-type=master et node-type=worker à l’installation évite de faire du rattrapage plus tard.
Désactiver les composants bundlés : k3s inclut Traefik et ServiceLB par défaut. Les désactiver dès le bootstrap (--disable traefik --disable servicelb) évite des conflits lors de l’installation de versions Helm.
Stockage des masters : utiliser des SSD même pour les masters. La carte SD sous charge etcd se dégrade rapidement. Un SSD USB 3.0 à 20€ change tout.
worker-3 à 2 Go : ce nœud s’est avéré trop limité pour héberger des workloads substantiels. Il sert aujourd’hui principalement à augmenter le quorum Longhorn (3e réplique) pour les volumes qui le nécessitent. Ne jamais sous-estimer la RAM minimale pour les agents Kubernetes.
Pour aller plus loin
La suite logique : chiffrer les secrets Kubernetes avant de les committer dans Git avec Sealed Secrets, puis automatiser les déploiements avec ArgoCD.