TP: déploiement dans Kubernetes

Principe

  • Prendre en main la ligne de commande Kubernetes
  • Déployer une API web déjà prête sur un registry
  • Déployer un BD
  • Déployer une deuxième application
  • Configuration

Infrastructure

Un cluster Kubernetes (nommé local) est mis à disposition. Chaque étudiant recevra un mot de passe via tomuss (le login est le même que le compte étudiant usuel). Une interface Web de gestion (instance Rancher) est disponible à l’adresse https://rancher.fsa.os.univ-lyon1.fr. Les identifiants de connexion sont votre login étudiant (pxxxxxxx) et le mot de passe spécifié dans tomuss (mdp_k8s). Bien que cette interface permette d’effectuer un certain nombre d’actions, il est demandé d’utiliser plutôt l’interface en ligne de commandes de Kubernetes: kubectl. Cet utilitaire nécessite une configuration pour accéder au cluster. Celle-ci peut être récupérée en cliquant sur “Explore Cluster: local” dans le menu déroulant en haut à gauche, puis via le bouton “Download Kubeconfig” en haut à droite. Vous pouvez sauvegarder ce fichier et indiquer son emplacement à kubectl via la variable d’environnement $KUBECONFIG. Chaque étudiant/groupe/binôme s’est vu associé un projet au sein du cluster. Dans ce projet, un namespace de la forme prj-xx a été créé. La commande suivante va permettre de changer la configuration par défaut de kubectl pour changer utiliser ce namespace par défaut (ne pas oublier de changer xx):

kubectl config set-context $(kubectl config current-context) --namespace=prj-xx

Il faudra bien penser à créer toutes vos ressources dans ce namespace.

Pour tester que kubectl fonctionne, lancer la commande suivante:

kubectl get pod

Cette commande devrait répondre: “No resources found.”

Premiers déploiements

Il est conseillé de bien garder les fichiers utilisés pour cette partie: il pourront servir de point de départ pour le déploiement des applications des TPs précédents.

Dans la suite du TP, bien penser à toujours ajouter votre namespace (prj-xx) comme champ namespace dans la section metadata de vos fichiers de déploiements yaml.

D’une manière générale, préférez kubectl apply à kubectl create, y compris pour la création de nouveaux pod/déploiements, etc.

Conteneurs stateless: nginx

Suivre ce tutoriel afin de déployer un conteneur nginx.

Avant de détruire le déploiement à la fin du tutoriel, vérifiez que le conteneur fonctionne correctement via kubectl port-forward.

Conteneurs stateful: postgresql

Adapter le tutoriel sur le déploiement de MySQL pour:

  • utiliser une base PostgreSQL (image)
    • attention au point de montage et aux variables d’environnement
  • utiliser un volume dont la taille est limitée à 1 Gi
  • ne pas créer de PersistentVolume, mais simplement un PersistentVolumeClaim utilisant:
    • longhorn comme storageClassName
  • bien penser à préciser la valeur de la variable PGDATA comme indiqué dans la documentation de l’image docker.

Supprimer le déploiement, y compris le Service et le PersistentVolumeClaim.

Déploiement de l’application “chiffrement”

On va maintenant déployer une application “chiffrement” qui offre la possibilité de chiffrer un contenu via une API. Cette application est composée de 2 composants: api et worker.

  • api est la partie visible de l’application. Elle offre une Web API avec 3 contrôleurs: /user (pour la gestion des utilisateurs), /key (pour la gestion des clés de chiffrement) et /crypt (pour le chiffrement/déchiffrement de contenus). Les échanges de données avec la route /crypt doivent être encodée en base64.
  • worker est le composant qui effectue concrètement le chiffrement. L’implémentation fournie utilise un algorithme naïf basé sur un décalage du nom de la clé. Afin de simuler une opération de chiffrement plus complexe, un temps de latence est ajouté lors du (dé)chiffrement d’un contenu.

Le code source de ces deux composants est fourni ici: https://forge.univ-lyon1.fr/tiw-fsa/fsa-apps-ha.

Le diagramme suivant résume les liens entre les composants de cette application:

graph LR
    client --> api
    subgraph Kubernetes
    api("fa:fa-coffee api") --> worker("fa:fa-coffee worker ")
    api --> db[("fa:fa-database postgres ")]
    end

Le composant api peut être déployé grâce à l’image harbor.fsa.os.univ-lyon1.fr/fsa/api:latest et le composant worker via l’image harbor.fsa.os.univ-lyon1.fr/fsa/worker:latest.

Déploiement de Worker

Le worker ne dépend d’aucun autre composant pour fonctionner, c’est celui-ci que l’on va déployer en premier.

Créer un déploiement pour le composant worker. Créer également un service pour accéder au worker. Prévoir 2 instances de worker. Prévoir également un service pour accéder aux workers.

Worker et API sont des applications spring-boot. Leur valeurs de configuration (définies dans application.properties) sont modifiable via des variables d’environnement (voir la doc). Par exemple, il est possible de changer le temps de calcul simulé d’un worker via la propriété tiw.fsa.worker.latence et donc via la variable d’environnement TIW_FSA_WORKER_LATENCE.

Modifier le déploiement précédent en changeant cette valeur pour la mettre à 10000 (au lieu de 1000 par défaut). Tester que le worker mets maintenant 10s à répondre en lui envoyant une requête en passant par un kubectl port-forward.

Détruire un ou deux pods worker et observer le comportement de kubernetes. Comment faire si l’on veut réduire le nombre de workers ? Quel est l’intérêt sur Service ?

Déploiement de la base de données

On veut maintenant déployer une base PostgreSQL sur laquelle s’appuiera API.

Créer un ConfigMap pour contenir les variables d’environnement contenant le nom de la base de données, l’utilisateur et le mot de passe de la base postgres (doc de l’image postgres, doc sur l’utilisation des configmaps), puis utiliser ce ConfigMap pour créer un déploiement de PostgreSQL avec les valeurs ainsi spécifiées. Ne pas oublier de configurer un Service pour accéder à la base de données.

Déploiement de l’API

Le composant API requiert plus de configuration. Il s’appuie sur la base PostgreSQL et sur les workers. Si vous avez correctement fait lesd éploiements précédentsCes deux composants sont accessibles via des services et pas directement via les adresses des pods.

Configurer et deployer l’API en utilisant les techniques utilisées précédement pour les workers et la base de données. Vérifier le bon fonctionnement de l’API en consultant ses logs (via kubectl logs) et en la requêtant. On pourra par exemple se connecter comme admin, créer une clé puis demander le chiffrement d’une donnée via cette clé.

Registre privé

Configuration de votre machine

En complément du cluster kubernetes, un registre docker a été créé: harbor.fsa.os.univ-lyon1.fr. Ce registre dispose d’une interface Web (https://harbor.fsa.os.univ-lyon1.fr) qui vous permttra de consulter son contenu. Le login est votre login étudiant et votre mot de passe est indiqué sur tomuss (mdp_k8s, le même que pour Rancher). Sur ce registre, vous avez la possibiliter de gérer des images docker taguées par harbor.fsa.os.univ-lyon1.fr/prj-xx/yyyy:zz oprj-xx est le même que votre projet/namespace Rancher.

Vérifiez que vous pouvez vous connecter au registre via docker login harbor.fsa.os.univ-lyon1.fr en utilisant les mêmes logins et mots de passe que pour l’interface Web de Harbor. Une fois le login effectué, vous devez pouvoir pousser une image, pour tester (penser à remplacer prj-xx):

docker pull hello-world
docker tag hello-world:latest harbor.fsa.os.univ-lyon1.fr/prj-xx/montest:latest
docker push harbor.fsa.os.univ-lyon1.fr/prj-xx/montest:latest

Utilisation dans kubernetes

Pour que Kubernetes puisse utiliser vos images, il lui faut pouvoir se connecter au registre privé. Pour cela on va suivre la documentation (lien) et créer un secret kubernetes (nommé harborcred) et contenant les informations de connexion (bien penser à remplacer les valeurs):

kubectl create secret docker-registry harborcred --docker-server=harbor.fsa.os.univ-lyon1.fr --docker-username=pxxxxxxxx --docker-password=XXXXXXXXXX --docker-email=yyyyyyyyyyyy@etu.univ-lyon1.fr

On va ensuite utiliser ce secret pour lancer un job de test utilisant l’image que l’on a poussé ci-dessus (bien remplacer les valeurs):

apiVersion: batch/v1
kind: Job
metadata:
  name: test-harbor-pull
spec:
  template:
    spec:
      containers:
        - name: test-harbor-pull
          image: harbor.fsa.os.univ-lyon1.fr/prj-xx/montest:latest
      restartPolicy: Never
      imagePullSecrets:
        - name: harborcred
  backoffLimit: 4

Vérifier ensuite dans rancher que le job a fonctionné (en sélectionant le projet prj-xx du cluster local du menu à côté de la vache, dans l’onglet Workload)

En cas de problème, des infos sont disponibles en suivant les liens du job, puis du pod et en affichant les événements du pod.

Préparation du TP suivant

Le TP suivant consistera à mettre en place la surveillance de cette application. Il est conseillé de bien regarder le fonctionnement des deux services Java en amont de la séance. Ne pas hésiter à réaliser un fork du dépôt du code des applications.

Les script build-push.sh permettent de construire les images docker et de les pousser vers Harbor. Il faudra changer le tag pour indiquer votre projet au lieu de fsa. Essayez d’avoir un cycle modification -> build -> déploiement fluide. Pour mettre au point ce cycle, vous pouvez ajouter/changer des lignes de log dans chacune des applications. Vous pouvez également ajouter une fonctionnalité, comme par exemple exposer l’interface OpenAPI via springdoc.

Un miroir maven local au campus est disponible ici: https://nexus.ecoquery.os.univ-lyon1.fr/repository/maven-central/ Il est possible d’utiliser ce lien comme valeur pour l’argument de build MVN_MIRROR des Dockerfile pour accélérer la construction des images. Son utilisation est intégrée aux scripts build-push.sh.