image de mise en avant pour l'article comment installer Kubernetes sur Ubuntu 22.04

comment installer un cluster Kubernetes sur Ubuntu 22.04

Temps de lecture estimé: 8 minutes

Je suis en train de faire évoluer la manière dont je gère mes environnements de développement et de prod.

J’ai actuellement un Hyperviseur Vmware Esxi qui fait tourner une machine virtuelle Linux (Ubuntu). C’est mon serveur principal et tous mes services, applications et site web sont sur ce même serveur de façon un peu monolithique.

MySql, apache, PostgreSQL, mon instance Gitlab, mon site CV, ce blog WordPress quelques autres services tournent sur le même serveur, côte à côte, et non dissociés.

J’ai envie de scinder tout ça et au passage de faire joujou d’améliorer la façon dont je déploie mes projets en y ajoutant un peu d’intégration et de développement continu (CI/CD) avec Gitlab, de la conteneurisation Docker et … pourquoi pas de l’orchestration et du clustering Kubernetes!!

L’orchestration et le clustering étant à la base de cette pile, je te propose aujourd’hui la première brique, comment installer un cluster Kubernetes sur Ubuntu 22.04 fraichement installé.

De mon côté, le cluster sera physiquement sur une seule machine. Pas trop davantage d’avoir un cluster…. Si la machine tombe, le cluster tombe!! Mais bon ça permet de tester (et ça permet d’avoir l’architecture déjà en place donc le jour où j’ai envie de scaler, ça sera « plus simple »).

Donc après avoir fait 2 nouvelles machines virtuelles avec une installation fraiche de la dernière version Ubuntu LTS, la 22.04 Jammy Jellyfish sur chacune des VMs, place à Kubernetes. La plupart des étapes suivantes sont à faire sur les 2 machines. Il n’y aura que la déclaration du master d’un côté et la demande de rejoindre le cluster sur le worker de l’autre côté qui seront à faire en fonction des machines.

prérequis système et Vérification des ports

Avant de se lancer dans l’installation de Kubernetes, il y a quelques prérequis à vérifier.

Réseaux pontés

Déjà, il faut s’assurer que le système peut avoir des réseaux bridge. Pour ça il faut vérifier que le noyau Linux a bien le module br_netfilter chargé.

Un petit

lsmod | grep br_netfilter

Ça permet de vérifier. s’il n’y a pas de résultat, il faut alors l’activer avec

sudo modprobe br_netfilter

Je vérifie ensuite que le firewall Iptables peut voir ce trafic bridgé

sysctl net.bridge.bridge-nf-call-iptables

Si ce n’est pas le cas, je vais créer un fichier /etc/sysctl.d/k8s.conf pour charger les bons paramètres au démarrage

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

Et je l’applique directement

sudo sysctl --system

Désactiver le swap

Pour faire fonctionner Kubernetes (kubelet), il faut désactiver le swap. Pour le faire immédiatement

sudo swapoff -a

Maintenant pour le désactiver au démarrage, il faut éditer le fichier des partitions /etc/fstab donc

sudo nano /etc/fstab

Pour commenter la ligne de swap. Dans mon cas

#/swap.img      none    swap    sw      0       0

Vérifier les ports par défaut

Une petite vérification pour savoir si tous les ports par défaut listés ne sont pas utilisés par d’autres applications

sudo netstat -lnp | grep 6443

Dans mon cas, j’ai eu la bonne idée d’installer MicroK8s par défaut sur une des VM. du coup des ports étaient utilisés. Pour repartir sans microK8s

microk8s.disable dashboard dns
sudo snap remove microk8s

définir les noms d’hôtes

Je vais avoir besoin, minimum, d’un nœud Master et d’un nœud Worker. Donc sur chaque machine je définis son petit hostname

#sur la machine virtuelle Master
sudo hostnamectl  k8s-master.anthony-jacob.com
#sur la machine virtuelle Worker
sudo hostnamectl  k8s-worker.anthony-jacob.com

Sur chaque machine j’ai aussi édité le fichier /etc/hosts en fonction de la machine

sudo nano /etc/hosts
127.0.0.1 localhost 
127.0.1.1 k8s-workernode k8s-workernode.anthony-jacob.com

#IP Master
192.168.8.89  k8s-masternode k8s-masternode.anthony-jacob.com</p>

#IP Worker
192.168.8.88  k8s-workernode k8s-workernode.anthony-jacob.com

Installation du container runtime – Docker.

Kubernetes peut utiliser différents environnements de conteneurisation. Dans mon cas je souhaite utiliser Docker.

Depuis la version 1.24 de Kubernetes, l’intégration de Docker via dockershim n’est plus disponible. Il faut maintenant passer par cri-dockerd. Dans le cas d’une mise à jour, il y a toute une procédure disponible. Dans mon cas, c’est une installation from scratch donc pas de problème de migration (juste des problèmes d’installations !!! )

Installation de Docker

Avant d’installer l’interface cri-dockerd qui fera le lien entre Kubernetes et Docker, il faut avant tout installer Docker.

Je commence par ajouter la clé GPG du dépôt Docker. Les clés ne s’ajoutent plus avec apt-key, qui est déprécié. Il faut maintenant gérer les clés manuellement dans /etc/apt/trusted.gpg.d/ . Donc je la télécharge la clé

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker.gpg

Et j’ajoute le dépôt dans la liste des sources d’apt

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/docker.gpg] https://download.docker.com/linux/ubuntu \
  $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

Je peux maintenant mettre à jour les dépôts disponibles et installer Docker

sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin

Utiliser systemd

Pour la gestion des droits de Kubernetes, il est conseillé d’utiliser systemd au lieu de cgroupfs . Par conséquent, Docker aussi devrait utiliser systemd. Pour le vérifier

docker info

Devrait donner

Cgroup Driver: systemd
Cgroup Version: 2

Si ce n’est pas le cas, il faut spécifier des paramètres au lancement du daemon Docker.

Pour ça il faut créer (ou éditer si déjà présent) le fichier /etc/docker/daemon.json , donc

nano /etc/docker/daemon.json

Pour y mettre les options d’exécutions

{
  "exec-opts": ["native.cgroupdriver=systemd"]
}

Un petit reload de tout ça

sudo systemctl daemon-reload
sudo systemctl reload docker

et voilà, je vérifie que le service tourne

systemctl status docker

Ajout de mon utilisateur au groupe docker

Au passage j’en profite pour rajouter mon utilisateur au groupe docker

sudo usermod -aG docker $USER
newgrp docker

Installation de Mirantis Cri-Dockerd

Pour installer Cri-dockerd, l’interface entre Kubernetes et Docker, il faut Go.

wget https://storage.googleapis.com/golang/getgo/installer_linux
chmod +x ./installer_linux
./installer_linux
source ~/.bash_profile

Si tout est OK, go est installé

go version

devrait donner

go version go1.18.3 linux/amd64

Ensuite dans un répertoire de travail, je clone le repository git,
je compile cri-dockerd,
je le copie dans les bons répertoires,
j’installe et j’active les services

git clone https://github.com/Mirantis/cri-dockerd.git

cd cri-dockerd
mkdir bin
go get && go build -o bin/cri-dockerd
mkdir -p /usr/local/bin
sudo install -o root -g root -m 0755 bin/cri-dockerd /usr/local/bin/cri-dockerd
sudo cp -a packaging/systemd/* /etc/systemd/system
sudo sed -i -e 's,/usr/bin/cri-dockerd,/usr/local/bin/cri-dockerd,' /etc/systemd/system/cri-docker.service

sudo systemctl daemon-reload
sudo systemctl enable cri-docker.service
sudo systemctl enable --now cri-docker.socket

systemctl status cri-docker.socket

Installation de Kubernetes

Maintenant que les prérequis à Kubernetes sont là, je vais pouvoir passer à l’installation de Kubernetes. Je télécharge la clé gpg du dépôt

curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/google-k8s.gpg

Et j’ajoute Kubernetes à la liste des dépôts en créant le fichier /etc/apt/sources.list.d/k8s.list

sudo nano  /etc/apt/sources.list.d/k8s.list

j’y met le dépôt en spécifiant la clé

deb [arch=amd64 signed-by=/etc/apt/trusted.gpg.d/google-k8s.gpg] http://apt.kubernetes.io/ kubernetes-xenial main
# deb-src http://apt.kubernetes.io/ kubernetes-xenial main

Je peux maintenant mettre à jour les dépôts disponibles et installer Kubernetes

sudo apt update
sudo apt install kubeadm kubelet kubectl kubernetes-cni

Configuration et déclaration du Master Kubernetes

Toutes les étapes précédentes étaient à faire sur les 2 VMs, la machine qui sera le master et la machine qui sera le worker du cluster Kubernetes. Ici, j’initialise le master.

l’adresse IP du master est 192.168.8.89

j’utilise docker au travers de cri-dockerd.

systemctl status cri-docker.socket

Me permet de voir que le socket d’écoute est unix:///run/cri-dockerd.sock

Et je vais devoir par la suite devoir installer un pod réseaux. Dans mon cas je choisirais Flannel, par défaut Flannel utilisera adressage CIDR 10.244.0.0/16 pour les pods

Avec toutes ces informations, je peux lancer la commande

sudo kubeadm init \
  --pod-network-cidr=10.244.0.0/16 \
  --cri-socket=unix:///run/cri-dockerd.sock \
  --apiserver-advertise-address=192.168.8.89

Si tout se passe comme prévu, kubeadm devrait arriver à la fin de la configuration et indiquer quelque chose comme

Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
  
  mkdir -p $HOME/.kube
  
  sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
  
  sudo chown $(id -u):$(id -g) $HOME/.kube/config

You should now deploy a Pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with e of the options listed at:
  
     
    /docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each node
as root:

kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

Il faut mettre de côté la commande

kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

qui nous servira pour le worker

Mis à par ça, comme conseillé je copie les préférences dans mon dossier personnel

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

Installation du pod Réseau

Comme annoncé plus haut, je déploie un pod réseau.

kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

Quelques secondes après, je lance

kubectl get pods -n kube-system

Pour vérifier que tous mes pods de base (Flannel inclus) sont lancés

NAME                                                     READY    STATUS    RESTARTS       AGE
coredns-6d4b75cb6d-rn2cv                                 1/1      Running   3(4d7h ago)    4d8h 
coredns-6d4b75cb6d-zkftf                                 1/1      Running   3(4d7h ago)    4d8h 
etcd-k8s-masternode.anthony-jacob.com                    1/1      Running   3(4d7h ago)    4d8h 
kube-apiserver-k8s-masternode.anthony-jacob.com          1/1      Running   3(4d7h ago)    4d8h 
kube-controller-manager-k8s-masternode.anthony-jacob.com 1/1      Running   4(4d7h ago)    4d8h 
kube-flannel-ds-hntr4                                    1/1      Running   0              4d7h 
kube-flannel-ds-s8n5h                                    1/1      Running   3(4d7h ago)    4d8h 
kube-proxy-fmzl2                                         1/1      Running   3(4d7h ago)    4d8h 
kube-proxy-zrb4p                                         1/1      Running   0              4d7h 
kube-scheduler-k8s-masternode.anthony-jacob.com          1/1      Running   5(4d7h ago)    4d8h

Optionnellement, pour isoler le control plane pour un cluster Kubernetes mono-machine pour le développement, exécutez:

kubectl taint nodes --all node-role.kubernetes.io/master- 

Déclarer le Worker et rejoindre le master

Depuis la machine worker maintenant, je vais rejoindre le cluster et déclarer la machine au master avec la commande que m’a précédemment donnée l’initialisation du master

kubeadm join <control-plane-host>:<control-plane-port> --token <token> --discovery-token-ca-cert-hash sha256:<hash>

Il est possible de régénérer cette commande, depuis le master, avec

kubeadm token create --print-join-command 

ça donnera tout ce qu’il faut

kubeadm join 192.168.8.88:6443 --token fepq6o.am5wzzq75utqzzyy --discovery-token-ca-cert-hash sha256:c9f7798ed7a6ccf03b5590cddedecb3e250ea9427103e22ed10b30e3b43a2cfc --cri-socket=unix:///run/cri-dockerd.sock

Je vérifie que tout est bon

kubectl get nodes -A -o wide
NAME                             STATUS  ROLES         AGE  VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE          KERNEL-VERSION        CONTAINER-RUNTIME
k8s-masternode.anthony-jacob.com Ready   control-plane 4d9h v1.24.1 192.168.8.89  <none>     Ubuntu 22.04 LTS 5.15.0-37-generic docker://20.10.17 
k8s-workernode.anthony-jacob.com Ready   <none>        4d7h v1.24.1 192.168.8.88 <none>     Ubuntu 22.04 LTS 5.15.0-37-generic docker://20.10.17

Autocomplétion

Le panel de commande de Kubernetes à l’air sssuuuuper large, donc pour aller plus loin j’ai aussi mis en place l’autocomplétion sur le système. Donc si ce n’est pas déjà fait

apt-get install bash-completion

Et ensuite

kubectl completion bash | sudo tee /etc/bash_completion.d/kubectl > /dev/null

Installer Helm Gestionnaire de paquet Kubernetes

Par la suite je pourrai avoir besoin de helm, le gestionnaire de paquet Kubernetes. Assez simple, on ajoute la bonne clé, le dépôt dans la liste des sources et il suffit de l’installer avec apt

curl https://baltocdn.com/helm/signing.asc | gpg --dearmor | sudo tee /etc/apt/trusted.gpg.d/helm.gpg > /dev/null
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/trusted.gpg.d/helm.gpg] https://baltocdn.com/helm/stable/debian/ all main" | sudo tee /etc/apt/sources.list.d/helm-stable-debian.list
sudo apt-get update
sudo apt-get install helm

Voilà, l’installation sommaire d’un cluster Kubernetes est faite de mon côté. Je n’ai plus qu’à approfondir son utilisation.

J’ai fait 2 autres articles sur l’installation d’interfaces pour gérer le cluster ou au moins avoir les informations essentielles. un article pour installer Kubernetes Dashboard et un autre pour installer Portainer.io

Dis moi ce que tu en penses et si ça a pu te servir ! En attendant, je te dis à bientôt pour de nouvelles aventures!!

Partagez l'article:
FacebookTwitterEmailLinkedIn

4 réflexions au sujet de « comment installer un cluster Kubernetes sur Ubuntu 22.04 »

  1. Holà !
    J’espère que tu vas bien.
    Merci énormément pour le temps que tu as pris à tester puis rassembler les infos pour les partager.

    J’ai un petit soucis de connexion entre mon worker et mon master, lorsque je veux faire une cmd kubectl depuis le worker (en sudo ou non) je reçois cette erreur :
    The connection to the server localhost:8080 was refused – did you specify the right host or port?

    J’ai lu sur plusieurs forums comme quoi ça pouvait venir de la partie attribution des droits des fichiers de config après l’initialisation mais pourtant je les ai bien faites (et refaites) sur le master.

    Si jamais t’as déjà rencontré ce problème, je serais preneur d’un coup de main 😉

    Encore merci pour ton tuto en tout cas !

    1. Petit edit :
      J’ai trouvé la solution mais maintenant je galère à accéder au dashboard depuis l’extérieur avec mes VMs NATées mais bon on avance tranquillement.

      Bonne soirée à toi !

  2. Salut Maxime,
    merci pour ton message!

    oui ton premier souci ressemblait à un manque ou une mauvaise config du fichier ./kube/config dans ton dossier utilisateur?!
    Comment tu l’as résolu?

    Pour l’accès au dashboard, là comme ça je ne peux pas t’aiguiller.
    si ton service fonctionne bien et que tu y as accès depuis ton worker
    https://blog.anthony-jacob.com/comment-installer-kubernetes-dashboard/#premier-test

    je dirai que ça se passe au niveau d’une translation d’adresse ou un forward quelque part.
    j’ai aussi eu des problèmes réseau et DNS que j’ai résolu par la suite, je prépare un petit mémo là-dessus
    idem , je serai curieux de savoir comment tu as résolu ce problème si tu as avancé dessus.

    bonne journée!

    1. Holà
      Effectivement ma première erreur était liée au fichier .kube/config sur le worker qui n’était pas défini, du coup il tapait sur rien quand je faisais une cmd kubectl. J’ai copié celui du master et ça fonctionne niquel
      Pour le dashboard je suis toujours bloqué, j’ai bien l’erreur 200 lorsque je fais le curl en localhost mais depuis mon browser j’ai une erreur de certificat. En même temps, le certificat a été créé sur le Master et là on essaye d’y accéder via le worker donc je sais pas si c’est à cause de ça, je creuse le problème ce soir tranquillement 😉

      Bonne journée à toi aussi et bon week-end !

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée.

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