Kubectl et Premiers pas avec kubernetes

<<< Chap 2 | Sommaire | Chap 4 >>>

Chap 3. Kubectl et Premiers pas avec kubernetes

I. Master vs Worker

Comme nous l’avons déjà vu, Kubernetes fonctionne avec un modèle de type Master/Worker.

Le Master (Plan de Contrôle), est comme un chef d’orchestre du système. C’est lui qui dirige tout, comme par exemole, de la distribution des resources entre les différents Nodes, etc.

Les Workers (aussi appelé, Nodes ou Minions), eux par contre, ne s’occupent que de créer ou détruire les Pods (on ne parle pas de conteneurs avec kubernetes).

De ce fait, une fois le cluster kubernetes créé, tout se passera au niveau du Master. Il n’y a pas besoin de se connecter sur les différents nodes pour la suite.

Je vais reprendre ici, une des images de mon précédent article, pour illustrer la suite.

Les pods générés dans le plan de contrôle (Master).

  • API Server
    Valide et configure les données pour les objets API (Pods, Services, etc.)
  • Controller Manager
    Daemon qui intègre les boucles de contrôle principales de kubernetes (replication controller, namespace controller, etc.)
  • Scheduler
    Assigne les Pods aux différent Nodes
  • etcd
    Stocke les données de configuration du cluster

Les Pods ci-dessous exisent aussi bien, au niveau des différents Nodes que du Master, afin que garantir le bon fonctionnement du traffic réseau.

  • kube-proxy
  • canal

Par contre, les Pods qui gèrent le service de DNS en local n’existent qu’au niveau des Pods, pour la raison simple qu’il n’est pas possible (en théorie) d’installer des Pods sur le Master.

  • CoreDNS

II. Namespace

Après déployement du cluster kubernetes, le status des Pods créés par défaut, devrait être sur « RUNNING ». Si l’un de ces pods tombe en panne, le clusteur risque de ne pas fonctionner correctement.

student@k8sn01:~$ kubectl get pods --namespace kube-system

Pour séparer les pods créés par l’utilisateur avec ceux du système, kubernetes utilise les « namespaces » pour cloisonner ces Pods, qui vont ainsi se retrouver dans au moins deux types d’environnements différents.

La liste des différents namespaces est donnée par la commande

student@k8sn01:~$ kubectl get namespaces

student@k8sn01:~$ kubectl get ns

De cette liste, vous devriez reconnaître « kube-system », qui contient l’ensemble de Pods du système. Les pods créés par l’utilisateur devraients se trouver dans le namespace « kube-default », à moins que vous ne décidez autrement.

Ainsi, pour avoir la liste de tous les pods du le cluster,

student@k8sn01:~$ kubectl get pods --all-namespaces

student@k8sn01:~$ kubectl get po -A

Par contre, ce qui nous intéresse pour la suite, ce sont les pods dans notre environnement de travail. Ces pods se trouvent dans le namespace « default ».

student@k8sn01:~$ kubectl get pods --namespace default
No resources found in default namespace.

Ou, plus simplement

student@k8sn01:~$ kubectl get pods
No resources found in default namespace.

Ici, il n’y a aucun Pod de créé, d’où le message.

Ce qu’il faut retenir ici, c’est la conception du système fait en sorte que les pods entre les différentes namespaces (par exemple « default » et « kube-system ») ne peuvent pas se comminiquer entre eux.

III. Les primitives

Une primitive, dont je vous donne la liste ci-dessous, est l’ensemble d’outils nécessaires à la construction d’un cluster kubernetes. Il nous faut,

  • Pods
    Peuvent contenir un ou plusieurs conteneurs
  • Labels
    Sont des étiquettes qui peuvent être attachés à des objets Kubernetes comme les Pods
  • Contrôleurs (Replication, Daemon, Job et Deployment)
    Comme son nom l’indique, permet de contrôler l’état du cluster
  • Services
    Un groupe de pods peut avoir une interface unique accessible de l’extérieur

En une seule ligne de commande, vous pouvez avoir l’état du primitive.

student@k8sn01:~$ kubectl get ns,svc,pods,deploy,rs,ds -A

Cette même commande peut être décomposée en plusieurs commandes.

  • Information sur les pods (pods ou po)
$ kubectl get pods -A

$ kubectl get po -A
  • Information sur les différents types de contrôleurs

(replicasets ou rs)

$ kubectl get replicasets -A

$ kubectl get rs-A

(daemonset ou ds)

$ kubectl get daemonsets -A

$ kubectl get ds -A

(deployments ou deploy)

$ kubectl get deployments -A

$ kubectl get deploy -A
  • Information sur les services (services ou svc)
$ kubectl get services -A

$ kubectl get svc -A

Pour avoir une idée de comment interagissent les contrôleurs avec les Pods,


C’est un peu le fouilli, c’est pour celà que je vous ai fait un récapitulatif ci-dessous.

IV. Les différents services de kubeadm

Voyons la liste de services nécessaire à Kubeadm pour fonctionner correctement.

student@k8sn01:~$ apt-cache depends kubeadm
kubeadm
Depends: kubelet
Depends: kubectl
Depends: kubernetes-cni
Depends: cri-tools

Kubelet, l’agent installé sur chacun des Workers (Minions), sert d’intermédiare entre ces Nodes et le Master. L’une de ces fonctions est de recevoir la spécification des Pods (podspecs) dans le format YAML our JSON, pour pouvoir les déployer sur l’un des nodes.

Je ne vous présent plus l’outil kubectl, puisque c’est celui qu’on a utilisé pour

  • Initialiser le cluster (kubectl init)
  • Joindre les différents nodes au Master (kubectl join)
  • Obtenir des informations du cluster (kubectl get)

On n’en a parlé aussi des CNIs, avec l’installation de Canal qui est un plugin réseau pour conteneur.

Pour une utilisation avancée de kubernetes, il a été introduit depuis la version 1.5 le CRI ou Interface d’Exécution du conteneur.

V. Création d’un pod

Une nouvelle commande kubectl à connaîte, est « kubectl run » pour télécharger une image à partir du Hub de Docker, qui est un grand centre de stockage d’images pour conteneurs.

Comme test, je vais créer un serveur web nginx.

student@k8sn01:~$ kubectl run nginx --image=nginx

Récupérer le nom du node sur lequel le serveur est installé, puis son adress IP.

student@k8sn01:~$ kubectl describe pods/nginx

A partir du Master, vérifier que le serveurs nginx s’est bien lancé en utilisant la commande curl.

student@k8sn01:~$ curl <adresse_ip_de_nginx-app>

Et voilà, vous avez un serveur web qui tourne sur kubernetes.

Voyons maintenant la liste de Pods installés dans le cluster.

Ici, j’ai rajouté deux pods suplémentaires (« nginx-app » et « nginx-serv »),

  • afin de bien pouvoir voir la différence entre les pods créés par défaut (namespace: « kube-system ») (2) et ceux créés par l’utilisateur (1)
  • les Pods sont répartis entre les différents Nodes disponibles
    • « nginx » et « nginx-app » sur k8sn03
    • « nginx-serv » sur k8sn02

Je suppose qu’à ce stage, vous avez créé un ou plusieurs pods. Pour supprimer ceux dont vous n’avec pas besoin, lancer la commande.

k8sn02:~$ kubectl delete pod <nom_du_pod>

Je ne vous l’ai pas implicitement annoncé, mais jusqu’ici, nous avons vu deux méthodes pour créer un pod avec kubernetes.

  • Avec le fichier yaml téléchargé sur internet, nous avons créé un pod pour la gestion du réseau cannal
    $ kubectl apply -f canal.yaml
    • La suppression de tel type de pode se fait grâce à la commande
      $ kubectl delete -f monFichier.yaml
  • En passant par un hub de Docker, nous avons téléchargé un pod prêt à l’emploi
    $ kubectl run nginx --image=nginx
    • Pour la suppression du pod
      $ kubectl delete monPod

Source

Kubernetes: Get started

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