Blog Zenika

#CodeTheWorld

DevOpsFabLab

K3S sur un cluster de Raspberry Pi

Afin de présenter à des étudiants les avantages et inconvénients d’une architecture microservices, j’ai voulu déployer sur un cluster de Raspberry Pi 3 B des instances de k3s, une version allégée de Kubernetes, pour illustrer les capacités de scalabilité et de résilience d’un orchestrateur de conteneurs. Je vous propose de m’accompagner dans l’installation et la configuration de celui-ci, avec son lot de déconvenues et, je l’espère, d’astuces qui pourront vous aider si vous tenter l’expérience vous-même.


Le matériel

Le matériel que j’ai utilisé (un kit Pico 5), initialement prêté à @eric_briand pour expérimenter sur l’éco-conception logicielle, se compose des éléments suivants :

  • 5 Raspberry 3B et des cartes SD 64Go pour héberger les OS et systèmes de fichiers
  • une alimentation externe
  • un switch réseau pour connecter les nodes entre eux
  • une prise RJ45 externe pour se connecter au switch en Ethernet

La prise réseau externe fut particulièrement utile à des fins de configuration ou pour se connecter directement au master sans passer par le réseau local, comme nous le verrons après.

Le tout est présenté dans un boîtier en plaques acryliques à monter soi-même, ce qui permet d’apprécier les lumières clignotantes du cluster et remplace aisément un sapin en ces périodes de fêtes (bon, j’ai en effet un peu de retard dans la livraison de cet article…).

Installation de l’OS

Afin de profiter d’un OS maintenu à jour avec la Raspbian Lite (distribution Linux très légère à destination des processeurs ARM) et disposant d’outils de configuration et de conteneurisation, le choix s’est porté sur HypriotOS. Cette distribution orientée conteneurs comprend cloud-init qui m’a été fort utile pour l’initialisation et la configuration du Wi-Fi. L’utilisation de l’outil flash, fourni par Hypriot, avec l’ajout d’un hostname et l’utilisation d’un fichier user-data personnalisé a permis de démarrer les différents Raspberry et de les connecter à notre réseau local afin de poursuivre l’installation.

Exemple d’une commande pour flasher l’image sur la carte SD : 

flash -n master -u wifi-user-data.yaml https://github.com/hypriot/image-builder-rpi/releases/download/v1.11.0/hypriotos-rpi-v1.11.0.img.zip

Le fichier wifi-user-data.yaml est une version modifiée de celui-ci avec nos paramètres Wi-Fi. Préciser le hostname avec l’option -n surcharge l’information contenue dans le fichier user-data.

Pour mon installation, j’ai utilisé les noms suivants pour différencier les nodes du cluster: master, node01, node02, node03 et node04. L’avantage de les nommer est de pouvoir les retrouver simplement via ssh pour lancer l’installation de k3s, comme nous allons le voir juste après.

Mise en place du serveur k3s

Mettons maintenant en place le serveur sur le node master. Il faut pour cela se connecter en ssh à celui-ci: ssh pirate@master.local (password: hypriot)

Les identifiants et mots de passe peuvent être changés via le fichier user-data à l’initialisation du Raspberry. J’ai laissé les valeurs par défaut pour des raisons de simplicité dans un premier temps, mais il est évidemment nécessaire de créer des utilisateurs avec des mots de passe différents et robustes pour chacun des nodes. Par défaut les Raspberry sont accessibles via ssh avec <identifiant>@<hostname>.local tel que nous les avons configurés précédemment.

Le script d’installation fourni par Rancher sur le repo Github de k3s permet de récupérer automatiquement l’exécutable adapté à l’architecture ainsi que divers utilitaires et scripts pour gérer le service :

curl -sfL https://get.k3s.io | sh -

Il est bien entendu recommandé de jeter un œil sur le script install.sh avant de l’exécuter dans un shell sur votre machine.

Le lancement du serveur k3s va être ajouté en tant que service dans systemd, ce qui permettra son démarrage automatique au branchement du Raspberry ou lors d’un reboot.

On notera l’existence d’un script k3s-killall.sh, qui arrête tous les processus système liés à k3s afin de relancer proprement l’exécutable, une commande que j’aurais beaucoup utilisée lors de l’installation et de la configuration des agents k3s.

Mise en place des nœuds k3s

Afin d’installer et de configurer correctement k3s sur les autres Raspberry, il nous faut récupérer le token généré par le serveur à son installation, ainsi que l’adresse IP de celui-ci. Et c’est à ce moment-là que les ennuis ont commencé pour moi… La récupération du token est aisée, une simple commande sudo cat /var/lib/rancher/k3s/server/node-token sur le master l’affiche. Nous le passerons en variable d’environnement au lancement de l’agent. Pour la récupération de l’IP du serveur c’est une autre histoire. Il m’a fallu de nombreux tâtonnements et moult ifconfig sur le master avant de comprendre que je devais utiliser l’adresse associée au Wi-Fi pour connecter les agents au master :

ifconfig wlan0 | grep -w inet | awk '{print $2}'

La raison est que k3s utilise un certificat généré à l’installation du master pour sécuriser la communication avec l’API et que celui-ci est exposé uniquement sur l’adresse wlan, empêchant la connexion depuis une autre adresse. La commande pour l’installation des agents est la suivante, à répéter sur chaque Raspberry restant :

curl -sfL https://get.k3s.io | K3S_URL=https://<ip_wlan_du_noeud>:6443 K3S_TOKEN=<node_token> sh -

Ces commandes devraient lancer le téléchargement et la configuration des agents. Une fois terminé il est possible de vérifier le bon fonctionnement de ceux-ci en se connectant sur le master et en lançant la commande :

sudo kubectl get nodes

On notera que j’ai commencé à assigner des labels au différents nœuds et master à l’aide de la commande sudo kubectl label node <hostname> kubernetes.io/<master_or_node> depuis le master.

Il est possible (ce fut le cas pour moi à de multiples reprises…) que malgré une installation sans problème, ou lors du redémarrage du cluster, les nodes ne parviennent pas à se connecter au master, pour des raisons que j’ignore. Ma solution, un peu cavalière, j’en conviens, mais d’une efficacité redoutable : se connecter en ssh au node et reboot!! lancer les commandes suivantes :

sudo k3s-killall.sh 
sudo k3s agent -server https://<ip_wlan_du_noeud>:6443 -token <node_token>

A ce sujet, il devient fastidieux de changer de machine en ssh ou de naviguer entre les différent terminaux dans tmux, aussi je vous propose d’installer kubectl et de le configurer pour accéder à notre cluster. Pour pouvoir agir sur le master de façon transparente, il nous reste à récupérer la configuration du cluster sur celui-ci, modifier l’adresse du serveur et nommer le fichier .kube /config dans votre répertoire personnel. J’ai utilisé scp pour copier le fichier via ssh :

scp pirate@master.local:/etc/rancher/k3s/k3s.yaml .

Vous devrez remplacer ‘127.0.0.1’ par l’adresse ip wlan du master à ligne “server : https://127.0.0.1:6443&#8221;

Puis renommer et déplacer le fichier :

mv k3s.yaml ~/.kube/config

Cela va nous permettre de lancer toutes les commandes depuis notre machine favorite, sans sudo et nous simplifiera la vie pour lancer et accéder au Dashboard.

Installation du Dashboard

Commençons par déployer les éléments nécessaires avec la commande :

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta8/aio/deploy/recommended.yaml

Et vérifions que tout s’est déployé correctement :

kubectl get all -n kubernetes-dashboard

Nous devons ensuite créer un ServiceAccount et un Role pour avoir le droit d’accéder au Dashboard et d’effectuer des modifications ou des déploiements sur le cluster :

cat >> dashboard-adminuser.yaml <<EOF
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
EOF

Puis appliquer les modifications :

kubectl apply -f dashboard-adminuser.yaml

Il nous faut ensuite utiliser la commande kubectl proxy &, ce qui va exposer celui-ci à l’adresse suivante, accessible dans notre navigateur web : http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

Attention, le dashboard ne sera accessible que depuis la machine sur laquelle la commande de proxy a été lancée.

Reste à se connecter à celui-ci avec le token lié au serviceAccount créé précédemment. La commande suivante permet de récupérer le token :

kubectl -n kubernetes-dashboard describe secret $(kubectl -n kubernetes-dashboard get secret | grep admin-user | awk '{print $1}') 

Copiez et collez la valeur de celui-ci dans le champ “Saisissez un jeton” :

You’re in, well done! On peut maintenant aller vérifier la bonne santé de nos nodes.

Ne reste plus qu’à trouver un magnifique projet microservice à déployer sur notre beau cluster tout neuf! Pour l’instant je n’ai pas trouvé de projet de démo simple à déployer, les projets existants comme Sock shop ou Hipster Shop de GoogleCloudPlatform utilisent des fonctionnalités de Kubernetes non présentes ici… Je ne désespère pas de réussir à modifier subtilement les manifests pour faire fonctionner l’un des deux d’ici peu.

Pour conclure

A posteriori, je me rends compte qu’une meilleure connaissance des problématiques d’adressage réseau et du fonctionnement interne du cluster m’aurait probablement évité de m’arracher les cheveux (qu’il me reste) sur la connexion des agents au serveur.

Après consultation des collègues plus au point que moi sur le sujet, une solution à envisager pour éviter de dépendre du réseau local et d’une connexion Wifi est de se connecter en Ethernet et d’utiliser son poste de travail comme serveur DHCP. Cela permettrait de s’abstraire de la configuration du Wi-Fi faite en début d’article et de s’assurer de toujours pouvoir communiquer avec le cluster.

Enfin malgré tous mes efforts, je n’ai toujours pas réussi à adapter un des projets cités ci-dessus à k3s, mes pods tombant presque tous dans l’enfer du CrashLoopBackoff. Malgré ces écueils, l’installation est assez aisée et permet de monter rapidement un environnement de démonstration pour les fonctionnalités d’un orchestrateur et les avantages et inconvénients d’une architecture microservices.

Un grand merci à @pyaillet et @eric_briand pour leur conseils avisés.

Sources:

https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard

https://github.com/kubernetes/dashboard/blob/master/docs/user/access-control/creating-sample-user.md

Auteur/Autrice

Laisser un commentaire

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.