349 lines
17 KiB
Markdown
349 lines
17 KiB
Markdown
\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 :
|
|
|
|
{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 à :
|
|
|
|
{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 :
|
|
|
|
{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 :
|
|
|
|
{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](#demarche)),
|
|
* 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.
|
|
|
|
{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](
|
|
https://handbook.gitlab.com/handbook/engineering/monitoring/#historical-service-availability)
|
|
, 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
|
|
|
|
{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
|
|
|
|
{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**](https://docs.gitlab.com/ci/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.
|