Niveau 3 : Orchestration de conteneurs avec Rancher et Kubernetes.
Auteurs
© CNRS 2020
Assemblé et rédigé par Martin Souchal, d'après les travaux de Remi Cailletaud.

This work is licensed under a Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International License.
Introduction

Déployer un cluster Kubernetes n'est pas une chose aisée. Rancher est un produit indépendant de la CNCF qui permet de déployer simplement un cluster Kubernetes avec une surcouche propre à Rancher, tout en assurant la compatibilité avec les commandes Kubernetes traditionnelles. Rancher est un produit OpenSource maintenu par la société Rancher Labs.
Ecosystème

Déploiement d'un cluster Kubernetes avec Rancher
Un peu de vocabulaire
- Node: Serveur physique ou virtuel.
- Cluster: Groupe de noeuds.
- Control plane: Noeud qui contrôle les autres noeuds.
- Persistent Volumes: Volumes disponibles.
- Persistent Volume Claims: Volume necessaire.
- Pods: Une description d'un ensemble de conteneurs et les volumes qu'ils utilisent.
- Deployment: Un ensemble de pods.
- Service: Une description du réseau utilisé par les déploiements.
Kubernetes fait tourner des applications en les placant dans des conteneurs rassemblés dans des Pods qui eux mêmes tournent sur des noeuds. Un noeud peut être une machine virtuelle ou physique, et un cluster peut contenir les deux types de noeuds. Le control plane est un noeud chargé de gérer le cluster. En général un cluster Kubernetes comprends plusieurs noeuds pour être efficace. Dans un environnement de test ou de formation, on peut créer un cluster Kubernetes eavec une seule machine.
Un noeud comprends le kubelet, une runtime de conteneur et un kube-proxy.
Rancher a besoin d'un rancher server (pour la gestion du cluster Rancher) et d'un service etcd (base de donnée simple clé valeur) en plus du control plane et de workers kubernetes.
1. Rancher Server
Pour déployer le Rancher Server, il faut utiliser la commande suivante :
2. Working nodes
Pour déployer les working nodes Kubernetes sur un cluster de machine virtuelles il faut utiliser l'UI de Rancher : alller dans Modifier le cluster et dans la partie Customize Node Run Command choisir les rôles à assigner et faire un copier coller de la commande générée. Par exemple :
Avec au moins un worker, un etcd et un control plane on a une infrastructure Rancher fonctionnelle, sur laquelle on peut déployer des applications.
Déploiement d'une application
1. Installation et configuration de kubectl
- Choisissez une méthode d'installation de kubectl, et installez la dernière version.
- Récupérez votre fichier kubeconfig.
2. Premiers pas
Afin de bien comprendre le fonctionnement, tous les participants sont administrateurs du cluster. En revanche, chacun se voit attribuer un Namespace afin de bien isoler les différentes ressources.
Afin de vérifier que vous accédez au cluster, lancez :
3. Namespaces
Listez les différents namespaces :
Kubernetes supporte plusieurs clusters virtuels au sein d'un même cluster physique. Ces clusters virtuels sont appellés namespaces. Les namespaces sont prévus pour être utilisés dans des environnements avec beaucoup d'utilisateurs et de projets différents.
Ici l'intêret d'utiliser des namespaces différents est de pouvoir avoir des noms de pods identiques, ce qui n'est pas possible dans un même namespace.
Kubernetes démarre avec 4 namespaces initiaux :
- default : Le namespace par défaut pour les objets crées sans namespaces particuliers
- kube-system : Namespace pour les objets crées par le système Kubernetes
- kube-public : Ce namespace est créé automatiquement et est lisible par tous les utilisateurs (y compris ceux qui ne sont pas authentifiés). Ce namespace est principalement réservé à l'utilisation du cluster, au cas où certaines ressources devraient être visibles et lisibles publiquement dans l'ensemble du cluster. L'aspect public de ce namespace n'est qu'une convention, pas une exigence.
- kube-node-lease : Ce namespace pour les objets de location associés à chaque nœud améliore la performance du heartbeat des nœuds au fur et à mesure que la grappe s'étend.
Listez les pods dans le namespace actuel puis dans tous les namespaces :
Maintenant créez votre propre namespace :
Pour configurer le namespace par défaut que vous allez utiliser, modifiez la configuration :
4. Monitoring
Vérifiez l'usage des ressources par pod :
5. Déploiement d'un conteneur
Enfin, lancez un pod, depuis une image debian, et lancez-y un shell :
Avec la commande kubectl get pods -o wide, vérifiez sur quel noeud le pod s'éxecute.
Avec la commande kubectl get pods -o yaml, récupérez le fichier de configuration du pod.
Application
Nous allons lancer trois pods: un pour Mariadb, un pour l'application Django, et un pour notre frontal NGINX. Ces pods seront contrôlés par des Deployments, ce qui permet de les relancer automatiquement en cas de défaillance.
1. Mariadb
Premier déploiement
Astuce: pour générer les fichier yaml facilement, vous pouvez utiliser la commande kubectl avec les options --dry-run -o yaml :
Lancez le déploiement (1 réplicas) :
Surveillez l'état du pod :
Debug
Le pod mariadb-* produit une erreur. Pour la comprendre :
L'erreur est Back-off restarting failed container, ce qui signifie que le pod redémarre sans cesse. Pour examiner plus précisément l'activité d'un conteneur du pod :
On voit qu'il manque des options (variables d'environnement) pour le que conteneur mariadb démarre correctement. Définissez les variables MYSQL_ROOT_PASSWORD, MYSQL_USER, MYSQL_PASSWORD et MYSQL_DATABASE dans le fichier mariadb.yml à l'aide du champ env.
Dans la suite, nous verrons comment éviter les secrets en clair... Si nous avons le temps ;)
Une fois les variables définies, réappliquez les changements et vérifiez que le pod tourne :
Tests
Pour tester facilement que le pod mariadb répond correctement, et pour les futurs debug, vous pouvez utiliser la commande kubectl port-forward :
Nous avons vu que les pods et leur configuration réseau sont temporaires. Afin de les exposer de manière pérenne, il faut mettre en place un service. On utilise la même astuce du dry-run pour générer le fichier :
Ainsi, le nom DNS mariadb pointera vers le pod correspondant. Vous pouvez créer un pod temporaire afin de vérifier la résolution DNS, et le bon fonctionnement du serveur mariadb.
2. Django
Secret Kubernetes
Afin de déployer l'application directement depuis la registry Gitlab, il faut pouvoir s'identifier sur le registre privé gitlab : pour cela, créer un secret Kubernetes pour stocker vos identifiants gitlab :
Déploiement de django (à vous de jouer)
Sur l'exemple des manifests mariadb, créez un manifest pour déployer le conteneur django.
Vous pouvez déclarer plusieurs objets dans le même fichier en les séparant par la ligne ---
Pensez à : * Spécifier les images correspondantes (!) ; * Spécifier les ports pour chaque conteneur ; * Utiliser le secret pour vous identifier sur gitlab ; * Créer les services correspondants.
Après avoir appliqué le manifeste, vérifez que vous accédez aux conteneurs avec kubectl port-forward :
3. Aller plus loin
Ressources
Afin de limiter l'usage des ressources par les pod, et de faciliter le travail du scheduler, il est fortement conseillé de spécifier des Resources. Vous pouvez par exemple configurer le pod nginx avec 2Mo/10Mo, et le pod mariadb avec 40Mo/80Mo.
Secrets
Dans le TP, les secrets sont dans le dépôt, ce qui est évidemment un mauvaise pratique. En pratique, l'API Kubernetes comporte un objet (que l'on a utilisé pour configurer la registry docker) qui permet de séparer les secrets des déploiements : l'objet Secret. Ajouter un secret avec les différentes variables d'environnement nécessaire, et modifier les déploiements mariadb et django afin qu'ils utilisent le secret comme variable d'environnement. Par la suite, on peut utiliser sops pour chiffrer les secrets yaml et les ajouter au dépôt en tout confiance...
Volume
Vous aurez remarqué que nous n'abordons pas la problématique de la persistance, par manque de temps. Cet problématique est résolue par Kubernetes grâce aux Volumes. L'API est capable de communiquer avec le cloud sous-jacent (par exemple cinder, dans le cas d'Openstack), mais aussi de tailler des volumes iSCSI, nfs, etc...
NetworkPolicy
Par défaut, la base mariadb est accessible à tous les pods du cluster. Vous pouvez limiter les pods qui y ont accès à l'aide d'une NetworkPolicy. Utilisez le namespaceSelector qui correspond à votre namespace, et le label app: django.