Skip to content
Snippets Groups Projects
user avatar
remche authored
7c74af63
History
Name Last commit Last update
helm
solution
README.md
intro.odp
intro.pdf

TP Kubernetes

Prise en main

Installation de snap

Tout d'abord, si ce n'est pas déjà fait, installez snap:

sudo apt-get update
sudo apt-get install snapd

Installation et conf de base

Puis installez MicroK8s via snap et configurer-le pour l'utilisateur de la VM:

sudo snap install microk8s --classic
sudo usermod -a -G microk8s $USER
sudo chown -f -R $USER ~/.kube
su - $USER

Vérifiez que le cluster Kubernetes fonctionne correctement :

microk8s status --wait-ready

Vous pouvez récupérer la liste des noeuds (un seul par défaut) :

microk8s kubectl get nodes

Afin de faciliter la suite et de rester vanilla, ajouter l'alias suivant :

alias kubectl='microk8s kubectl'
echo "alias kubectl='microk8s kubectl'" >> ~/.bashrc

Services de base

MicroK8s est un déploiement minimal de Kubernetes. Vous pouvez lister les pods déployés par défaut :

kubectl get pods -A

Il s'agit uniquement des pods Calico, le plugin CNI (Container Network Interface) qui gère le réseau pour les conteneurs.

Vous allez ajouter deux services importants généralement déployés sur les cluster Kubernetes :

  • metrics-server pour l'accès aux métriques de base ;
  • CoreDNS pour la resolution DNS interne.

metrics-server

Actuellement, vous n'avez pas accès aux métriques :

kubectl top nodes
kubectl top pods -A

Déloiyez metrics-server et vérifiez que le pod correspondant tourne bien :

microk8s enable metrics-server
kubectl get pods -A

Après quelques dizaine de secondes, les métriques devraient être disponibles :

kubectl top nodes
kubectl top pods -A

CoreDNS

Pour tester le service de DNS (qui est derrière le mécanisme de Service Discovery), lançez un pod nginx et vérifiez qu'il tourne :

kubectl run --image nginx web
kubectl expose pod web --port 80
kubectl get pods -o wide
kubectl get service

Essayez de l'atteindre depuis un autre pod, via son IP, l'IP du service, puis le nom DNS du service :

kubectl run --rm --restart=Never -i -t --image busybox test /bin/sh
  wget -O-  $ip_du_pod_nginx
  wget -O-  $ip_du_service
  wget -O- web

Déployez CoreDNS, vérifiez qu'il tourne bien et testez à nouveau la résolution DNS :

microk8s enable dns
kubectl get pods -A
kubectl run --rm --restart=Never -i -t --image busybox test /bin/sh
  wget -O- web

Nettoyage

kubectl delete service web
kubectl delete pod web

Vapormap

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.

Mariadb

Premier déploiement

Astuce: pour générer les manifestes yaml facilement, vous pouvez utiliser la commande kubectl avec les options --dry-run -o yaml :

kubectl create deployment mariadb --image mariadb --dry-run=client -o yaml > mariadb.yml

Lancez le déploiement (1 réplicas) :

kubectl apply -f mariadb.yml

Surveillez l'état du pod :

kubectl get pods -w

Debug

Le pod mariadb-* produit une erreur. Pour la comprendre :

kubectl describe pod mariadb-*

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 :

kubectl logs mariadb-*

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 :

kubectl apply -f mariadb.yml
kubectl get pods -w

Tests

Pour tester facilement que le pod mariadb répond correctement, et pour les futurs debug, vous pouvez utiliser la commande kubectl port-forward :

kubectl port-forward mariadb-* 3306:3306
telnet localhost 3306

Nous avons vu que les pods et leur configuration réseau sont temporaires. Afin de les exposer de manière pérenne, déplyez une service comme dans la première partie. Utilisez la même astuce du dry-run pour générer le fichier :

kubectl expose deployment mariadb --port=3306 --target-port=3306 --dry-run=client -o yaml > mariadb-service.yml
kubectl apply -f mariadb-service.yml

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.

kubectl run --rm --restart=Never -i -t --image busybox test /bin/sh
telnet mariadb 3306

Vapormap

Déploiement de vapormap (à vous de jouer)

Sur l'exemple des manifests mariadb, créez un manifest pour déployer les conteneurs vapormap et nginx, avec 2 replicas pour nginx et 3 pour vapormap.

Vous pouvez déclarer plusieurs objets dans le même fichier en les séparant par la ligne ---

Pensez à :

  • Spécifier les images correspondantes, Si vous n'avez pas vos propres images, vous pouvez utiliser les suivantes : registry.plmlab.math.cnrs.fr/resinfo/anf/2019/ada/vapormap/vapormap:master
    registry.plmlab.math.cnrs.fr/resinfo/anf/2019/ada/vapormap/nginx:master
  • Positionner les variables VAPOR_DBNAME, VAPOR_DBUSER, VAPOR_DBPASS, DJANGO_SETTINGS_MODULE et VAPOR_DBHOST pour le conteneur vapormap ;
  • Positionner les variables VAPORMAP_URL et VAPORMAP_PORT pour le conteneur nginx ;
  • Spécifier les ports pour chaque conteneur ;
  • Créer les services correspondants.

Après avoir appliqué le manifeste, vérifez que vous accédez aux conteneurs avec kubectl port-forward.

Migration de base

L'application ne marchera pas en l'état, puisqu'il faut lancer les migrations de base avant de lancer l'application Django. Ajoutez un initContainer au déploiement varpomap, dont le rôle sera d'éxecuter la commande python manage.py makemigrations && python manage.py migrate

Verifiez le bon fonctionnement de l'application à l'aide de :

kubectl port-forward svc/nginx 8000:8000

Ingress

Maintenant, nous allons exposer l'application au monde extérieur grâce à l'objet Ingress :

cat <<EOF > ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: vapormap
spec:
  rules:
  - http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: nginx
            port:
              number: 8000
EOF
kubectl apply -f ingress.yml

Pour l'instant l'objet Ingress est bien inutile car aucun Ingress Controler n'est déployé dans le cluster. Ajoutons Traefik, un Ingress Controler léger et rapide :

microk8s.enable traefik
kubectl get pods --all-namespaces

Par défaut, Traefik écoute sur port 8080. Vous n'avez désormais plus besoin de port-forward (qui est un mécanisme prévu pr le debug) pour accéder à votre application :

firefox http://localhost:8080

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 vapormap 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 vapormap 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: vapormap.

Helm

Vous trouverez dans le repertoire helm un chart qui permet de déployer Vapormap à l'aide de Helm, un gestionnaire de paquets pour Kubernetes. Le chart se base lui-même sur le chart MariaDB de Bitnami.