soutenance/content/30_specifications_techniques.md

17 KiB

\newpage

Spécifications techniques

Après avoir décrit, via un cahier des charges, les différents besoins du projet, les livrables attendus, il est temps de décrire une solution. Nous aborderons avant tout l'étude de l'existant puis enchaînerons sur le détail de l'infrastructure choisie pour terminer sur divers sujets intégrés et quelques outils utilisés.

Étude de l'application

Le dépôt Git contenant l'application existait déjà. Une étude des composants fournis par le projet a donc été nécessaire. Ce qui a été fournis aux développeurs également. Ce qui a permis d'en mesurer les implications.

Composants de l'application

L'équipe de développement a fait le choix du monorepo pour contenir l'ensemble des éléments de l'application. L'application est composée de :

  • une base de données PostgreSQL,
  • un backend écrit en Python et construit sur FastAPI,
  • un frontend écrit en TypeScript et construit avec ReactJS.

\newpage

L'ensemble se comprend mieux à l'aide du schéma suivant :

Schéma des composants de
l'application{height=55%}

Outils fournis aux développeurs

Via le dépôt, les développeurs ont accès à :

  • une documentation principale via un fichier README.md,
  • une documentation secondaire via :
    • un fichier backend/README.md pour les développeurs du Backend,
    • un fichier frontend/README.md pour les développeurs du Frontend,
  • plusieurs fichiers Docker Compose afin de déployer localement :
    • une base de données (BDD) PostgreSQL avec un jeu de données préchargé,
    • un accès à la BDD via une interface Web, via l'outil nommé adminer,
    • le backend (FastAPI),
    • le frontend (ReactJS),
  • une documentation deployment.md pour déployer le projet à l'aide de Docker Compose,
  • et un fichier docker-compose.traefik.yml afin de déployer une instance locale du proxy Traefik configuré pour utiliser Docker.

Ces éléments sont un bon point de départ pour l'équipe de DevOps qui prendra connaissance des particularités de cette application.

Points d'attentions

La partie Frontend permet de générer des fichiers dits « statiques », du serverless est envisageable. L'application, bien que faisant des appels à une API, fonctionne de manière autonome. Ce qui, a priori, facilite la préparation pour un déploiement. Cependant un nom de domaine est inscrit en dur dans le fichier Dockerfile, ce qui peut compliquer un déploiement sur plusieurs domaines et environnements.

La partie backend s'appuie sur une base de données de type PostgreSQL. Elle est donc dépendante de la BDD.

La partie proxy utilise actuellement Traefik comme outil. Ce qui n'est pas une obligation d'usage pour un déploiement en production.

Ces trois parties ont une influence sur le choix de l'infrastructure à mettre en place. Il reste cependant une marge de manœuvre sur la partie proxy.

Infrastructure

Afin d'accueillir l'application dans le Cloud, l'infrastructure de base va poser les fondations de l'environnement complet nécessaire à un usage quotidien.

Couche basse

La couche basse pourrait se définir comme le minimum nécessaire avant d'installer quoique ce soit pour exploiter l'application. En ce sens, on utilise des éléments de base d'Amazon Web Services (AWS) pour fabriquer notre infrastructure :

  • un espace privé, Virtual Private Cloud (VPC),
  • sur plusieurs régions,
  • avec plusieurs zones de disponibilités (Availability Zone),
  • contenant chacune, d'un point de vue réseau informatique, des réseaux publics (public subnet) et des réseaux privés (private subnet),
  • en utilisant une passerelle entre le VPC et Internet, appelée Internet Gateway (IGW),
  • en utilisant des passerelles NAT (Network Access Translation) entre les réseaux privés et les réseaux publics pour un accès à l'IGW,
  • avec des groupes de sécurité (Security groups) pour définir les règles d'entrée/sortie,
  • et des équilibreurs de charge de type réseau (Network Load Balancer) afin de gérer les accès aux services de manière équilibrée.

\newpage

Le schéma de la couche basse de l'infrastructure ressemble donc à :

Schéma de la couche basse de
l'infrastructure{width=100%}

C'est sur cette base qu'il est possible d'intégrer un environnement capable de déployer, automatiser et gérer des applications conteneurisées.

Environnement Kubernetes

Kubernetes est un système capable de faire tourner des applications conteneurisées, d'automatiser le déploiement et de gérer la mise à l'échelle (auto-scaling).

Sur l'infrastructure présentée dans le paragraphe précédent il va falloir ajouter quelques éléments comme :

  • un cluster Kubernetes appelé EKS (Elastic Kubernetes Service) géré par Amazon,
  • avec l'usage d'une mise à l'échelle (autoscaling) des serveurs virtuels EC2(Elastic Container) d'Amazon,
  • un équilibreur de charge de type réseau entre l'extérieur du cluster et le cluster (AWS Elastic LoadBalancer ou ELB) ; présent d'ailleurs dans le schéma de la couche basse de l'infrastructure dans le paragraphe précédent,
  • un équilibreur de charge de type réseau (couche 4 du modèle OSI - Open Systems Interconnection) qui fait le lien entre les services et l'extérieur du cluster : NGINX Ingress Controller ; il va notamment échanger avec l'AWS Elastic LoadBalancer précédent,
  • l'utilisation d'un agent externaldns qui va mettre à jour les routes DNS (Domain Name System) de Route53 pour les sous-domaines utilisés (~16€/mois pour 3 routes),
  • et avec l'usage de cert-manager pour faire la demande de certificats SSL (Secure Sockets Layer) via le service - gratuit - de Let's Encrypt pour nos sous-domaines.

Le contenu du cluster EKS, une fois implémenté, pourrait ressembler à ceci :

Schéma des applications et services contenu(e)s dans le cluster
EKS{width=100%}

Pourra tourner dans le cluster, en plus des agents précédemment cités, les applications suivantes :

  • le serveur de BDD postgreSQL,
  • le backend de l'application (FastAPI),
  • et le frontend de l'application (en fichiers statiques).

Afin de permettre une livraison régulière de l'application, il va falloir automatiser au maximum les étapes entre la publication d'une nouvelle version de l'application et sa livraison. Puis son déploiement en production via une intervention humaine.

Environnements

Nous parlons de production depuis un moment. À quoi cela correspond ?

Afin de mener à bien le travail de DevOps, nous avons défini les différents environnements par lesquels nous allons passer pour toute notre chaîne de production logicielle. Ainsi nous avons 4 environnements :

  • l'environnement de développement : c'est l'environnement disponible sur chaque machine des développeurs à l'aide des outils fournis (Dockerfile, docker-compose du projet applicatif),
  • l'environnement de test : il est composé de l'ensemble des Runner Gitlab utilisés à l'intérieur de la chaîne d'intégration continue,
  • l'environnement de pré-production (appelé « staging ») : c'est l'infrastructure présentée ci-avant, appliquée dans AWS avec une configuration dite plus légère (moins de machines virtuelles EC2 par exemple),
  • et l'environnement de production : c'est l'infrastructure finale ; celle qui est disponible aux utilisateurs finaux (les usagers).

\newpage

Le schéma des différents environnements est plus compréhensible :

Schéma des environnements
utilisés{height=50%}

[commentaire1]: # Cf. https://mermaid.live/view#pako:eNptkkFugzAQRa9izRoiAiUkLLrKtlKldtXShYUHYtXY1Nhp05AD5Ry5WAcCUSuVFR6_-X4e-QilEQg5VMp8ljtuHXveFprRJ3D_WvG84mGLtjM6FLKupa7Z9nLeozJtiw1q93alP_gE18gte8Zu3ugcH7qmXSU7F5Y7LN_Zo72cw9Ya4UsnjZ7woTCxpTJeEPaLuJmxMLxnvcCGa4FUYJXvCOnJY_a5Io5MOsa9Mw138sNj189Kf_yu9J4rKfhwGKNkj0phPyrNR8-xl_NwCTam94PQP2FSj3GX8wRAAA3ahktB8z4ODQW4HQ2xgJx-BVbcK1dAoU-EDspPB11C7qzHAKzx9Q5oLqqjlW9JE7eS15Y3M9Jy_WJMc4NoDfkRviCPo2SxSdZplEXrKMrWyziAA5Wz5SJJ0ihebrJ4la7i9BTA9xgRLVZJnCXZJrlL19S6CgCFdMY-XN_L-GxOP_j4v68

Livraison continue et déploiement

Il est visé une CI/cd, c'est à dire une Intégration Continue (Continuous Integration) et une livraison continue (continuous delivery). L'automatisation est donc essentielle.

Le déploiement en production passera par une validation manuelle.

Doivent être automatisés :

  • les tests du backend et du frontend,
  • l'étude de sécurité sur les dépendances des composants de l'application,
  • la génération d'une image Docker pour le frontend et le backend,
  • la publication de cette image sur un dépôt d'images,
  • le déploiement d'un environnement de pré-production (appelé staging, dont nous parlerons dans le chapitre Démarche suivie),
  • le déploiement, une fois la validation manuelle sur l'environnement de pré-production faite, d'un environnement de production,
  • et la mise en place initiale de l'infrastructure (appelée boostrap).

Nous retrouverons ces éléments dans les chapitres suivants.

Services et outils divers

Plusieurs sujets tournent autour des services mis en place :

  • les données : définit les éléments enregistrés à l'usage quotidien de l'application,
  • la supervision : définit tous les éléments permettant de mesurer les différents services et d'alerter si les métriques dépassent des seuils définis,
  • la sécurité : définit tout ce qui peut être mis en œuvre pour palier rapidement à des problèmes de sécurité de l'application, de l'infrastructure et des outils utilisés.

Données

Le sujet des données ne couvre pas uniquement les données brutes enregistrées par l'application, mais aussi la manière de les stocker, de les sauver via un plan de sauvegarde et de les restaurer si besoin.

Où sont les données ?

Les données de ce projet sont multiples. En voici une liste non-exhaustive :

  • les dépôts contenant le code applicatif (backend + frontend),
  • les dépôts contenant la description de l'infrastructure,
  • les données brutes de l'application, stockées dans la base de données postgreSQL,
  • les données sensibles (mots de passe, clés d'accès),
  • les copies de sauvegardes des données elle-même,
  • et les fichiers de journalisation des services en production.

Regardons pour chacun des points de cette liste où se situe le stockage.

Stockage

En reprenant les éléments précédent, nous avons :

  • des dépôts Gitlab pour notre code applicatif ET les dépôts de l'infrastructure, gérés par Gitlab,
  • un stockage AWS EBS (Elastic Block Store) pour la base de données postgreSQL,
  • et un stockage AWS S3 (Simple Storage Service) pour les copies de sauvegardes.

Cela devrait être suffisant pour stocker les diverses données disponibles.

\newpage

Base de données postgreSQL

Pour le choix d'un service de base de données, nous avons fini par opter pour postgresql-ha (pour postgreSQL High Availability) qui s'appuie sur 2 bases de données répliquées avec un service pgpool par lequel on accède pour chaque requête faite à la base de données.

Schéma du fonctionnement de
postgreSQL-HA{height=50%}

Sauvegardes

Les dépôts de version utilisés étant sur Gitlab, service qui se targue d'être entre 99% et 100% disponible , une sauvegarde dite « préventive » mensuelle suffit.

En revanche la production, même en étant un service en haute disponibilité, doit fournir au moins une sauvegarde 1 fois par jour. L'outil de sauvegarde choisi est Velero. Compatible avec l'environnement Kubernetes et permettant aussi de sauver l'état du cluster à un moment donné. Son outil en ligne de commande permet de gérer les sauvegardes mais aussi les restaurations de ces dernières.

Comme énoncé précédemment, les sauvegardes du cluster seront mises sur un stockage AWS S3 (dit « bucket S3 »).

\newpage

Le fonctionnement de Velero dans ce projet est visible sur le schéma suivant.

[commentaire2]: # Cf. https://mermaid.live/view#pako:eNptVE1v00AQ_SvWSr0lkWOTOPEBKU2CFLWUgkuRkKVqY08dK7Y37EegRLlxqiqBygFuvSH4B1zopT-I_gTWazteK1g-2G9m35t5s7sbFJAQkIsMxjGHSYwjitP22vKzgwNjMn02O5mdzV6ceH5myEcwoIZrvOZxEjOZL2iBryEBSi6CJJbRx7ub63MFGOPjWZGwHLALvMqjR2IONAMOzBidllFYMhmZHpUqzFYsX38cimAJ3PDshsqKhE0VCRQJIY3XqsDHu9v76aHXHnuz9kSBdRlrkhQZf85JIlJgZQ1zpuBvn_7-_izXFih-z0qt0RvPqPQSEcVZuYwHeTXTs_GkrGGuFnz5fkoYjyh4L4-LgHL01fR4pPmpddRuP60av7lmWKwhwjSEnSN5fM8ACnJsgoI2HS1PjmNvPHm4HkbOEZA0FVn8TkBzVE3B_VjeueaBRvzf3monQ0hxFoIhX5bhFVsQXvijjbBiK4YVPfysesxplPq8oqs46jHurMQ0WEi6_dpDbU9oihXp7T1kFKKY8UpWTrVREuMkWD788stdoA6P2sabAtAEa6B2rOlPjel1afu1BmT7Wva8-N76GWqhFGiK41CeZVWDj_gCUvCRKz9DuMQi4T7ys61MxYIT7yoLkMupgBaiREQL5F7ihMk_sQrrq6BKWeHsLSHpLkn-I3eDPiDXMu3O0B70TMccmKYz6FotdCVhp9ux7Z5pdYeO1e_1rd62hT4qCrPTty3Hdob2k95ALu23EIQxJ_R5cRepK2n7D1LIfM8

Schéma du système de sauvegarde{height=70%}

\newpage

Supervision

Le choix se porte sur Datadog pour sa souplesse et sa capacité à proposer des services supplémentaires de manière progressive.

Le fonctionnement semble simple : installation d'agents Datadog dans le système Kubernetes pour receuillir de nombreuses informations. Comme peut le montrer le schéma suivant.

[commentaire3]: # Cf. https://mermaid.live/view#pako:eNp1VEtu2zAQvQrBImgLKIYs-RctCji2ChhxHMNKUaDQhhZHjiCZNCiqbRL4DgV6gB6g-266C9D79Agl9ZeTaiPyzZsZzvcRB5wCdnAqiYR5RHaC7M8_Wz7z2dkZmrvvF6vF7eJm5fkMqY8SSSjfIQf9_fHtF5oX10IGcarw6Z48cIbcq1Ij4EwKnijJ6s_3jKKnn2hWQuuEMEBPvwviFy5iEG3exwLRhNJ7QLSHHTBZuUY0Q0GSpRJEyWEvcpg2WjDibAsJSMW6Kk5VaOndlhNBlWBenQvRnrNIcv22a32CTLxJ35YiEunYZjwTIoKkANOEBLFCPf03EMig1ySDRAxEP9dhEpgyhuhrcjgkUQ_1T2jWyzSroJFDpENdL5AH4rNOgCrZ7GZ5s6lyn5A0nUOINkBRGCWJ8yoMaUgHRqoKEIMjgJ4wL5MMSioZBCFsK-pWCU6464jFtVkYQFhxD0rQ4uZ123Rc5WW67JrM41nnqnkkG3c5bbVeVbbz83e5dlPuHAlI0yMlpQso603aNBB3ql-ptTu6Nt4Gq2bQgrL606W7uXW95_KqEUoCetYFnZe2yl7jxRhOVx5aumi2_ODdupuyyfTE5kP3WAANWM1cS1AG3gXqpOnveGqlHMgTI52s1YYY6QJNiP_ByxY-dn6F32rHtBzT7jy20lzrYwPvQaiCULXNclUfyzvYg48ddaQQkiyRPvbZUVFJJrl3zwLsSJGBgQXPdnfYCUmSqlt2oM02rCgHwj5xvq9J6o6dR_wVO5Zp9y7sydAcmxPTHE_6loHvFTzu92x7aFr9i7E1Go6s4dHAD7kJszeyrbE9vrAHw4lSHRkYqA7nutjG-VI-_gOoBrf7

Schéma des agents Datadog dans notre système
Kubernetes{height=70%}

Surveillance (monitoring)

Pour le monitoring, on veillera à suivre des indicateurs simples comme l'utilisation CPU et la mémoire vive des instances AWS EC2 (Elastic Compute Cloud) utilisées.

Il y a également :

  • le nombre de pods utilisés par l'instance EC2,
  • et la disponibilité du service de l'application API-Utilisateurs.

Cependant ces moniteurs doivent s'agrémenter d'alertes.

Alertes

On va utiliser un canal Slack (#alertes) pour avertir les DevOps d'une quelconque alerte levée. Datadog permet cela facilement comme énoncé dans l'introduction de ce chapitre sur la Supervision.

Suite aux alertes, les DevOps peuvent opérer et notifier de la prise en charge d'un problème via le chatbot Gitlab intégré à ce canal Slack. Nous utilisons donc le Gitlab ChatOps.

En suivant toutes ces indications, nous devrions avoir une base stable et saine pour constuire une supervision correcte de l'application API-Utilisateurs.

Sécurité

Au niveau de la sécurité, vaste sujet, nous partirons de peu d'éléments :

  • lancement de tests sur le code applicatif,
  • lancement de tests SAST (Static application security testing), sur Terraform notamment,
  • et utilisation d'un coffre fort numérique pour les mots de passes et clés d'accès en tous genres.

Le coffre-fort choisi est Vaultwarden.

Il y a beaucoup à faire pour améliorer la sécurité. Ceci est un processus continu à faire tout au long du suivi et la maintenance du projet.

Conclusion

Les spécifications techniques étant établies, nous allons pouvoir nous concentrer sur la démarche suivie pour mettre en place le projet. C'est à dire comment nous allons atteindre les objectifs du cahier des charges à l'aide des solutions choisies ici-même.