Aller au contenu
Conteneurs & Orchestration medium

Mixer des nœuds ARM et AMD64 dans un cluster k3s

8 min de lecture

logo k3s

Mélanger des Raspberry Pi (ARM) et des machines x86 dans un même cluster k3s fonctionne nativement : l'agent détecte son architecture, et le bon label se pose tout seul. Le réflexe moderne n'est pas de forcer chaque pod sur une architecture, mais d'utiliser des images multi-architecture que Kubernetes tire automatiquement selon le nœud. Ce guide montre comment ajouter un nœud ARM, exploiter les images multi-arch, et cibler une architecture avec nodeSelector ou nodeAffinity quand c'est nécessaire. Pour utilisateurs Kubernetes intermédiaires. Commandes validées sur k3d (k3s 1.31).

  • Ajouter un nœud ARM à un cluster k3s
  • Comprendre le tirage automatique des images multi-architecture
  • Cibler une architecture avec nodeSelector et nodeAffinity
  • Isoler des nœuds avec taints et tolerations
  • Un cluster k3s existant (voir installer k3s)
  • Une ou plusieurs machines ARM (Raspberry Pi en OS 64 bits pour viser arm64)

k3s est disponible pour x86_64 (AMD64), arm64/aarch64 et armhf (ARM 32 bits). L'agent télécharge le binaire correspondant à sa plateforme : il n'y a aucun paramètre d'architecture à passer.

Récupérez d'abord le token sur le nœud serveur :

Fenêtre de terminal
sudo cat /var/lib/rancher/k3s/server/node-token

Puis, sur le Raspberry Pi, lancez l'agent en pointant vers le serveur :

Fenêtre de terminal
curl -sfL https://get.k3s.io | \
K3S_URL=https://<ip-serveur>:6443 \
K3S_TOKEN=<token> sh -

Le kubelet pose automatiquement les labels bien connus kubernetes.io/arch et kubernetes.io/os sur chaque nœud. L'option -L les affiche en colonnes :

Fenêtre de terminal
kubectl get nodes -L kubernetes.io/arch -L kubernetes.io/os
NAME STATUS ROLES VERSION ARCH OS
k3d-cairn-server-0 Ready control-plane,master v1.31.5+k3s1 amd64 linux

Le réflexe moderne : les images multi-architecture

Section intitulée « Le réflexe moderne : les images multi-architecture »

C'est le point que beaucoup de vieux tutoriels ratent. Une image multi-architecture embarque une manifest list (un index OCI) qui pointe vers une variante par plateforme. Quand un nœud tire l'image, le registre renvoie l'index et Kubernetes choisit automatiquement la variante de l'architecture du nœud. Inspectez n'importe quelle image officielle :

Fenêtre de terminal
docker buildx imagetools inspect nginx:1.27-alpine
MediaType: application/vnd.oci.image.index.v1+json
Platform: linux/amd64
Platform: linux/arm/v6
Platform: linux/arm64
...

Conséquence directe : avec une image multi-arch (la plupart des images officielles le sont), vous n'avez aucun nodeSelector à écrire. Le même Deployment tourne sur vos Pi et vos x86, chacun tirant sa variante. Pour vos propres images, construisez-les multi-arch avec buildx :

Fenêtre de terminal
docker buildx build --platform linux/amd64,linux/arm64 --push -t monorg/monimage:1.0 .

Le --push est requis : le driver docker-container pousse directement la manifest list au registre.

Le ciblage explicite ne sert que dans deux cas : une image mono-architecture, ou un placement délibéré (réserver les Pi à certains workloads). La forme la plus simple est nodeSelector :

apiVersion: apps/v1
kind: Deployment
metadata:
name: web-arm
spec:
replicas: 1
selector:
matchLabels: { app: web-arm }
template:
metadata:
labels: { app: web-arm }
spec:
nodeSelector:
kubernetes.io/arch: arm64
containers:
- name: web
image: nginx:1.27-alpine

nodeSelector est une contrainte dure et n'accepte qu'une égalité. Pour autoriser plusieurs architectures, passez à nodeAffinity avec l'opérateur In :

spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: kubernetes.io/arch
operator: In
values: ["amd64", "arm64"]

Les deux formes ont été validées en lab (rollout réussi). Retenez la distinction : required... est une contrainte dure (le pod reste Pending si rien ne correspond), tandis que preferred... (pondéré de 1 à 100) n'est qu'une préférence, le pod est placé ailleurs à défaut.

Pour qu'un nœud ARM ne reçoive que des workloads explicitement autorisés (les Pi sont lents, on veut les réserver), tachez-le (taint) :

Fenêtre de terminal
kubectl taint nodes rpi-01 arch=arm64:NoSchedule

Plus aucun pod n'y est planifié, sauf ceux qui portent la toleration correspondante :

spec:
tolerations:
- key: "arch"
operator: "Equal"
value: "arm64"
effect: "NoSchedule"

Différence à garder en tête : nodeSelector/nodeAffinity attirent un pod vers des nœuds ; les taints repoussent les pods d'un nœud. On les combine souvent (cibler l'arch et tolérer le taint).

SymptômeCauseSolution
exec format error puis CrashLoopBackOffimage compilée pour une autre architectureutiliser une image multi-arch, ou cibler l'arch de l'image
Image qui marche en dev, casse sur le clusterQEMU émule l'ARM sur votre Mac, pas sur les nœudstester sur du matériel natif
Pod Pending sans raisonnodeSelector d'une arch absente du clustervérifier kubectl get nodes -L kubernetes.io/arch
Image arm64 refusée sur un Pil'OS du Pi est en 32 bits (arm, armhf)réinstaller un OS 64 bits, ou viser arm

Le exec format error est le plus fréquent : c'est le noyau qui ne sait pas exécuter un binaire d'une autre architecture. La parade est toujours la même, l'image multi-architecture.

  • k3s gère nativement AMD64, arm64 et armhf ; l'agent détecte son architecture, aucun paramètre à passer.
  • Le kubelet pose kubernetes.io/arch automatiquement (beta.kubernetes.io/arch est déprécié).
  • Les images multi-architecture sont la clé : Kubernetes tire la bonne variante par nœud, sans nodeSelector.
  • Construisez vos images multi-arch avec docker buildx build --platform linux/amd64,linux/arm64 --push.
  • Ciblez une architecture avec nodeSelector (simple) ou nodeAffinity (plusieurs arch, In) seulement si l'image est mono-arch ou pour un placement voulu.
  • exec format error + CrashLoopBackOff = mauvaise architecture d'image ; la réponse est l'image multi-arch.

Ce site vous est utile ?

Sachez que moins de 1% des lecteurs soutiennent ce site.

Je maintiens +700 guides gratuits, sans pub ni tracking. Un soutien, même symbolique, m'aide à couvrir l'hébergement et à garder ces ressources gratuites. Merci pour votre appui.

Le formulaire ne s'affiche pas ? Ouvrir Ko-fi dans un onglet.

Abonnez-vous et suivez mon actualité DevSecOps sur LinkedIn