Déployement de Kubernetes avec kubeadm

<<< Chap 1 | Sommaire | Chap 3 >>>

Chap 2. Déployement de Kubernetes avec kubeadm

Dans l’un des articles précédents, je vous ai parlé de Docker, puis de Podman. Maintenant, je vais vous présenter Kubernetes.

« Kubernetes, k8s (pour k, 8 caractères, s) ou encore « kube », est une plateforme Open Source qui automatise l’exploitation des conteneurs Linux. Elle permet d’éliminer de nombreux processus manuels associés au déploiement et à la mise à l’échelle des applications conteneurisées. En d’autres termes, Kubernetes vous aide à gérer facilement et efficacement des clusters au sein desquels vous aurez rassemblé des groupes d’hôtes exécutant des conteneurs Linux. Ces clusters peuvent couvrir des hôtes situés dans des clouds publics, privés ou hybrides. » (lu sur redhat.com)

Ci-dessous, une liste non-exhaustive d’outils d’installation de Kubernetes, avec leurs préférences d’utilisation.

  • Minikube
    S’installe en local, sur un ordinateur portable (hyperviseur de type 2)
    Nécessite d’avoir un outil de virtualisation (virtualbox, etc.)
  • Kubeadm
    Peut être installé directement sur hyperviseur de type 1, y compris sur un Raspberry Pi
    Le réseautage se fait via un plugin non intégré à l’outil kubeadm
  • Kops
    Très utilisé dans le Cloud (AWS, etc.)

De cette liste, j’ai opté pour kubeadm.

I. Prérequis

1. Serveurs Physiques ou Virtuels

Pour faire tourner un cluster kubernetes, il nous faut au moins 3 serveurs:

  • Un Master
  • Deux Workers

En mode HA (High Availability, ou Haute Disponibilité), il faudrait 4 Masters avec au moins 2 Workers.

Chacun de ces serveurs peuvent tourner sur un raspberry-pi 4, ou directement sur une machine avec beaucoup de resources (au moins 10 Go de mémoire).

Server « K8s Control Plane »: Master (k8sn01)

OS: Ubuntu 20.04 LTS Server (Focal Fossa)
RAM: 4 Go
CPU: 2
HDD: 20 Go

Serveur « K8s Worker Nodes »: Worker/Minion (k8sn02 et k8sn03)

OS: Ubuntu 20.04 LTS Server (Focal Fossa)
RAM: 2 Go
CPU: 2
HDD: 20 Go

2. Docker

Docker devrait déjà être installé sur chacun de ces serveurs (Master/Workers). Si ce n’est pas le cas, revoyez mon article, dont les étapes sont résumées ci-dessous.

$ sudo apt update && sudo apt upgrade -y
$ sudo apt install apt-transport-https gnupg-agent
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | \
  sudo apt-key add -
$ sudo add-apt-repository "deb [arch=amd64] \
  https://download.docker.com/linux/ubuntu $(lsb_release -cs) \
  stable"
$ sudo apt update
$ sudo apt install docker-ce
$ sudo usermod -aG docker $USER

Vérifier que docker peut lancer le programme « hello-world ».

$ docker run hello-world

3. Pilote du Docker

Si vous utilisez Debian ou l’un de ces dérivés, remplacer le pilote de Docker (cgroupfs, installé par défaut) avec celui du systemd.

Affichage du pilote de Docker.

$ docker info | grep Cgroup
Cgroup Driver: cgroupfs

Si le pilote n’affiche pas « cgroupfs », vous pouvez passer à l’étape suivante.

Le remplacement du pilote cgroupfs de Cgroup par systemd se fait en plusieurs étapes.

Etape 1- Créer un fichier daemon.json

$ ls /etc/docker
key.json
$ cat <<EOF | sudo tee /etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2"
}
EOF

Etape 2 – Créez le dossier docker.service.d

$ sudo mkdir -p /etc/systemd/system/docker.service.d

Etape 3 – Redémarrer le service de docker

$ sudo systemctl daemon-reload
$ sudo systemctl restart docker

Vérifier ensuite que le changement a eu lieu, et que le pilote utilisé est celui de systemd.

$ docker info | grep Cgroup
Cgroup Driver: systemd

4. Désactivation du swap

Depuis la version 1.8 de Kubernetes, le service kubelet ne peut pas se lancer si le swap est activée.

Lancer les commandes ci-dessous sur chacun des nodes, y compris le Master, pour désactiver le swap.

$ sudo swapoff -a
$ sudo systemctl stop swap.target
$ sudo systemctl mask swap.target
$ sudo sed -i '/swap/d' /etc/fstab

II. Installation

1. Installation de kubeadm

La suite se fera sur chacun des serveurs (Master/Workers), à moins que je ne précise autrement.

Importer la clef GPG.

$ curl -s \
 https://packages.cloud.google.com/apt/doc/apt-key.gpg| \
 sudo apt-key add -

Ajouter le dépot de kubernetes aux sources de APT.

$ sudo apt-add-repository "deb http://apt.kubernetes.io/ \
 kubernetes-xenial main"
$ sudo apt update

Lancer l’installation de kubeadm, l’outil d’installation de kubernetes.

$ sudo apt install kubeadm

2. Initialisation du Master

Tous les serveurs doivent se trouver sur le même réseau.

Voici mes configurations.

k8sn01: 192.168.0.200 (Master)
k8sn02: 192.168.0.201 (Worker)
k8sn03: 192.168.0.202 (Worker)

Serveur DCHP/DNS: 192.168.0.151

Pour le réseautage avec kubernetes, il nous faut crér un nouveau réseau, sinon vous aurez un conflit entre votre réseau local et les différents nodes.

CIDR pour le cluster kubernetes: 172.16.0.0/16

2.1. Configuration du node Master

L’initialisation du Master se fait via la commande « kubeadm init ».

$ sudo kubeadm init --pod-network-cidr 172.16.0.0/16

Les instructions suivantes sont détaillées à la fin de la commande d’initialisation de kubeadm.

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

2.2. Configuration des Workers

Après avoir pris note de la commande à la fin de l’initialisation du Master, coller cette commande dans chacun des Workers. Voici un exemple,

$ sudo kubeadm join 192.168.0.200:6443 \
 --token cvkith.x2ukhvjvwm722u48 \
--discovery-token-ca-cert-hash \
sha256:d6229d458xxxxxxxxxxxxxxxxxxxxx

Vérifier ensuite l’état du cluster à partir du Master,

Si vous le faîtes à partir d’un des Workers, vous aurez droit à un petit message d’erreur, faute de permission.

3. Configuration du reseau

Si vous lancer la commande « kubectl get nodes », le status des Workers devrait être « NotReady », c’est à dire « pas prêt ».

$ kubectl get nodes
NAME STATUS ROLES AGE VERSION
k8sn01 NotReady master 14m v1.19.3
k8sn02 NotReady <none> 3m22s v1.19.3
k8sn03 NotReady <none> 3m2s v1.19.3

Pour comprendre ce qui se passe, voyons ce qu’il a dans les logs en se focalisant sur les nodes.

$ kubectl describe nodes

Ce message nous indique que le plugin pour le réseau n’est pas prêt et que le CNI (Container Network Interface, ou Interface Réseau des Conteneurs) ne peut pas être initialisé.

Ce qui est tout à fait normal, puisqu’aucun plugin n’est installé par défaut avec kubeadm, et que la gestion du réseau se fait via un plugin justement.

Les différentes options de réseau pour les containers (CNI),

J’ai choisi Canal, qui est le résultat de la collaboration entre les projets Calico et Flannel.

Récupérer le fichier de configuration de Canal au format YAML (aussi appelé Manifest), puis l’appliquer au niveau du Master.

$ curl https://docs.projectcalico.org/manifests/canal.yaml -O
$ kubectl apply -f canal.yaml

Vérifier ensuite que le node Master voit bien les Workers, dont le status devrait maintenant ête sur « Ready ».

$ kubectl get nodes
$ kubectl get pods -n kube-system

Vérifier aussi que touts les pods créés dans le « namespace » (Espace de Nom) kube-system, ont pour status « Running ». Ce qui signifie que l’infastructure de kubernetes est fonctionnel.

Par défaut, il y a quatre Espaces de Nom (namespace) créés après l’installation de kubernetes. Chaque namespace peut avoir 0 ou plusieurs pods.
Sachez que les pods de chaque namespace ne peuvent communiquer qu’entre eux, dans le même namespace, mais pas avec ceux d’un autre namespace.

Ci dessus, je vous ai demandé de vérifier que tous les Pods du namespace kube-system, sont tous activés et fonctionnel. Ces pods créés par défaut avec l’installation de kubernetes, sont les bases de l’infrastucture de notre cluster.

J’ai repris ici une image de wikipedia, avec pour référence les valeurs de sortie de la commande « kubectl get pods –namespace kube-system » pour que vous ayez une idée de comment ces pods communiquent entre eux.

La commande ci-dessous devrait donner le même résultat sur un clusteur nouvellement créé, puisque les autres namespaces sont encore vides.

$ kubeclt get pods -A


Les pods que vous allez créér manuellement, se trouveront dans le namespace « default ».

III. Astuces

Vous pouvez vous simplifier la vie avec les alias. Ici par exemple, j’ai créé un alias tout simple pour remplacer la commande kubectl.

$ alias kube=kubectl

Les alias peuvent vous être bénéfique, et vous font gagner du temps, même pour les examens CKA et CKAD.

Une fonctionnalitée que je trouve excellente, est l’auto-completion des commandes.

Ajouter les informations suivantes dans bashrc.

$ echo 'source <(kubectl completion bash)' >> ~/.bashrc

Relancer bashrc avec l’une des deux commandes ci-dessous,

$ . ~/.bashrc

ou

$ source ~/.bashrc

Sinon, ouvrez une nouvelle session pour valider le changement.

Pour vérifier que l’auto-complétion fonctionne, tapez « kubectl get no » puis sur la touche TAB. Vous devriez avoir « kubectl get nodes.

Sachez que l’auto-complétion n’est pas compatible avec les alias.

Je vous renvoie ensuite sur la page d’aide mémoire de kubernetes, qui fournit une liste de commandes à savoir si vous vous intéressez au projet.

Sources

Kubernetes, qu’est-ce que c’est ?
Container runtimes
10+ Useful Kubernetes Tools
Creating a cluster with kubeadm
Comparing Kubernetes CNI Providers: Flannel, Calico, Canal, and Weave
System requirements (Calico)
Install Calico for policy and flannel (aka Canal) for networking
The Tale of Two Container Networking Standards: CNM v. CNI