Retour aux publications

Article

Architecture CloudJunior Mbogning16 septembre 20267 min de lecture

Concevoir une architecture AWS 3-tiers prête pour la production

Les choix de réseau, de disponibilité et d'exploitation d'une application AWS 3-tiers déployée avec Terraform.

Concevoir une architecture AWS 3-tiers prête pour la production

Une application web peut démarrer sur une unique instance EC2. Ce choix est souvent raisonnable au lancement d'un produit : il réduit le coût, la complexité et le temps de mise en ligne. Il devient insuffisant dès que l'application doit rester disponible pendant un déploiement, un incident d'infrastructure ou une hausse de trafic.

Le passage à une architecture 3-tiers ne consiste pas à ajouter des services AWS au diagramme. Il consiste à séparer les responsabilités et à rendre chaque chemin réseau explicite : l'utilisateur atteint le point d'entrée, le point d'entrée joint l'application, et l'application seule accède à la base de données.

Point de départ d'une application web à trois composants
Une application web, une couche applicative et PostgreSQL.

Le scénario étudié est volontairement simple : une application HTTP, un backend sur EC2 et PostgreSQL sur RDS. L'infrastructure est décrite avec Terraform. EC2 n'est pas présenté comme le meilleur choix dans tous les contextes ; ici, il permet d'isoler les sujets qui comptent : routage, load balancing, health checks, Auto Scaling et failover. Une plateforme déjà conteneurisée pourra naturellement s'appuyer sur ECS ou EKS.

Le réseau fixe les limites de l'architecture

Je pars d'une VPC en 10.0.0.0/16, puis je réserve un subnet public, un subnet applicatif et un subnet de données dans chaque Availability Zone.

Plan d'adressage de la VPC AWS sur deux zones de disponibilité
La VPC sépare les couches publique, applicative et données sur deux zones.

Cette convention n'a rien de particulier. Elle est utile parce qu'elle reste lisible. Une adresse 10.0.12.x identifie immédiatement une ressource applicative de la seconde zone ; c'est précieux lorsqu'on analyse un Flow Log ou un incident plusieurs mois après le déploiement.

Le /16 laisse de la marge pour de nouveaux environnements, une connexion hybride ou un futur cluster Kubernetes. Ce point mérite d'être traité tôt : un mauvais plan CIDR se corrige beaucoup moins facilement qu'une AMI ou qu'un type d'instance.

resource "aws_vpc" "main" {
  cidr_block           = "10.0.0.0/16"
  enable_dns_support   = true
  enable_dns_hostnames = true

  tags = {
    Name        = "production-vpc"
    Environment = "production"
    ManagedBy   = "terraform"
  }
}

Un subnet /24 offre 251 adresses IPv4 utilisables après la réservation AWS. C'est largement suffisant pour ce cas. Ce calcul doit être revu avec EKS, ECS ou Lambda dans une VPC : ces services peuvent consommer des adresses par l'intermédiaire de nombreuses interfaces réseau.

Chaque subnet appartient à une seule Availability Zone. La haute disponibilité se prépare donc dans le réseau avant d'être confiée à l'Auto Scaling Group.

Le routage définit ce qui est public et ce qui ne l'est pas

Le nom d'un subnet ne lui donne aucun droit. C'est sa table de routage qui définit son comportement.

Public
10.0.0.0/16 -> local
0.0.0.0/0   -> Internet Gateway

Privé avec sortie Internet
10.0.0.0/16 -> local
0.0.0.0/0   -> NAT Gateway

Isolé
10.0.0.0/16 -> local

Les subnets publics hébergent l'Application Load Balancer et, dans le modèle zonal, les NAT Gateways. Les instances EC2 résident dans les subnets applicatifs. Elles peuvent sortir pour joindre un dépôt de paquets ou une API externe, sans être directement accessibles depuis Internet. Les subnets de base de données n'ont pas de route par défaut vers Internet.

resource "aws_route" "public_internet" {
  route_table_id         = aws_route_table.public.id
  destination_cidr_block = "0.0.0.0/0"
  gateway_id             = aws_internet_gateway.main.id
}

Le longest prefix match explique la circulation des paquets. Avec une route locale 10.0.0.0/16 et une route par défaut 0.0.0.0/0 vers une NAT Gateway, une requête à destination de 10.0.21.40 reste dans la VPC. Une requête vers 8.8.8.8 suit la route par défaut. Cette règle suffit à expliquer une grande partie des erreurs de routage observées en pratique.

Politique réseau et flux autorisés entre les couches
L'accès public s'arrête à l'ALB ; la base n'est accessible que depuis l'application.

Une entrée publique, des instances privées

L'Application Load Balancer est le seul composant applicatif exposé. Il reçoit le trafic HTTPS et le distribue vers les instances saines des deux zones.

Internet -> Application Load Balancer -> EC2 privée

Les instances n'ont pas d'IPv4 publique. Ce choix élimine une surface d'attaque inutile et impose un chemin d'entrée unique, observable et contrôlable. Les accès d'administration passent par Systems Manager plutôt que par un port SSH ouvert sur Internet.

Les instances ont néanmoins besoin de sorties. Une NAT Gateway zonale par Availability Zone conserve l'affinité entre le workload et sa sortie réseau. AWS propose également des NAT Gateways régionales, qui peuvent simplifier une architecture répartie sur plusieurs zones. Elles ne répondent toutefois pas aux besoins de connectivité privée ; il faut donc choisir le modèle en fonction des flux réels, pas d'une règle générale.

Topologie avec une NAT Gateway par zone de disponibilité
Chaque zone dispose de son chemin de sortie NAT dans le modèle zonal.

Pour les services AWS, une NAT Gateway n'est pas toujours nécessaire. Un Gateway VPC Endpoint vers S3 permet de conserver le trafic dans le réseau AWS et évite de facturer inutilement la sortie NAT.

Les Security Groups expriment l'intention de connectivité

La politique de sécurité peut se résumer ainsi :

Internet -> ALB:443
ALB      -> EC2:8080
EC2      -> RDS:5432

L'application accepte le port 8080 uniquement depuis le Security Group de l'ALB. RDS accepte 5432 uniquement depuis le Security Group applicatif. Les références de Security Groups sont plus robustes que des plages CIDR larges, car elles suivent directement les dépendances entre les composants.

Groupes de sécurité et règles de flux entre les composants
Les Security Groups traduisent les dépendances entre les trois couches.
resource "aws_security_group" "application" {
  name   = "production-app-sg"
  vpc_id = aws_vpc.main.id

  ingress {
    description     = "Application traffic from ALB"
    protocol        = "tcp"
    from_port       = 8080
    to_port         = 8080
    security_groups = [aws_security_group.alb.id]
  }
}

Les Security Groups sont stateful : les paquets de réponse sont autorisés sans règle de retour supplémentaire. Les tests doivent néanmoins vérifier les refus aussi bien que les autorisations : Internet vers EC2 et Internet vers RDS doivent échouer.

Une flotte remplaçable plutôt que des serveurs à réparer

L'ALB ne s'intéresse pas à l'état running d'une instance. Il vérifie la santé de l'application au moyen d'un endpoint, par exemple /health. Une machine peut être allumée alors que Nginx, le runtime ou l'application elle-même ne répondent plus.

L'Auto Scaling Group maintient une capacité minimale de deux instances. Lorsqu'une cible devient unhealthy, l'ALB cesse de lui envoyer des requêtes. Le groupe crée ensuite une nouvelle instance pour retrouver la capacité attendue. Cette mécanique suppose que l'instance soit remplaçable : ni fichiers utilisateurs, ni sessions critiques, ni configuration modifiée à la main ne doivent y rester.

Le test révélateur consiste à arrêter Nginx sans arrêter EC2. Si /health échoue, la cible doit sortir du trafic et être remplacée. Une capture de deux instances vertes ne démontre pas ce comportement ; une panne contrôlée, si.

RDS Multi-AZ protège la disponibilité, pas les lectures

RDS Multi-AZ maintient une standby synchrone dans une autre zone de disponibilité. Le mécanisme améliore la disponibilité et permet le failover, mais la standby ne traite pas les lectures applicatives. Pour du read scaling, il faut étudier les read replicas ou un Multi-AZ DB cluster selon le moteur et le workload.

La base reste dans ses subnets dédiés, sans exposition publique. Les secrets ne doivent pas être dispersés dans le code ou dans des variables Terraform manipulées trop largement. Lorsque le cas d'usage le permet, laisser RDS gérer le mot de passe maître dans Secrets Manager réduit le risque de l'exposer dans le state Terraform.

Multi-AZ ne remplace pas les sauvegardes. Une erreur de données est répliquée avec la même efficacité qu'une écriture valide. Les sauvegardes automatisées, le point-in-time recovery et des restaurations testées restent donc indispensables.

Terraform, revue et exploitation

Terraform rend l'infrastructure reproductible et soumet les changements à la revue de code. Il ne rend pas un changement sûr par nature. C'est pourquoi terraform plan est une étape importante : il permet d'identifier les destructions, les routes modifiées, les nouveaux accès réseau et les changements RDS susceptibles de provoquer un remplacement.

Organisation modulaire d'un projet Terraform
La structure Terraform sépare réseau, sécurité, calcul et données.

En production, le state doit être distant, chiffré et soumis à des contrôles d'accès stricts. Les déploiements doivent passer par une pipeline CI/CD qui utilise OIDC plutôt que des clés d'accès longue durée.

Valider le comportement attendu, y compris en échec

L'application doit répondre, mais les chemins interdits doivent également être absents :

Internet -> ALB:443  : autorisé
ALB -> EC2:8080      : autorisé
EC2 -> RDS:5432      : autorisé
Internet -> EC2:8080 : refusé
Internet -> RDS:5432 : refusé

Reachability Analyzer et les VPC Flow Logs servent à vérifier cette intention. Je teste ensuite le remplacement d'une instance, la montée en charge, le temps nécessaire pour qu'une nouvelle cible devienne saine et la récupération de l'application pendant un failover RDS.

La question utile n'est pas seulement « le système est-il hautement disponible ? ». C'est « lorsqu'un composant tombe, que voit l'utilisateur et pendant combien de temps ? ».

Conclusion

Une architecture AWS 3-tiers se juge moins à son diagramme qu'à son comportement sous contrainte. La segmentation réseau, les Security Groups, l'Auto Scaling et RDS Multi-AZ n'ont d'intérêt que s'ils produisent un service prévisible lorsqu'un composant échoue.

Le design présenté ici n'est pas une recette universelle. Une application interne peu critique n'a pas le même niveau d'exigence qu'une plateforme transactionnelle. Les compromis dépendent toujours du risque accepté et du coût réel d'une indisponibilité.

Discussion

Commentaires

Les lecteurs peuvent réagir, poser une question ou prolonger l'échange. Une connexion GitHub est demandée pour publier un commentaire.