Read in English · Leer en español · Auf Deutsch lesen
Section 10.3 sur 10.8 · Intermédiaire · 20 min de lecture
L’application douze facteurs et les principes cloud native
Leçon vidéo
5 min · narré en anglais, avec sous-titresÉcouter seulement (audio)
Lire la transcription
Kubernetes et toutes les plateformes modernes supposent que les applications se comportent d’une certaine manière. Dans cette leçon, vous allez découvrir ces règles, les douze facteurs, et apprendre à auditer un vrai service à leur aune.
Pensez à une chaîne de cuisines de plats à emporter. Une bonne fiche recette fonctionne dans n’importe quelle succursale : elle énumère chaque ingrédient, et ne dit rien de la succursale où elle se trouve. N’importe quel cuisinier peut la reprendre en plein service, car rien d’important n’est gardé dans la tête d’un seul cuisinier. Et quand la carte change, une nouvelle fiche est imprimée et numérotée, pas griffonnée. L’application douze facteurs est ce genre de fiche recette pour le logiciel.
En 2011, Adam Wiggins, cofondateur de Heroku, a publié The Twelve-Factor App, qui condensait ce que son équipe avait appris en observant un très grand nombre d’applications sur sa plateforme. Ce document est antérieur à Docker et à Kubernetes, et pourtant il décrit presque exactement le contrat que ces plateformes ont imposé par la suite. Et il porte sur la relation d’une application avec sa plateforme, pas sur ses entrailles : un monolithe modulaire peut parfaitement respecter les douze facteurs.
Prenons les facteurs par groupes. Facteur un : une seule base de code sous gestion de versions, déployée dans de nombreux environnements. Facteur deux : chaque dépendance est déclarée, pour que les builds soient reproductibles sur n’importe quelle machine. Les facteurs trois et quatre gardent les URL, les identifiants et les services externes hors du code, accessibles par la configuration. Un test simple : le code pourrait-il être rendu public aujourd’hui sans exposer un seul identifiant ? Le facteur cinq, build, release, run, sépare ces étapes. Nous y reviendrons dans un instant. Les facteurs six à neuf rendent la mise à l’échelle sûre. Les processus sont sans état et ne partagent rien. L’application sert les requêtes en écoutant sur un port. On monte en charge en exécutant davantage de processus de chaque type. Et les processus démarrent vite et s’arrêtent proprement. Les facteurs dix à douze réduisent les surprises : gardez le développement et la production semblables, écrivez les journaux sous forme de flux sur la sortie standard, et exécutez les tâches ponctuelles, comme les migrations, en tant que processus distincts utilisant la même version.
Voici le facteur cinq. L’étape de build transforme un commit en artefact exécutable, aujourd’hui généralement une image de conteneur identifiée par son digest. Elle n’est construite qu’une fois. L’étape de release combine cette image avec la configuration d’un environnement, et donne au résultat une identité, par exemple la version quarante-deux. L’étape de run démarre des processus à partir d’une version. Les versions sont immuables : toute modification du code ou de la configuration produit une nouvelle version, jamais la modification d’une ancienne. Revenir en arrière consiste donc simplement à exécuter de nouveau la version quarante et un, sans rien reconstruire. Personne ne modifie de fichiers sur un serveur, donc les serveurs ne dérivent pas, et ce qui a passé les tests est exactement ce qui tourne.
Auditons un vrai service : le service d’inscription des restaurants de la plateforme de livraison de repas, vieux de cinq ans, sur deux machines virtuelles montées à la main. L’équipe veut le déplacer sur la plateforme de conteneurs, et l’audit relève neuf problèmes. Premièrement, le mot de passe de la base de données de production se trouve dans un fichier du dépôt. Quiconque peut lire le code le possède. Renouvelez-le immédiatement, et placez-le dans le gestionnaire de secrets. Priorité un. Deuxièmement, les cartes et les logos envoyés sont écrits sur le disque local d’une machine. Ils disparaissent quand une requête arrive sur l’autre machine, et ils bloquent tout passage à des conteneurs jetables. Priorité un également. Troisièmement, les sessions sont gardées en mémoire, si bien que chaque déploiement déconnecte le personnel des restaurants au milieu d’un formulaire. Priorité deux. C’est aussi le cas du déploiement par connexion à chaque machine pour y récupérer le code, des migrations exécutées par les deux instances au démarrage et des arrêts brutaux pendant les déploiements : pas de retour arrière, des migrations qui se font concurrence et des formulaires à moitié enregistrés. Les fichiers de journaux, une tâche nocturne sur une seule machine et SQLite sur les portables des développeurs peuvent suivre plus tard, en priorité trois. Remarquez l’ordre : le risque d’abord, car un identifiant exposé est un incident en cours, puis ce qui bloque la plateforme cible, puis la fiabilité, puis la commodité.
Certains conseils ont vieilli. Les variables d’environnement fuient dans les journaux, les rapports de plantage et les processus enfants, si bien que les secrets relèvent désormais d’un gestionnaire de secrets ou, mieux, de l’identité de charge de travail, où la plateforme donne à chaque service des identifiants de courte durée. Sans état ne veut pas dire que le système n’a pas d’état. Cela veut dire que les processus ne le conservent pas : l’état est déplacé vers des services externes conçus pour le garder. Et la pratique actuelle ajoute quatre thèmes : concevoir pour être tué à tout moment, ne jamais corriger ce qui tourne, émettre des journaux, des métriques et des traces, et intégrer la sécurité dès le départ.
La section complète contient un tableau des douze facteurs avec leurs réserves actuelles, ainsi que l’audit complet. Ensuite, dans la section dix point quatre, nous appliquons la même discipline à l’infrastructure elle-même. À très vite.
Ce qu’il faut savoir
- The Twelve-Factor App (Adam Wiggins, Heroku, 2011, passé en open source en 2024) décrit le contrat entre une application et une plateforme moderne, et s’applique aussi bien aux monolithes qu’aux microservices.
- La configuration (III) et les services externes (IV) gardent hors de l’artefact tout ce qui varie d’un déploiement à l’autre, si bien qu’un même artefact tourne dans chaque environnement ; les secrets relèvent désormais d’un gestionnaire de secrets ou de l’identité de charge de travail plutôt que de simples variables d’environnement.
- Build, release, run (V) rend les versions immuables et numérotées, de sorte qu’un retour arrière consiste à exécuter une version antérieure et que personne ne modifie un serveur en fonctionnement.
- Les processus sans état (VI), la concurrence par type de processus (VIII) et la jetabilité (IX) sont ce qui rend sûrs la scalabilité horizontale, les mises à jour progressives et le remplacement des instances défaillantes.
- La parité dev/prod (X), les journaux sous forme de flux (XI) et les processus d’administration exécutés comme des processus ponctuels distincts (XII) réduisent les surprises en production ; les migrations doivent être compatibles avec l’ancien et le nouveau code.
- Au-delà des douze facteurs, les applications cloud native sont conçues pour la jetabilité, l’immuabilité, l’observabilité et la sécurité, et l’extension proposée par Hoffman en 2016 ajoute l’API first, la télémétrie ainsi que l’authentification et l’autorisation.
- Un audit au regard des facteurs doit classer les écarts par risque : d’abord les secrets exposés, puis tout ce qui bloque la plateforme cible, comme l’état local, puis la fiabilité et la commodité.
D’où viennent les douze facteurs
En 2011, Adam Wiggins, cofondateur de Heroku, a publié The Twelve-Factor App, un court document web qui condensait ce que l’équipe de Heroku avait appris en observant un très grand nombre d’applications construites, déployées et mises à l’échelle sur sa plateforme. La méthodologie de l’application douze facteurs (twelve-factor app) décrit des applications qui se mettent en place à partir d’étapes déclaratives et automatisées, ont un contrat clair avec la plateforme sous-jacente afin de pouvoir tourner n’importe où, gardent le développement et la production assez proches pour permettre le déploiement continu, et peuvent monter en charge horizontalement sans refonte.
Le document est antérieur à Docker (2013) et à Kubernetes (2014), et pourtant il décrit presque exactement le contrat que ces plateformes ont imposé par la suite : une application est un ensemble de processus sans état, assemblés en un artefact immuable, configurés de l’extérieur, qui écrivent leurs journaux dans un flux et communiquent avec tout le reste par le réseau. C’est pourquoi il reste le vocabulaire commun de la conception d’applications cloud native. En novembre 2024, Heroku a annoncé que la méthodologie devenait open source, maintenue par une communauté de contributeurs issus de plusieurs entreprises, dans le but de l’actualiser selon les pratiques actuelles ; ses douze facteurs d’origine restent le point de référence.
Les facteurs portent sur la relation de l’application avec sa plateforme d’exécution, pas sur son architecture interne. Un monolithe modulaire peut parfaitement respecter les douze facteurs ; un ensemble de microservices peut les enfreindre tous. Ils complètent les préoccupations de déployabilité et d’exploitabilité du chapitre 2 et les principes de mise à l’échelle et d’absence d’état du chapitre 9.
Les douze facteurs, avec leurs réserves actuelles
| Facteur | Ce que cela signifie | Pourquoi c’est important | Réserve actuelle |
|---|---|---|---|
| I. Base de code | Une seule base de code sous gestion de versions par application, déployée dans de nombreux environnements. | Chaque environnement exécute une version du même code ; pas de forks par client ni par environnement. | Un monorepo contenant plusieurs applications convient si chacune a une frontière claire ; l’anti-pattern, ce sont les forks par copier-modifier. |
| II. Dépendances | Déclarez explicitement chaque dépendance et isolez l’application du système hôte. | Les builds sont reproductibles sur n’importe quelle machine ; rien ne repose sur un paquet que quelqu’un a installé à la main. | Les lockfiles et les images en font le comportement par défaut ; les dépendances épinglées doivent tout de même être mises à jour régulièrement et analysées pour détecter les vulnérabilités. |
| III. Configuration | Gardez tout ce qui varie d’un déploiement à l’autre (URL, identifiants, réglages de fonctionnalités) hors du code, dans l’environnement. | Un même artefact tourne dans chaque environnement ; les secrets n’entrent jamais dans le dépôt. | Les variables d’environnement fuient dans les journaux, les rapports de plantage et les processus enfants ; il vaut mieux lire les secrets depuis un gestionnaire de secrets ou des fichiers montés. |
| IV. Services externes | Traitez les bases de données, files d’attente, caches et API externes comme des ressources attachées, localisées par la configuration. | Une base de données locale peut être remplacée par une base managée, ou une base défaillante par une copie restaurée, en changeant une URL. | Les substitutions sont rarement transparentes quand la sémantique diffère ; isolez les différences derrière des ports et des adaptateurs. |
| V. Build, release, run | Séparez l’assemblage d’un artefact, sa combinaison avec la configuration en une version (release), et son exécution. | Les versions sont immuables et numérotées ; toute version peut être réexécutée ; personne ne modifie le code sur un serveur. | Aujourd’hui : un seul build dans la CI, l’image stockée par digest, les versions enregistrées dans Git ou dans l’outil de déploiement. |
| VI. Processus | Exécutez l’application comme un ou plusieurs processus sans état qui ne partagent rien ; gardez l’état dans des services externes. | N’importe quelle copie peut traiter n’importe quelle requête, donc on peut ajouter, retirer et remplacer des copies librement. | Les sessions persistantes masquent le problème au lieu de le résoudre ; le disque local n’est qu’un espace de travail temporaire. |
| VII. Associations de ports | L’application est autonome et expose son service en écoutant sur un port. | La plateforme lui achemine le trafic sans l’injecter dans un serveur web distinct. | Universel aujourd’hui ; les consommateurs de files d’attente n’ont pas de port, et un service mesh peut se placer devant l’application. |
| VIII. Concurrence | Montez en charge en exécutant davantage de processus, avec des types de processus différents pour des travaux différents (web, worker). | Chaque type de travail passe à l’échelle indépendamment, selon sa propre charge. | Les autoscalers le font automatiquement, y compris selon la longueur des files ; les threads au sein d’un processus comptent toujours. |
| IX. Jetabilité | Démarrer vite, s’arrêter proprement sur SIGTERM, survivre à une mort subite. | Mise à l’échelle rapide, déploiements progressifs sûrs et robustesse face aux plantages. | Les runtimes lents à démarrer ont besoin de sondes de démarrage (startup probes) ou de techniques de démarrage plus rapide ; les tâches d’arrière-plan doivent être idempotentes et pouvoir reprendre. |
| X. Parité dev/prod | Gardez le développement, le staging et la production aussi semblables que possible en matière de délais, de personnes et d’outils. | Moins de surprises qui n’apparaissent qu’en production ; le déploiement continu devient sûr. | La parité totale coûte trop cher ; donnez la priorité aux mêmes types et versions de services externes, en utilisant des conteneurs en local. |
| XI. Journaux | Écrivez les journaux comme un flux d’événements sans tampon sur la sortie standard ; laissez la plateforme les acheminer. | L’application ne gère pas de fichiers ; les journaux de toutes les copies sont collectés de manière centralisée. | Utilisez des journaux structurés, ainsi que des métriques et des traces (par exemple via OpenTelemetry) ; surveillez le volume et le coût des journaux. |
| XII. Processus d’administration | Exécutez les tâches ponctuelles (migrations, scripts) comme des processus distincts utilisant le même code et la même configuration. | Les tâches d’administration s’exécutent sur exactement la version en production, pas sur une copie périmée. | Exécutez-les comme des étapes du pipeline ou des Jobs Kubernetes ; ne laissez jamais chaque réplica exécuter les migrations au démarrage sans verrou. |
Configuration, secrets et services externes
Le facteur configuration a un test simple : la base de code pourrait-elle être rendue publique aujourd’hui sans exposer un seul identifiant ? Si ce n’est pas le cas, la configuration a fui dans le code. Séparer la configuration du code permet à un même artefact de traverser tous les environnements sans modification, ce qui est le fondement du principe build once (construire une seule fois) de la section 10.5 (CI/CD et déploiement). La configuration comprend les URL des bases de données et des services, les identifiants et les réglages propres à chaque environnement ; elle exclut le câblage interne identique partout, par exemple quelle classe traite quelle route, qui relève du code.
La recommandation d’origine d’utiliser des variables d’environnement a vieilli de façon inégale. Elles sont universelles et indépendantes du langage, et Kubernetes, les plateformes PaaS et les fonctions les prennent toutes en charge. Mais l’environnement d’un processus est visible par les processus enfants, se retrouve souvent recopié dans les rapports de plantage et les pages de débogage, et ne peut pas faire l’objet d’une rotation sans redémarrage. La pratique actuelle pour les secrets consiste à les récupérer au démarrage depuis un gestionnaire de secrets (AWS Secrets Manager, Azure Key Vault, Google Secret Manager, HashiCorp Vault ou OpenBao) ou à les monter sous forme de fichiers que la plateforme peut mettre à jour, et mieux encore à remplacer les secrets à longue durée de vie par l’identité de charge de travail, où la plateforme donne automatiquement à chaque service des identifiants de courte durée. L’intention du facteur, garder la configuration hors de l’artefact, reste inchangée.
Traiter un service externe (backing service) comme une ressource attachée signifie que le code atteint la base de données des commandes, le prestataire de paiement et le courtier de messages de la même façon : par une URL et des identifiants fournis au moment du déploiement. Cela rend les environnements composables et la reprise plus rapide. Cela ne rend pas pour autant les services externes interchangeables par magie ; remplacer un courtier de messages par un autre change la sémantique de livraison. Le style hexagonal du chapitre 5 complète le facteur : la configuration dit où se trouve la ressource, et un adaptateur derrière un port masque son comportement.
Build, release, run (assembler, publier, exécuter)
Le facteur build, release, run (assembler, publier, exécuter) sépare trois étapes souvent confondues. L’étape de build transforme un commit en artefact exécutable, aujourd’hui généralement une image de conteneur identifiée par son digest. L’étape de release combine cet artefact avec la configuration d’un environnement et donne au résultat une identité, par exemple la version v42 du service des commandes en production. L’étape de run démarre des processus à partir d’une version. Les versions sont immuables : une modification du code ou de la configuration produit une nouvelle version, jamais la modification d’une version existante.
Un seul build, une version par environnement, une exécution n’importe où
C’est cette séparation qui rend le déploiement ennuyeux. Personne ne modifie de fichiers sur un serveur, donc les serveurs ne dérivent pas ; l’image qui a passé les tests en staging est celle qui tourne en production, donc un résultat de test a un sens ; et le retour arrière est une opération rapide et rodée plutôt qu’une reconstruction en urgence. C’est aussi une piste d’audit : pour n’importe quel moment, vous pouvez dire exactement quel code et quelle configuration tournaient. Kubernetes conserve un historique des révisions des ReplicaSets de chaque Deployment, les plateformes PaaS numérotent les versions, et GitOps (section 10.4) fait de l’historique Git du dépôt des versions la référence.
Processus, concurrence et jetabilité
Des processus sans état, qui ne partagent rien, sont la condition préalable de presque tout le reste de ce chapitre : scalabilité horizontale, déploiements progressifs, autoscaling, remplacement des nœuds défaillants et répartition sur plusieurs zones. Tout ce qu’un processus garde uniquement en mémoire ou sur son disque local (la session d’un utilisateur, un fichier envoyé, un rapport en partie construit) est perdu quand ce processus est remplacé, et reste invisible pour les autres copies. Le chapitre 9 traite en détail de la gestion des sessions (équilibrage de charge, absence d’état et sessions). L’état ne disparaît pas ; il est déplacé vers des services externes conçus pour le conserver.
Le facteur concurrence ajoute que les différents types de travail doivent s’exécuter comme des types de processus différents qui passent à l’échelle séparément. Dans la plateforme de livraison de repas, le processus web qui sert l’app client passe à l’échelle selon le débit de requêtes, tandis qu’un processus worker qui envoie les confirmations de commande passe à l’échelle selon la longueur de la file, et un consommateur des positions des livreurs selon le débit d’événements. Les mélanger dans un seul type de processus oblige à tous les mettre à l’échelle pour les besoins d’un seul.
La jetabilité (disposability) exige que les processus démarrent en quelques secondes et s’arrêtent proprement. À la réception de SIGTERM, un processus web cesse d’accepter des connexions et termine les requêtes en cours ; un worker remet son message courant dans la file ou le termine dans le délai de grâce. Comme les processus peuvent aussi mourir sans prévenir (une panne de nœud, un arrêt forcé pour mémoire insuffisante), le travail doit pouvoir être répété sans danger : traitement idempotent des messages, comme dans l’architecture pilotée par les événements, et tâches qui reprennent à partir de points de contrôle. George Candea et Armando Fox ont poussé l’idée à l’extrême en 2003 avec le crash-only software, qui n’a qu’une façon de s’arrêter (planter) et une façon de démarrer (la reprise), de sorte que le chemin de reprise est exercé en permanence au lieu d’être découvert pendant un incident.
Parité dev/prod, journaux et processus d’administration
Le texte d’origine identifie trois écarts entre le développement et la production : le temps (du code écrit des semaines avant d’être déployé), le personnel (les développeurs l’écrivent, les opérateurs le déploient) et les outils (SQLite sur un portable, PostgreSQL en production). La livraison continue comble le premier, les équipes qui exploitent ce qu’elles construisent comblent le deuxième, et les conteneurs comblent une grande partie du troisième : un développeur peut exécuter en local la même version de PostgreSQL, le même courtier de messages et le même cache, et des outils comme Testcontainers démarrent de vraies dépendances dans les tests d’intégration. Une parité parfaite n’est ni abordable ni nécessaire ; l’essentiel est d’utiliser les mêmes types et versions de services externes, car c’est là que se cachent les différences surprenantes.
Traiter les journaux comme des flux d’événements signifie que l’application écrit chaque événement sur la sortie standard et laisse à la plateforme le stockage, la rotation et l’expédition. Cela reste juste, avec deux ajouts modernes : les journaux doivent être structurés (par exemple en JSON, avec des noms de champs cohérents et un identifiant de requête ou de trace), et les journaux sont l’un des trois signaux, avec les métriques et les traces, qui rendent un système observable (observabilité). Le volume des journaux est aussi un vrai facteur de coût ; la section 10.8 y revient.
Les processus d’administration, comme les migrations de base de données, les réparations de données et les rapports ponctuels, doivent s’exécuter avec la même version (code et configuration) que l’application, sous forme de processus distincts. Dans Kubernetes, cela signifie généralement un Job exécuté par le pipeline avant le déploiement de la nouvelle version. Les migrations demandent un soin particulier : elles doivent être compatibles à la fois avec l’ancienne et la nouvelle version du code qui tournent côte à côte, ce qui correspond à la discipline d’expansion-contraction de l’évolution des schémas.
Au-delà des douze facteurs
Les douze facteurs n’ont jamais prétendu être complets, et des auteurs ultérieurs les ont étendus. Beyond the Twelve-Factor App de Kevin Hoffman (O’Reilly, 2016) a porté la liste à quinze, en ajoutant API first (concevoir le contrat avant l’implémentation), la télémétrie (intégrer métriques, santé et traçage) ainsi que l’authentification et l’autorisation (la sécurité comme préoccupation de conception dès le départ). La pratique actuelle ajoute quatre thèmes que toute application cloud native devrait respecter.
La jetabilité, prise au sérieux. Concevez pour être tué à tout moment : opérations idempotentes, délais d’expiration courts pour les requêtes, temps de démarrage borné, drainage en douceur, et aucun processus unique dont la perte compte. L’immuabilité. Ne corrigez jamais un conteneur ou un serveur en fonctionnement ; construisez une nouvelle image et remplacez-le (section 10.4 sur l’infrastructure immuable). Chaque instance en cours d’exécution devient ainsi traçable jusqu’à un commit, et la dérive disparaît. L’observabilité. Émettez des journaux structurés, des métriques et des traces via un standard comme OpenTelemetry, exposez des endpoints de santé qui reflètent l’état propre du processus, et propagez le contexte de trace d’un appel à l’autre, afin que les opérateurs puissent répondre à des questions qu’ils n’avaient pas anticipées. La sécurité. Exécutez sous un utilisateur non root, avec un système de fichiers en lecture seule quand c’est possible ; obtenez les identifiants par l’identité de charge de travail plutôt que par des clés à longue durée de vie ; appliquez le moindre privilège à chaque service externe ; et construisez à partir d’images minimales, analysées et signées (sécurité de la chaîne d’approvisionnement).
Exemple commenté
Exemple commenté : l’audit du service d’inscription des restaurants
Le service d’inscription des restaurants de la plateforme de livraison de repas est une application web vieille de cinq ans, installée sur deux machines virtuelles montées à la main derrière un équilibreur de charge à sessions persistantes. L’équipe veut la déplacer sur la plateforme de conteneurs de l’entreprise. Un audit au regard des facteurs relève neuf problèmes ; chacun reçoit un risque, une correction et une priorité.
| 1. Mot de passe de la base de données de production dans un fichier de propriétés du dépôt (III) | Risque : toute personne ayant accès en lecture au code, y compris d’anciens prestataires, possède l’identifiant. Correction : renouveler le mot de passe immédiatement, le placer dans le gestionnaire de secrets, l’injecter au moment du déploiement. Priorité 1. |
|---|---|
| 2. Cartes et logos envoyés, écrits sur le disque local de la VM (VI, IV) | Risque : les fichiers disparaissent quand une requête arrive sur l’autre VM ou qu’une VM est remplacée ; bloque tout passage à des conteneurs jetables. Correction : stockage objet, avec une copie ponctuelle des fichiers existants. Priorité 1. |
| 3. Sessions dans la mémoire du processus, répartition de charge persistante (VI) | Risque : chaque déploiement déconnecte le personnel des restaurants au milieu d’un formulaire. Correction : jetons de session signés ou stockage de sessions partagé. Priorité 2. |
4. Déploiement par SSH, git pull et redémarrage sur chaque VM (V, II) | Risque : les deux VM exécutent un code différent après un pull raté ; pas de retour arrière. Correction : la CI construit une image par commit ; versions numérotées. Priorité 2. |
| 5. Migrations exécutées automatiquement au démarrage par les deux instances (XII) | Risque : les deux instances se disputent la même migration. Correction : une étape de migration distincte dans le pipeline, avec des changements en expansion-contraction. Priorité 2 (priorité 1 si une telle situation de concurrence s’est déjà produite). |
6. Arrêt par kill -9 pendant les déploiements (IX) | Risque : formulaires d’inscription à moitié enregistrés. Correction : gérer SIGTERM, drainer les requêtes, ajouter une sonde de disponibilité (readiness) et un délai pre-stop. Priorité 2. |
| 7. Journaux écrits dans des fichiers à rotation sur chaque VM (XI) | Risque : journaux perdus avec la VM ; recherche difficile d’une instance à l’autre. Correction : JSON structuré sur la sortie standard, collecté de manière centralisée. Priorité 3, peu coûteux à faire en même temps que le point 4. |
| 8. Rapport nocturne des reversements en tâche cron sur la VM 1 seulement (XII, VIII) | Risque : la tâche s’arrête sans bruit quand la VM 1 est reconstruite, ou s’exécute deux fois si elle est copiée. Correction : une tâche planifiée sur la plateforme, rendue idempotente. Priorité 3. |
| 9. Les développeurs utilisent SQLite, la production PostgreSQL (X) | Risque : du SQL qui fonctionne en local échoue en production. Correction : PostgreSQL dans un conteneur pour le développement et les tests. Priorité 3. |
Les priorités suivent d’abord le risque (un identifiant exposé est un incident en cours), puis ce qui bloque la plateforme cible (l’état local), puis la fiabilité, puis la commodité.
L’équipe n’a pas besoin de tout corriger avant de migrer : les points 1 et 2 sont des prérequis ; les points 3 à 6 peuvent être traités pendant le déplacement ; les points 7 à 9 peuvent suivre.
Un audit comme celui-ci est aussi une bonne matière pour un enregistrement de décision d’architecture : il explique pourquoi chaque changement est fait, dans quel ordre, et ce qui a été délibérément reporté.
Questions fréquentes
Toute application doit-elle respecter les douze facteurs ?
Non. Ils forment une liste de contrôle de propriétés qui rendent le déploiement, la mise à l’échelle et la reprise peu coûteux sur une plateforme moderne. Traitez chaque écart comme un risque assorti d’un coût, et corrigez d’abord ceux qui bloquent votre plateforme ou menacent la sécurité, comme dans l’audit ci-dessus.
La méthodologie s’applique-t-elle aux fonctions serverless ?
En grande partie, et la plateforme en impose l’essentiel : les fonctions sont sans état, configurées de l’extérieur, jetables et journalisées par la plateforme. Les facteurs qui demandent encore de l’attention sont la configuration et les secrets, les services externes, l’idempotence et la parité dev/prod, car l’émulation locale des sources d’événements d’un fournisseur est imparfaite.
Les douze facteurs sont-ils encore pertinents maintenant que Kubernetes existe ?
Oui, car Kubernetes les présuppose. Un pod qui garde les sessions en mémoire, écrit des fichiers en local ou met deux minutes à démarrer contrarie les mises à jour progressives, l’autoscaling et la replanification de la plateforme. Les facteurs décrivent ce qu’une application doit faire pour que l’automatisation de la plateforme l’aide au lieu de lui nuire.
Vérifiez votre compréhension
Quel test simple montre si la configuration a fui dans le code ?
Demandez-vous si la base de code pourrait être rendue publique aujourd’hui sans exposer aucun identifiant. Si ce n’est pas le cas, la configuration (au moins les secrets) se trouve dans le code.
Pourquoi build, release, run rend-il le retour arrière rapide ?
Chaque version est une combinaison immuable d’un artefact construit et d’une configuration, avec sa propre identité ; revenir en arrière consiste donc à exécuter de nouveau la version précédente, sans rien reconstruire ni modifier.
Un service stocke les fichiers envoyés sur le disque local de son serveur. Quel facteur cela enfreint-il, et qu’est-ce qui ne fonctionne plus ?
Les processus (VI), et sans doute les services externes (IV) : les fichiers manquent quand les requêtes atteignent une autre copie, et sont perdus quand l’instance est remplacée, ce qui bloque la scalabilité horizontale et les conteneurs jetables.
Pourquoi les migrations ne devraient-elles pas s’exécuter automatiquement dans chaque réplica au démarrage ?
Plusieurs réplicas risquent d’exécuter la même migration en même temps et d’entrer en concurrence, et le démarrage devient lent et fragile. Les migrations doivent s’exécuter une seule fois, comme une étape d’administration distincte dans le pipeline, avec la même version.
Sources et lectures complémentaires
Une question sur cette section ? ArchitectBot, l’assistant d’étude IA du cours, répond d’abord à partir du cours.
Demander : « Quels écarts aux douze facteurs devons-nous corriger avant de déplacer un ancien service vers Kubernetes, et lesquels peuvent attendre ? »