← Toutes les fiches

Fiche 19 Parcours : DevOps Lecture : 25 minutes

Infrastructure et cloud

Où tourne ton application, comment elle survit à une panne, et combien ça coûte vraiment.

Une application, c'est du code, mais aussi des machines, un réseau, une base de données, des fichiers, et une facture. Cette fiche part du cas le plus simple, un seul serveur, et montre ce qui change quand le trafic grandit ou quand une panne n'est plus acceptable. Puis elle compare les façons d'héberger : ton propre serveur, le cloud à la demande, les plateformes gérées et le serverless.

Le but n'est pas de t'envoyer sur l'architecture la plus impressionnante. C'est de savoir laquelle correspond à ton besoin, et ce qu'elle coûte en argent comme en travail. Beaucoup d'applications vivent très bien sur un seul serveur.

1.Le point de départ : un serveur

La boutique tourne sur un VPS (Virtual Private Server), une machine virtuelle louée quelques dizaines d'euros par mois. Tout est dessus : nginx, PHP-FPM, PostgreSQL, Redis, les tâches planifiées, les fichiers envoyés par les clients. C'est ce que tu as appris à administrer en fiche 11.

  1. C'est simple : une seule machine à comprendre, à surveiller et à sauvegarder.
  2. C'est bon marché, et le coût est fixe et prévisible.
  3. C'est un point unique de panne (single point of failure) : si la machine tombe, tout tombe. Une mise à jour du système qui demande un redémarrage coupe aussi le site.
  4. Tout se partage : un import lourd ou une requête SQL lente ralentit aussi les pages vues par les clients.
Quand un serveur suffit

Pour un site interne, une association, un produit qui démarre ou une boutique à quelques milliers de visites par jour, un serveur bien sauvegardé (fiche 13), surveillé et mis à jour reste souvent le meilleur choix. Une coupure de quelques minutes par mois y est acceptable. Ne paie pas tout de suite pour des problèmes que tu n'as pas encore.

2.Grandir : verticalement ou horizontalement

Le trafic double, le serveur sature. Il existe deux façons de grandir (en anglais, scaling) :

Grandir : une machine plus grosse, ou plus de machines À gauche, grandir verticalement : on remplace un serveur de 2 processeurs et 4 Go par un serveur de 16 processeurs et 64 Go. Rien ne change dans le code, mais il y a une limite, souvent un arrêt, et toujours un seul point de panne. À droite, grandir horizontalement : un répartiteur de charge envoie les requêtes à trois serveurs identiques. On ajoute ou retire des machines, et une panne n'arrête pas tout, mais l'application doit être sans état. Verticalement : une machine plus grosse Horizontalement : plus de machines serveur 2 CPU, 4 Go serveur 16 CPU, 64 Go + rien à changer dans le code − une limite : la plus grosse machine − souvent un arrêt pour changer − toujours un seul point de panne Répartiteur de charge répartit les requêtes serveur 2 CPU, 4 Go serveur 2 CPU, 4 Go serveur 2 CPU, 4 Go + on ajoute ou retire des machines + une machine tombe, les autres restent − l'application doit être sans état − un répartiteur à gérer en plus
Schéma 19.1 · Grandir : une machine plus grosse, ou plus de machines
  1. Verticalement (scale up) : une machine plus grosse. C'est le premier réflexe, et souvent le bon : aucun changement dans le code. Mais il y a une limite, et la machine reste unique.
  2. Horizontalement (scale out) : plusieurs machines identiques derrière un répartiteur de charge (load balancer, fiche 9). Plus de limite théorique, et une machine peut tomber sans couper le site. C'est aussi ce que fait Kubernetes avec ses réplicas (fiche 12).

Une condition apparaît pour la seconde : la requête suivante d'un client peut arriver sur une autre machine. L'application doit donc fonctionner sans rien garder sur le disque local.

3.Une application sans état

Une application sans état (stateless) ne garde rien d'important sur la machine qui l'exécute. Prenons les sessions : par défaut, Symfony les range dans des fichiers, sur le disque du serveur. Avec deux serveurs et un répartiteur qui envoie les requêtes à tour de rôle, Alice se connecte sur le serveur A, qui range sa session sur son disque. Sa requête suivante arrive sur le serveur B, qui n'a jamais vu cette connexion : pour lui, Alice est anonyme (schéma 19.2). Le même problème touche tout ce qui reste sur le disque local. Il faut tout recenser, et déplacer chaque chose dans un service partagé :

Ce qui est sur le disqueLe problème avec deux serveursOù le mettre
Les sessionsDéconnexions au hasardRedis ou la base de données
Les fichiers envoyésL'image est sur un serveur, pas sur l'autreUn stockage objet (S3 ou compatible), avec Flysystem
Le cache applicatifChaque serveur a sa version, parfois périméeRedis
Les verrous (Lock)Deux serveurs prennent le même verrouRedis ou la base de données
Les tâches planifiéesLa facture mensuelle part en deux exemplairesUne seule instance, ou le Scheduler avec un verrou
Les logsÉparpillés, et perdus quand la machine disparaîtLa sortie standard, collectée ailleurs (fiche 21)
Deux serveurs, et des sessions qui doivent être partagées En haut, chaque serveur garde les sessions sur son propre disque. Le répartiteur envoie la connexion d'Alice au serveur A, qui enregistre sa session, puis la requête suivante au serveur B, qui ne la connaît pas : Alice est déconnectée. En bas, les deux serveurs lisent et écrivent la session dans Redis : Alice reste connectée, quel que soit le serveur. Sessions sur le disque de chaque serveur Répartiteur à tour de rôle serveur A serveur B 1. connexion 2. panier disque de A : session d'Alice, connectée disque de B : rien, Alice est déconnectée Sessions dans Redis, partagé par les serveurs Répartiteur à tour de rôle serveur A serveur B 1. connexion 2. panier Redis session d'Alice Connectée sur A comme sur B. Avec des sessions locales, Alice est déconnectée une requête sur deux, au hasard du répartiteur.
Schéma 19.2 · Deux serveurs, et des sessions qui doivent être partagées
exemples/19/stateless.yaml · illustration, non exécuté
# config/packages/framework.yaml (extrait) : rien d'important sur le disque du serveur
framework:
    session:
        handler_id: '%env(REDIS_URL)%'       # sessions partagées par tous les serveurs
    cache:
        app: cache.adapter.redis
        default_redis_provider: '%env(REDIS_URL)%'
    lock: '%env(REDIS_URL)%'                # un verrou visible de tous les serveurs

Le cache de Symfony lui-même (le dossier var/cache, construit au déploiement) peut rester local : il est identique sur chaque machine, puisqu'il vient de la même image (fiche 18).

4.Une architecture type

Voici la forme que prennent beaucoup d'applications web chez un fournisseur cloud. Chaque bloc existe aussi en « service géré » : le fournisseur s'occupe des mises à jour, des sauvegardes et du remplacement en cas de panne.

Une architecture web type, répartie sur deux zones Les utilisateurs passent par un CDN pour les fichiers statiques, puis par un répartiteur de charge, seul élément public, placé dans un réseau privé de la région Paris. Le réseau est réparti sur deux zones. Chacune a un sous-réseau privé avec des conteneurs de l'application. La zone A a aussi les workers Messenger et la base PostgreSQL principale. La zone B a Redis pour les sessions et le cache, et une base PostgreSQL de secours, copie de la principale. Les fichiers envoyés vont dans un stockage objet. Utilisateurs navigateurs, mobiles CDN images, CSS, JS en cache Stockage objet (S3) fichiers envoyés Réseau privé (VPC), région Paris Répartiteur de charge seul élément public Zone A : sous-réseau privé Application conteneurs PHP Workers Messenger PostgreSQL principale Zone B : sous-réseau privé Application conteneurs PHP Redis sessions, cache PostgreSQL de secours copie Seul le répartiteur est joignable depuis Internet. Une zone entière peut tomber (un incendie, une panne de courant) : l'autre continue, et la base de secours prend le relais.
Schéma 19.3 · Une architecture web type, répartie sur deux zones
  1. Un réseau privé (VPC, Virtual Private Cloud) : les serveurs et la base n'ont pas d'adresse publique. Seul le répartiteur de charge est joignable depuis Internet. Pour administrer, on passe par une machine d'accès unique (un bastion) ou par l'accès à distance géré du fournisseur.
  2. Des zones : une région (Paris, Francfort…) contient plusieurs zones de disponibilité, des centres de données séparés, avec leur propre alimentation électrique. Répartir les machines sur deux zones protège d'un incendie ou d'une coupure de courant.
  3. Une base principale et une copie : la base de secours reçoit chaque écriture et prend le relais en cas de panne, en général en une ou deux minutes.
  4. Un CDN (Content Delivery Network, fiche 9) sert les images et les fichiers CSS et JavaScript depuis des serveurs proches des visiteurs.
  5. Des workers traitent les messages Messenger en arrière-plan (fiches 16 et 17), sur des machines à part : un gros traitement ne ralentit plus les pages.
Sécurité : les erreurs qui coûtent le plus cher dans le cloud
  1. Un stockage objet public par erreur. Des fuites massives de données viennent d'un simple réglage de lecture publique. Garde tout privé par défaut, et sers les fichiers par des URL signées, qui expirent.
  2. Des droits trop larges. Chaque composant reçoit uniquement ce dont il a besoin, comme cette politique d'accès qui ne permet que de lire et d'écrire les fichiers envoyés :
exemples/19/iam-policy.json · illustration, non exécuté
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "UploadsSeulement",
      "Effect": "Allow",
      "Action": ["s3:GetObject", "s3:PutObject"],
      "Resource": "arn:aws:s3:::boutique-uploads/*"
    }
  ]
}
  1. Le compte principal utilisé au quotidien. Protège-le par une double authentification, range-le, et travaille avec des comptes nominatifs aux droits limités.
  2. Un port d'administration ouvert à tout Internet (SSH, base de données). Les règles de pare-feu du fournisseur (les groupes de sécurité) n'ouvrent que ce qui est nécessaire, et seulement à qui en a besoin (fiche 11).

5.La haute disponibilité et son prix

On exprime la disponibilité en pourcentage du temps où le service fonctionne, souvent en « nombre de 9 ». Traduite en temps d'arrêt cumulé sur un an, elle devient beaucoup plus concrète :

DisponibilitéArrêt possible par anOrdre de grandeur
99 %3,7 joursUn serveur unique, sans précaution particulière
99,9 %8 h 46 minUn objectif courant pour une application métier
99,95 %4 h 23 minCe que promettent souvent les services gérés
99,99 %53 minDes machines en double partout, sur plusieurs zones

Une application est une chaîne d'éléments, et deux règles permettent d'estimer sa disponibilité :

  1. En série, les disponibilités se multiplient. Une requête traverse le répartiteur, un serveur et la base : il suffit qu'un seul tombe. L'ensemble est donc moins disponible que son élément le plus faible.
  2. En parallèle, elles se protègent. Deux serveurs, dont un seul suffit, ne tombent ensemble que si les deux tombent : on calcule 1 − (1 − a)², où a est la disponibilité d'un serveur.

Prenons un répartiteur à 99,99 %, des serveurs à 99,9 % et une base à 99,95 % :

ArchitectureCalculDisponibilitéArrêt par an
Un serveur, une base0,9999 × 0,999 × 0,999599,84 %14 h
Deux serveurs, une base0,9999 × (1 − 0,001²) × 0,999599,94 %5 h 16 min
Deux serveurs, deux bases0,9999 × (1 − 0,001²) × (1 − 0,0005²)99,99 %53 min

Trois enseignements :

  1. Doubler les serveurs ne suffit pas : tant que la base reste unique, c'est elle qui limite tout.
  2. Ces chiffres sont des estimations : ils supposent des pannes indépendantes. Une erreur de configuration déployée partout, ou une région entière en panne, fait tomber tous les exemplaires à la fois.
  3. Chaque 9 supplémentaire coûte cher : des machines en double, une base de secours, plusieurs zones, et des personnes capables de réagir la nuit.

Deux chiffres complètent la disponibilité, et se décident avec le métier, pas seulement par l'équipe technique :

  1. Le RTO (Recovery Time Objective) : combien de temps le service peut rester arrêté après une panne grave.
  2. Le RPO (Recovery Point Objective) : combien de données récentes on accepte de perdre. Une sauvegarde par nuit, c'est un RPO de 24 heures. La sauvegarde et sa restauration sont détaillées en fiche 13.
Combien de 9 te faut-il ?

Pose la question au métier sous la forme d'un coût : « si la boutique est fermée deux heures un mardi après-midi, combien perd-on ? ». Pour la plupart des applications, 99,9 % suffisent largement. Viser 99,99 % sans que la perte le justifie, c'est payer très cher pour quelques heures par an.

6.IaaS, PaaS, conteneurs, serverless : qui gère quoi

Le mot « cloud » recouvre plusieurs façons de louer des ressources. Elles diffèrent surtout par ce que tu gères, et ce que gère le fournisseur :

Qui gère quoi, selon le modèle d'hébergement Un tableau de six couches, du matériel à l'application, pour cinq modèles. Ton propre serveur : tu gères tout. IaaS : le fournisseur gère le matériel, le réseau est partagé, tu gères le système et au-dessus. PaaS : le fournisseur gère jusqu'au runtime PHP, la mise à l'échelle est partagée. Conteneurs gérés : tu fournis le runtime dans ton image, le fournisseur gère le système. Serverless : le fournisseur gère presque tout, le runtime est partagé. L'application et les données restent toujours à toi. Ton serveur VPS dédié IaaS EC2 Scaleway PaaS Clever Cloud Upsun Conteneurs Cloud Run Fargate Serverless Lambda + Bref Application, données toi toi toi toi toi Mise à l'échelle toi toi partagé partagé fournisseur Runtime PHP toi toi fournisseur toi partagé Système toi toi fournisseur fournisseur fournisseur Réseau toi partagé fournisseur partagé fournisseur Matériel toi fournisseur fournisseur fournisseur fournisseur De gauche à droite : moins de travail d'exploitation, mais moins de contrôle et plus de dépendance au fournisseur. L'application et les données restent toujours sous ta responsabilité.
Schéma 19.4 · Qui gère quoi, selon le modèle d'hébergement
  1. L'IaaS (Infrastructure as a Service) loue des machines virtuelles, des disques et des réseaux, à la demande : AWS EC2, Scaleway Instances, OVHcloud Public Cloud. Tu gères le système comme sur ton propre serveur, mais tu crées une machine en une minute.
  2. Le PaaS (Platform as a Service) prend ton code et le fait tourner : tu choisis la version de PHP, la plateforme s'occupe du reste. Clever Cloud ou Upsun, la plateforme de l'éditeur de Platform.sh, en sont des exemples.
  3. Les conteneurs gérés (CaaS) font tourner ton image Docker sans que tu administres de serveur : Google Cloud Run, AWS ECS avec Fargate, ou un Kubernetes géré par le fournisseur.
  4. Le serverless, ou FaaS (Function as a Service), exécute ton code à chaque événement, et seulement à ce moment-là : AWS Lambda, Google Cloud Functions, Scaleway Serverless Functions.

Une règle ne change jamais, quel que soit le modèle : tes données, ton code et les droits d'accès restent sous ta responsabilité. Les fournisseurs l'appellent le modèle de responsabilité partagée. Un fournisseur ne te protège pas d'un bucket laissé public ou d'un mot de passe faible.

7.Le serverless

Le nom trompe : il y a bien des serveurs, mais tu ne les vois jamais. Ton code est lancé à chaque requête ou à chaque événement (un fichier déposé, un message dans une file), facturé à la durée d'exécution, et rien n'est facturé quand rien ne se passe. Pour PHP, l'outil de référence est Bref, qui fait tourner une application Symfony sur AWS Lambda :

exemples/19/serverless.yml · illustration, non exécuté
# serverless.yml : une application Symfony sur AWS Lambda avec Bref.
# Les noms de runtime dépendent de ta version de Bref : vérifie-les dans sa documentation.
service: boutique

provider:
  name: aws
  region: eu-west-3                 # Paris
  environment:
    APP_ENV: prod

plugins:
  - ./vendor/bref/bref

functions:
  web:                              # chaque requête HTTP lance l'application
    handler: public/index.php
    runtime: php-84-fpm
    timeout: 28                     # secondes, la limite de l'API Gateway est proche
    events:
      - httpApi: '*'
  worker:                           # les messages Messenger, depuis une file SQS
    handler: bin/consumer.php
    runtime: php-84
    timeout: 120
  1. Il grandit tout seul : cent requêtes simultanées lancent cent exécutions, sans rien configurer.
  2. Le démarrage à froid (cold start) : après une période sans trafic, la première requête attend que l'environnement démarre, de quelques centaines de millisecondes à plus d'une seconde.
  3. Des limites strictes : 15 minutes au plus par exécution sur Lambda, environ 30 secondes derrière l'API HTTP, et aucun disque persistant. Tout doit être sans état (section 3).
  4. La base de données souffre : mille exécutions simultanées, ce sont mille connexions à PostgreSQL. Il faut un intermédiaire qui les regroupe, comme RDS Proxy chez AWS.
Quand l'utiliser, quand s'en passer

Utile pour un trafic faible ou très irrégulier (un site d'événement, un back-office peu utilisé), des traitements déclenchés par des événements (redimensionner une image déposée), et les petites équipes qui ne veulent administrer aucun serveur.

À éviter pour un trafic élevé et régulier (plus cher, voir section 8), les traitements longs, les connexions permanentes comme les WebSockets, et les pages où chaque milliseconde compte. Et il lie fortement l'application à un fournisseur.

8.Le coût et la dépendance au fournisseur

Le cloud se paie à l'usage. C'est sa force, et son piège : la facture dépend de choix techniques que l'on fait sans y penser. Comparons un serveur à prix fixe et du serverless facturé à la requête, avec des tarifs inventés, mais de l'ordre de grandeur de ceux des grands fournisseurs :

  1. Le serveur coûte 40 € par mois, et encaisse jusqu'à 20 millions de requêtes. Au-delà, il en faut un second.
  2. Le serverless facture 0,20 € par million d'appels, plus le temps de calcul : une requête de 200 millisecondes avec 1 Go de mémoire. Au total, environ 3,53 € par million de requêtes.
Requêtes par moisServeurServerless
100 00040 €0,35 €
1 million40 €3,53 €
10 millions40 €35,33 €
15 millions40 €53 €
30 millions80 €106 €
  1. Le coût caché le plus fréquent est le trafic sortant : les données qui quittent le cloud (vers les visiteurs, vers un autre fournisseur) sont souvent facturées au Go, alors que l'entrée est gratuite.
  2. Les services gérés coûtent plus cher que leur équivalent installé à la main, une base gérée par exemple. Tu paies le travail qu'ils t'évitent : sauvegardes, mises à jour, bascule en cas de panne. C'est souvent rentable, mais il faut le savoir.
  3. Une ressource oubliée se paie tous les mois : un environnement de test jamais éteint, un disque d'une machine supprimée. Configure des alertes de budget dès le premier jour.
  4. Le temps humain compte aussi : un serveur moins cher qui demande deux jours de maintenance par mois n'est pas moins cher.
Serveur ou serverless : où se croisent les coûts Un graphique du coût mensuel selon le nombre de requêtes, de 0 à 30 millions. Le serveur coûte 40 € jusqu'à 20 millions de requêtes, puis 80 € avec une seconde machine. Le serverless part de zéro et monte de 3,53 € par million. Les deux courbes se croisent vers 11,3 millions de requêtes par mois. 0 M 5 M 10 M 15 M 20 M 25 M 30 M 0 € 40 € 80 € serveur : 40 € par machine serverless : 3,53 € le million égalité : 11,3 M requêtes par mois Tarifs inventés pour l'exemple (section 8). Le serverless gagne pour un trafic faible ou irrégulier, le serveur pour un trafic élevé et régulier. Le temps passé à gérer le serveur n'est pas compté ici.
Schéma 19.5 · Serveur ou serverless : où se croisent les coûts

Reste la dépendance au fournisseur (vendor lock-in) : plus tu utilises de services propres à un fournisseur, plus le quitter coûte cher. Tout n'est pas égal :

  1. Facile à déplacer : une image Docker, une base PostgreSQL, un stockage compatible S3 (la plupart des fournisseurs reprennent cette interface).
  2. Difficile à déplacer : une base propriétaire comme DynamoDB, des fonctions Lambda branchées sur dix services d'AWS, un système de files propre à un fournisseur.
  3. La souveraineté : un fournisseur américain reste soumis au droit américain, comme le Cloud Act, même pour des données stockées en France. Pour des données sensibles (santé, administration), la qualification SecNumCloud de l'ANSSI désigne des offres protégées de ces lois.
Accepter la dépendance, en connaissance de cause

Refuser tout service propriétaire mène à tout réinstaller soi-même, et donc à se priver de ce qui fait l'intérêt du cloud. La bonne question : « si on devait partir dans deux ans, quelles parties faudrait-il réécrire, et combien de temps ? ». Si la réponse est acceptable, la dépendance l'est aussi.

Pièges fréquents

PiègeCe qui arriveLa parade
Commencer par l'architecture la plus complexeUne facture et une charge de travail sans rapport avec le traficUn serveur bien tenu, puis grandir quand le besoin est mesuré
Ajouter un second serveur sans rendre l'application sans étatDéconnexions, fichiers introuvables, tâches en doubleSessions, fichiers, cache et verrous dans des services partagés
Doubler les serveurs, garder une seule baseLa base reste le point unique de panneCalculer la disponibilité de toute la chaîne
Une base ou un SSH joignable depuis InternetDes tentatives d'intrusion en continuRéseau privé, groupes de sécurité, bastion
Un stockage objet en lecture publiqueUne fuite de toutes les données envoyées par les clientsPrivé par défaut, URL signées
Des droits « administrateur » pour l'applicationUne faille dans l'application donne tout le compte cloudUne politique d'accès minimale par composant
Aucune alerte de budgetUne facture multipliée par dix découverte en fin de moisDes alertes dès le premier jour
Du serverless pour un trafic élevé et constantPlus cher qu'un serveur, et des connexions à la base saturéesComparer les coûts avec les chiffres réels
Viser 99,99 % sans demander au métierUne infrastructure très chère pour un gain que personne n'a demandéFixer disponibilité, RTO et RPO avec le métier

Checklist avant de choisir une infrastructure

Exercice : choisir une infrastructure

Trois projets, trois besoins. Pour chacun, tu vas proposer une infrastructure et la justifier par des chiffres, avec une feuille, un crayon et les règles des sections 5 et 8.

  1. Une association : 2 000 visites par jour, un formulaire d'inscription, un bénévole pour la technique. Une coupure d'une heure n'est pas grave.
  2. Une boutique en ligne : 50 000 visites par jour, dix fois plus pendant les soldes. Une heure d'arrêt un jour de soldes coûte environ 20 000 €.
  3. Un traitement nocturne : chaque nuit, redimensionner les photos déposées dans la journée, entre 0 et 30 000 selon les jours. Rien ne se passe le reste du temps.

Pour chaque projet :

  1. Choisis un modèle d'hébergement (section 6), et dis ce que tu ne veux pas gérer toi-même.
  2. Dessine l'architecture sur papier, comme le schéma 19.3, avec seulement les blocs nécessaires.
  3. Calcule sa disponibilité avec les deux règles de la section 5 (multiplier en série, 1 − (1 − a)² en parallèle), et compare-la au besoin.
  4. Estime son coût mensuel avec les hypothèses de la section 8, et dis où ton projet se situe sur le schéma 19.5.
  5. Liste ce que l'application doit changer pour devenir sans état, s'il le faut.
  6. Question de recul : pour la boutique, à partir de quelle durée d'arrêt par an une base de secours devient-elle rentable ?

Conseils

  1. Dessine avant de louer. Une architecture sur une feuille, avec une flèche par échange, révèle les points uniques de panne et les ports ouverts avant qu'ils coûtent quoi que ce soit.
  2. Grandis d'abord verticalement, tant que c'est possible et raisonnable : c'est souvent le moyen le plus simple de gagner du temps. Prépare quand même l'application à être sans état, ça ne coûte presque rien.
  3. Utilise les calculateurs de prix des fournisseurs, avec tes vrais chiffres, et relis la facture du premier mois ligne par ligne.
  4. Lis le cadre « Well-Architected » d'AWS, ou son équivalent chez d'autres fournisseurs : même si tu n'utilises pas AWS, ses questions sur la fiabilité, la sécurité et le coût valent pour toute infrastructure.

Documentation officielle