Post

Kubernetes sur un unique noeud Debian

Kubernetes sur un unique noeud Debian

Introduction

Ce billet est inspiré de l’article en anglais Deploying Kubernetes Onto A Single Debian 12.1 Host écrit par Ben Tasker.
J’essaierai de le garder à jour avec les dernières versions de Kubernetes et Debian.

Prérequis

Voici les prérequis attendus pour ce guide :

  • Un serveur Debian “Trixie” 13 (13.5.0 au moment de l’écriture)
  • Une IP statique pour le nœud maître
  • Un utilisateur avec des privilèges sudo
  • Un accès à Internet
  • Un serveur NFS pour le stockage des données (optionnel)

Configuration du système

Avant de commencer l’installation de Kubernetes, effectuez quelques préparatifs.

Mettez d’abord votre système à jour et installez les paquets requis.

Le paquet jq n’est utile que pour les étapes de ce guide ; vous pourrez le désinstaller une fois l’installation et la configuration du nœud unique terminées.

1
2
sudo apt update
sudo apt install -y curl jq gnupg2

(Optionnel) Certaines parties de ce guide nécessitent helm :

1
2
3
curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-4
chmod 700 get_helm.sh
./get_helm.sh

Même si Kubernetes peut fonctionner avec le swap dans ses dernières versions1, il est recommandé de le désactiver :

1
2
sudo swapoff -a
sudo sed -i '/ swap / s/^[^#]/#&/' /etc/fstab

Activation du routage des paquets IPv4, permettant aux Pods de communiquer entre eux :

1
2
3
4
5
cat <<EOF | sudo tee /etc/sysctl.d/99-kubernetes-k8s.conf
net.ipv4.ip_forward = 1
EOF

sudo sysctl --system

Installation de containerd en tant que runtime de conteneurs (CRI) ; vous pouvez également opter pour cri-o si vous le préférez.

1
2
sudo apt update
sudo apt install -y containerd

Création du fichier de configuration de containerd :

1
2
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

Passez la valeur de SystemdCgroup de false à true dans la section plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options.
Cela permet à containerd de fonctionner correctement avec systemd :

1
cat /etc/containerd/config.toml | sed 's/SystemdCgroup = false/SystemdCgroup = true/' | sudo tee /etc/containerd/config.toml

Activation et redémarrage de containerd :

1
2
sudo systemctl enable containerd
sudo systemctl restart containerd

Installation de Kubernetes

Il est temps d’installer Kubernetes.

Ajoutez la clé GPG de Kubernetes ; vous pouvez remplacer v1.36 par la version de Kubernetes que vous souhaitez installer :

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

Sur les versions antérieures à Debian 12 et Ubuntu 22.04, vous devez créer le répertoire /etc/apt/keyrings avant d’exécuter la commande curl précédente.

Ajoutez le dépôt Kubernetes ; ici aussi, vous pouvez remplacer v1.36 par la version de Kubernetes que vous souhaitez installer :

1
2
3
4
5
6
7
cat <<EOF | sudo tee /etc/apt/sources.list.d/kubernetes.sources
Types: deb
URIs: https://pkgs.k8s.io/core:/stable:/v1.36/deb/
Suites: /
Components:
Signed-By: /etc/apt/keyrings/kubernetes-apt-keyring.gpg
EOF

Installez les paquets nécessaires :

1
2
sudo apt update
sudo apt install -y kubeadm kubelet kubectl

Bloquez les mises à jour automatiques des paquets :

1
sudo apt-mark hold kubeadm kubelet kubectl

Initialisation du nœud maître

Récupérez les images nécessaires pour Kubernetes :

1
sudo kubeadm config images pull

Initialisez le nœud maître en utilisant son IP :

1
sudo kubeadm init --control-plane-endpoint=$(hostname -I | awk '{print $1}')

Cela va prendre un certain temps. Une fois terminé, vous verrez le message suivant : Your Kubernetes control-plane has initialized successfully!

S’il ne s’est pas initialisé correctement, consultez la section Debugging à la fin de ce guide.

Pour configurer kubectl pour votre utilisateur, exécutez les commandes suivantes :

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

Vous devriez désormais pouvoir interagir avec votre cluster Kubernetes sans utiliser sudo :

1
kubectl get nodes

(optionnel) Vous pouvez activer l’autocomplétion de kubectl et l’ajouter à votre fichier .bashrc :

1
2
source <(kubectl completion bash)
echo "source <(kubectl completion bash)" | tee -a ~/.bashrc

Installation du réseau

Pour que les Pods puissent communiquer entre eux, vous devez installer un réseau. Plusieurs solutions sont disponibles, mais les plus courantes sont cilium, calico et flannel. Cette action ne doit être effectuée qu’une seule fois, après l’initialisation du nœud maître.

Utilisation de cilium

L’installation de cilium sur le cluster requiert la présence de la CLI cilium sur votre machine.

Téléchargement de la dernière version de la CLI cilium :

1
2
3
4
5
6
7
8
CILIUM_CLI_VERSION=$(curl -s https://raw.githubusercontent.com/cilium/cilium-cli/main/stable.txt)
CLI_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then CLI_ARCH=arm64; fi
(cd /tmp && curl -L --fail --remote-name-all https://github.com/cilium/cilium-cli/releases/download/${CILIUM_CLI_VERSION}/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum}) && \
(cd /tmp && sha256sum --check cilium-linux-${CLI_ARCH}.tar.gz.sha256sum) && \
sudo tar -C /usr/local/bin -xzf /tmp/cilium-linux-${CLI_ARCH}.tar.gz && \
rm /tmp/cilium-linux-${CLI_ARCH}.tar.gz{,.sha256sum} && \
cilium version --client

Vérification de l’installation du client cilium :

1
cilium version --client

Installation de cilium sur le cluster avec la dernière version disponible :

1
cilium install

Il est possible d’imposer une version précise de cilium lors de l’installation :

1
cilium install --version v1.16.1

Containerd et Coredns s’attendent à ce que le CNI soit installé dans /usr/lib/cni ; nous devons donc créer un lien symbolique de /opt/cni/bin vers /usr/lib/cni :

1
sudo ln -s /opt/cni/bin /usr/lib/cni

Validation de l’installation ; cela peut prendre quelques minutes avant que tout soit prêt :

1
cilium status --wait

Test de connectivité, à effectuer une fois le cluster configuré en nœud unique, ou après l’ajout de nouveaux nœuds :

1
cilium connectivity test

Configuration en tant que nœud unique

Jusqu’à présent, rien de ce qui a été fait n’était spécifique à un nœud unique. Quelques ajustements restent toutefois nécessaires pour que Kubernetes fonctionne correctement sur un seul nœud.

En l’absence d’autres nœuds, il est impossible d’exécuter quoi que ce soit dans le cluster, car Kubernetes applique un taint sur le nœud maître afin d’empêcher tout Pod d’y être planifié. Pour contourner cela, vous pouvez supprimer ce taint :

Affichez les taints de votre unique nœud :

1
kubectl get nodes -o json | jq '.items[].spec.taints'

Cela devrait afficher quelque chose comme :

1
2
3
4
5
6
[
  {
    "effect": "NoSchedule",
    "key": "node-role.kubernetes.io/control-plane"
  }
]

(Si vous avez installé une ancienne version, le taint peut se présenter sous la forme node-role.kubernetes.io/master)

On supprime le taint :

1
kubectl taint nodes $HOSTNAME node-role.kubernetes.io/control-plane:NoSchedule-

(Notez le - à la fin de la commande pour supprimer le taint)

Si vous récupérez à nouveau les taints, vous devriez voir que le taint a été supprimé.

1
kubectl get nodes -o json | jq '.items[].spec.taints'

Après quelques instants, vous devriez voir que vos Pods sont en cours d’exécution :

1
kubectl get pods --all-namespaces

Si vous avez installé cilium, vous pouvez maintenant vérifier le bon fonctionnement de la connectivité.

Ajout d’un StorageClass NFS

Pour plus de simplicité, j’utilise pour mes déploiements un fournisseur de stockage NFS, qui range automatiquement les données dans un sous-dossier d’un partage NFS.

Vous pouvez trouver plus d’informations sur le GitHub du projet nfs-subdir-external-provisioner.

L’approche la plus pratique est d’utiliser Helm pour installer le fournisseur NFS.

Vous devez d’abord installer le client NFS. Cette étape est à effectuer sur tous les nœuds, existants comme futurs ; n’oubliez pas non plus d’autoriser ces nœuds à accéder au serveur NFS :

1
2
sudo apt update
sudo apt install -y nfs-common

Ensuite, installez le fournisseur NFS avec Helm :

1
2
3
4
5
6
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner/
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
    --namespace kube-infra \
    --create-namespace \
    --set nfs.server=<IP SERVEUR NFS> \
    --set nfs.path=/exported/path

Si vous avez un doute sur le chemin NFS à utiliser, vous pouvez le trouver en exécutant la commande suivante :

1
sudo showmount -e <IP SERVEUR NFS>

(optionnel) Si vous souhaitez utiliser le StorageClass NFS par défaut, vous pouvez le définir comme suit :

1
kubectl patch storageclass nfs-client -p '{"metadata": {"annotations":{"storageclass.kubernetes.io/is-default-class":"true"}}}'

Installation de kubelet-csr-approver

Pour simplifier la gestion des certificats, mais aussi pour assurer le bon fonctionnement du metrics-server, il est judicieux d’installer kubelet-csr-approver.

Pour ce faire, vous pouvez utiliser le helm chart suivant, en remplaçant la plage d’adresses IP par celle de votre réseau :

1
2
3
4
helm repo add kubelet-csr-approver https://postfinance.github.io/kubelet-csr-approver
helm install kubelet-csr-approver kubelet-csr-approver/kubelet-csr-approver -n kube-system \
  --set providerIpPrefixes='10.6.9.0/24' \
  --set bypassDnsResolution='true'

Le paramètre providerIpPrefixes permet de spécifier les plages d’adresses IP autorisées à approuver les certificats. Le second paramètre, bypassDnsResolution, défini à true, permet de ne pas résoudre les noms de domaine.

D’autres paramètres peuvent être spécifiés ; pour les découvrir, consultez la documentation du projet à l’adresse suivante : https://github.com/postfinance/kubelet-csr-approver?tab=readme-ov-file#parameters

Activation du serverTLSBootstrap

Le serverTLSBootstrap est une fonctionnalité qui permet aux nœuds de générer leurs propres certificats pour communiquer avec le cluster.

Pour activer cette fonctionnalité, vous devez ajouter les paramètres suivants dans le fichier de configuration de kubelet sur chaque nœud :

1
2
echo "serverTLSBootstrap: true" | sudo tee -a /var/lib/kubelet/config.yaml
sudo systemctl restart kubelet

Cela va générer un CSR (Certificate Signing Request) pour chaque nœud, que kubelet-csr-approver va approuver automatiquement.

Vous pouvez voir les certificats approuvés en exécutant la commande suivante :

1
kubectl get csr

Installation de metrics-server

Le metrics-server est un composant qui collecte les métriques de l’ensemble du cluster Kubernetes. Il est indispensable au fonctionnement des HPA (Horizontal Pod Autoscaler) et de la commande kubectl top.

Pour l’installer, vous pouvez utiliser le manifeste suivant :

1
kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

Vérification de l’installation ; cela peut prendre quelques minutes avant que tout soit prêt :

1
kubectl get deployment metrics-server -n kube-system

Récupération des données directement depuis l’API metrics :

1
kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes" | jq . || kubectl get --raw "/apis/metrics.k8s.io/v1beta1/nodes"

Récupération des métriques depuis kubectl :

1
2
kubectl top nodes
kubectl top pods --all-namespaces

Installation de k9s

k9s est un outil en ligne de commande qui permet de gérer et de visualiser les ressources Kubernetes.
Vous pouvez l’installer en téléchargeant la dernière version depuis la page GitHub du projet.

Vous trouverez plus d’informations sur le projet à l’adresse suivante : https://k9scli.io/

Téléchargement de la dernière version de k9s :

1
2
3
4
5
6
7
8
9
K9S_VERSION=$(curl -s https://api.github.com/repos/derailed/k9s/releases/latest | jq -r .tag_name)
K9S_ARCH=amd64
if [ "$(uname -m)" = "aarch64" ]; then K9S_ARCH=arm64; fi
(cd /tmp && curl -L --fail --remote-name-all https://github.com/derailed/k9s/releases/download/${K9S_VERSION}/k9s_Linux_${K9S_ARCH}.tar.gz) && \
(cd /tmp && curl -L --fail --remote-name-all https://github.com/derailed/k9s/releases/download/${K9S_VERSION}/checksums.sha256) && \
(cd /tmp && sha256sum --check checksums.sha256 --ignore-missing) && \
sudo tar -C /usr/local/bin -xzf /tmp/k9s_Linux_${K9S_ARCH}.tar.gz && \
rm /tmp/k9s_Linux_${K9S_ARCH}.tar.gz /tmp/checksums.sha256 && \
k9s version

Puis lancez k9s :

1
k9s

Ajout de nœuds supplémentaires

Si vous souhaitez ajouter d’autres nœuds à votre cluster, vous pouvez utiliser la commande kubeadm join sur le nœud à ajouter :

1
sudo kubeadm join <ip nœud maître>:6443 --token <token> --discovery-token-ca-cert-hash sha256:<hash>

Vous pouvez obtenir le token et le hash en exécutant la commande suivante sur le nœud maître :

1
sudo kubeadm token create --print-join-command

(optionnel) Remise en place du taint sur le nœud maître, si vous ne souhaitez pas exécuter de Pods sur le nœud maître :

1
sudo kubectl taint nodes $HOSTNAME node-role.kubernetes.io/control-plane:NoSchedule

(optionnel) Installation de NFS sur le nœud nouvellement ajouté :

1
2
sudo apt update
sudo apt install -y nfs-common

Ajout du kubeconfig sur le nœud nouvellement ajouté :

1
mkdir -p $HOME/.kube

Copiez le fichier de configuration /etc/kubernetes/admin.conf du nœud maître dans le fichier $HOME/.kube/config du nœud nouvellement ajouté :

1
nano $HOME/.kube/config

Puis modifiez les droits :

1
2
sudo chown $(id -u):$(id -g) $HOME/.kube/config
sudo chmod 600 $HOME/.kube/config

Debugging

Si vous rencontrez des problèmes lors de l’installation ou de l’utilisation de Kubernetes, vous pouvez consulter les journaux de kubelet pour obtenir des informations supplémentaires :

1
sudo journalctl -xeu kubelet

Vous pouvez aussi réinitialiser le nœud avec la commande suivante, qui le remet dans son état initial :

1
sudo kubeadm reset

Si le test de connectivité de cilium échoue et laisse des objets sur le cluster, vous pouvez les supprimer avec la commande suivante (qui requiert jq) :

1
kubectl delete namespace $(kubectl get namespaces -o json | jq -r '.items[] | select(.metadata.name | startswith("cilium-test")) | .metadata.name')
  1. https://kubernetes.io/docs/concepts/cluster-administration/swap-memory-management/#swap-and-control-plane-nodes ↩︎

This post is licensed under CC BY 4.0 by the author.