gwift-book/source/part-1-workspace/12-factors.adoc

13 KiB
Raw Blame History

<<<<<<< Updated upstream == 12 facteurs

== Douze facteurs >>>>>>> Stashed changes

Pour la méthode de travail et de développement, on va se baser sur les The Twelve-factor App - ou plus simplement les 12 facteurs.

Lidée derrière cette méthode, et indépendamment des langages de développement utilisés, consiste à suivre un ensemble de douze concepts , afin de:

<<<<<<< Updated upstream . Faciliter la mise en place de phases dautomatisation; plus concrètement, de faciliter les mises à jour applicatives, simplifier la gestion de lhôte, diminuer la divergence entre les différents environnements dexécution et offrir la possibilité dintégrer le projet dans un processus dintégration continue/déploiement continu . Faciliter la mise à pied de nouveaux développeurs ou de personnes souhaitant rejoindre le projet . Minimiser les divergences entre les différents environnemens composant un projet . Augmenter lagilité générale du projet, en permettant une meilleure évolutivité architecturale et une meilleure mise à léchelle - Vous avez 5000 utilisateurs en plus? Ajoutez un serveur et on nen parle plus ;-).

  1. Faciliter la mise en place de phases dautomatisation; plus simplement, faciliter les mises à jour applicatives, simplifier la gestion de lhôte, diminuer la divergence entre les différents environnements dexécution, faciliter la maintenance et offrir la possibilité dintégrer le projet dans un processus dintégration continue/déploiement continu

  2. Faciliter la mise à pied de nouveaux développeurs ou de personnes rejoignant le projet. A linverse, faciliter également le départ dautres personnes et la communication générale.

  3. Définir des bonnes pratiques à chaque étape de la chaîne.

  4. Réduire les frictions entre les équipes de développement et les équipes dopération.

  5. Augmenter lagilité générale du projet, en permettant une meilleure évolutivité architecturale et une meilleure mise à léchelle - Vous avez 5000 utilisateurs en plus? Ajoutez un serveur et on nen parle plus ;-). >>>>>>> Stashed changes

En pratique, les idées qui se trouvent derrière les points ci-dessus permettront de monter facilement un nouvel environnement - quil soit sur la machine du petit nouveau dans léquipe, sur un serveur Azure/Heroku/Digital Ocean ou votre nouveau Raspberry Pi Zéro caché à la cave.

Pour reprendre de manière très brute les différentes idées derrière cette méthode, on a:

<<<<<<< Updated upstream . Une base de code unique, suivie par un système de contrôle de versions. Chaque déploiement de lapplication se basera sur cette source, afin de minimiser les différences que lon pourrait trouver entre deux environnements dun même projet. On utilisera un dépôt Git - Github, Gitlab, Gitea, …​ Au choix.

  1. Déclarez explicitement les dépendances nécessaires au projet, et les isoler du reste du système lors de leur installation. Lidée est que chaque installation ou configuration se fasse toujours de la même manière, et puisse être répétée quel que soit lenvironnement cible. Cela permet également déviter que lapplication nutilise une dépendance qui soit déjà installée sur un des sytèmes de développement, et quelle soit difficile à répercuter sur un autre environnement. Dans notre cas, cela pourra être fait au travers de pip - Package Installer for Python. Dans tous les cas, chaque application doit disposer dun environnement sain, qui lui est assigné, et vu le peu de ressources que cela coûte, il ne faut pas sen priver.

  2. Sauver la configuration directement au niveau de lenvironnement. On veut par exemple éviter davoir à recompiler/redéployer lapplication parce que ladresse du serveur de messagerie a été modifiée, ou parce quun protocole a changé en cours de route. Concrètement, toute information susceptible de modifier le comportement intrinsèque de lapplication doit se trouver dans un fichier ou dans une variable denvironnement. En allant un pas plus loin, cela permettra de paramétrer facilement un container, simplement en modifiant une variable de configuration, qui spécifiera la base de données sur laquelle lapplication devra se connecter. Toute clé de configuration (nom du serveur de base de données, adresse dun service Web externe, clé dAPI pour linterrogation dune ressource, …​) sera définie directement au niveau de lhôte - à aucun moment, on ne doit trouver un mot de passe en clair dans le dépôt source ou une valeur susceptible dévoluer, écrite en dur dans le code.

  3. Traiter les ressources externes comme des ressources attachées. On parle de bases de données, de services de mise en cache, dAPI externes, …​ Lapplication doit également être capable deffectuer des changements au niveau de ces ressources sans que le code intrinsèque ne soit modifié. On parle alors de ressources attachées, dont la présence est nécessaire au bon fonctionnement de lapplication, mais pour lesquelles le type nest pas obligatoirement défini. On veut par exemple "une base de données" et "une mémoire cache", et pas "une base MariaDB et une instance Memcached". De cette manière, les ressources peuvent être attachées et détachées dun déploiement à la volée. Si une base de données ne fonctionne pas correctement (problème matériel?), ladministrateur pourrait simplement restaurer un nouveau serveur à partir dune précédente sauvegarde, et lattacher à lapplication sans que le code source ne soit modifié. une solution consiste à passer toutes ces informations (nom du serveur et type de base de données, clé dauthentification, …​) directement via des variables denvironnement.

  4. Séparer proprement les phases de construction, de mise à disposition et dexécution. La construction (build) convertit un code source en un ensemble de fichiers exécutables, associé à une version et à une transaction dans le système de gestion de sources. La mise à disposition (release) associe cet ensemble à une configuration prête à être exécutée, tandis que la phase d'exécution (run) démarre les processus nécessaires au bon fonctionnement de lapplication. On doit pouvoir se baser sur les releases de Gitea, sur un serveur dartefacts ou sur Capistrano.

  5. Les processus dexécution ne doivent rien connaître ou conserver de létat de lapplication. On suppose donc que toute information stockée en mémoire ou sur disque naltérera pas le comportement futur de lapplication, par exemple après un redémarrage non souhaité. Si une réinitialisation devait être nécessaire, lapplication ne devra pas compter sur la présence dune information au niveau du système.

  6. Autoriser la liaison dun port de lapplication à un port du système hôte. Les applications 12-factors sont auto-contenues et peuvent fonctionner en autonomie totale. Lidée ici est quelles puissent être joignables grâce à un mécanisme de pont, où lhôte effectue la redirection vers lun des ports ouverts par lapplication, typiquement, en HTTP ou via un autre protocole.

  7. Faites confiance aux processus systèmes pour lexécution de lapplication. Comme décrit plus haut, lapplication doit utiliser des processus stateless (sans état). On peut donc facilement créer et utiliser des processus supplémentaires pour tenir plus facilement une lourde charge, ou dédier des processus particuliers pour certaines tâches: requêtes HTTP via des processus Web; long-running jobs pour des processys asynchrones, …​

  8. Améliorer la robustesse de lapplication grâce à des arrêts élégants et à des démarrages rapides. Par "arrêt élégant", on veut surtout éviter le kill -9 <pid> ou tout autre rechargement brutal du superviseur; de cette manière, on évite quune requête dun utilisateur naboutisse sur un code derreur. Au contraire, les requêtes en cours doivent être terminées au mieux, tandis que le démarrage rapide de nouveaux processus limite les perturbations et améliore la balance du travail dun processus en cours dextinction vers des processus tout frais. Lintégration de ces mécanismes dès les premières étapes de développement limite les perturbations et facilite la prise en compte darrêts inopinés (problème matériel, redémarrage du système hôte, etc.).

  9. Conserver les différents environnements aussi similaires que possible, et limiter les divergences entre un environnement de développement et de production. Lexemple donné est un développeur qui utilise macOS, NGinx et SQLite, tandis que lenvironnement de production tourne sur une CentOS avec Apache2 et PostgreSQL. Lidée derrière ce concept limite les divergences entre environnements, facilite les déploiements et limite la casse et la découverte de modules non compatibles dès les premières phases de développement.

  10. Gérer les journeaux dévènements comme des flux. Une application ne doit jamais se soucier de lendroit où ces évènements seront écrits, mais simplement de les envoyer sur la sortie stdout. De cette manière, quon soit en développement sur le poste dun développeur avec une sortie console ou sur une machine de production avec un envoi vers une instance Greylog, le routage des journaux sera réalisé en fonction de sa nécessité et de sa criticité.

  11. Isoler les tâches administratives du reste de lapplication. Evitez quune migration puisse être démarrée depuis une URL de lapplication, ou quun envoi massif de notifications ne soit accessible pour nimporte quel utilisateur: les tâches administratives ne doivent être accessibles quà un administrateur. Les applications 12facteurs favorisent les langages qui mettent un environnement REPL (pour Read, Eval, Print et Loop) à disposition (au hasad: Python).

Note
pensez à retravailler la partie ci-dessous; la version anglophone semble plus compréhensible… :-/
  1. Une base de code suivie, avec un système de contrôle de versions, doù démarreront chaque déploiement.

  2. Déclarez explicitement et isolez les dépendances

  3. Stockez la configuration dans des variables denvironnement

  4. Traitez les services externes comme des ressources attachées (?)

  5. Séparez strictement les étapes dassemblage et dexécution

  6. Exécutez lapplication comme un ou plusieurs processus sans état

  7. Exportez les services via des associations de ports (?)

  8. Grossissez à laide du modèle de processus (?)

  9. Maximisez la robustesse et la disponibilité avec des démarrages rapides et des arrêts gracieux (la commande kill -9 est donc à proscrire)

  10. Gardez le développement, la validation et la production aussi proches lun de lautre que possible

  11. Traitez les logs comme des flux dévènements (?)

  12. Lancez les processus dadministration et de maintenance comme des one-off-processes (?)

Table 1. Concrètement

Concept

Concept

Outil

Description

1

Base de code suivie avec un système de contrôle de version

Git, Mercurial, SVN, …​

Chaque déploiement démarre à partir dune base de code unique. Il ny pas de dépôt "Prod", "Staging" ou "Dev". Il ny en a quun et un seul.

2

Déclaration explicite et isolation des dépendances

Pyenv, environnements virtuels, RVM, …​

Afin de ne pas perturber les dépendances systèmes, chaque application doit disposer dun environnement sain par défaut.

3

Configuration dans lenvironnement

Fichiers .ENV

Toute clé de configuration (nom du serveur de base de données, adresse dun service Web externe, clé dAPI pour linterrogation dune ressource, …​) sera définie directement au niveau de lhôte - à aucun moment, on ne doit trouver un mot de passe en clair dans le dépôt source ou une valeur susceptible dévoluer, écrite en dur dans le code.

4

Services externes = ressources locales

Fichiers .ENV

Chaque ressource doit pouvoir être interchangeable avec une autre, sans modification du code source. La solution consiste à passer toutes ces informations (nom du serveur et type de base de données, clé dauthentification, …​) directement via des variables denvironnement.

5

Bien séparer les étapes de construction des étapes de mise à disposition

Capistrano, Gitea, un serveur dartefacts, …​

Lidée est de pouvoir récupérer une version spécifique du code, sans que celle-ci ne puisse avoir été modifiée. Git permet bien de gérer des versions (au travers des tags), mais ces éléments peuvent sans doute être modifiés directement au travers de lhistorique.

>>>>>>> Stashed changes