Infra de base — Réseau
Phases 1 à 3 du déploiement infrastructure : backend Terraform, VPC AWS, Security Groups. Pour la vue d'ensemble et la checklist globale, voir Infra de base — overview.
PHASE 1 — TERRAFORM STATE BACKEND
Objectif
Créer le stockage distant du state Terraform avant toute autre ressource. Sans ça, le state reste en local et ne peut pas être partagé ni verrouillé.
Instructions pour l'agent
Créer un dossier infrastructure/terraform/bootstrap/ séparé des environnements. Ce bootstrap est exécuté une seule fois, manuellement.
Ressources à créer :
- Un bucket S3
nex-terraform-state-<AWS_ACCOUNT_ID>(ex:nex-terraform-state-009001720821) : versioning activé, encryption AES-256, block public access total. Le suffixe avec l'account ID garantit l'unicité globale du nom. - Une table DynamoDB
nex-terraform-locks: clé primaireLockID(String). Utilisée pour le verrouillage concurrent — empêche deuxterraform applysimultanés.
Recommandations :
- Ce module ne doit PAS être géré par un backend distant (problème de l'œuf et de la poule). State local uniquement pour le bootstrap.
- Tagger les deux ressources avec les tags projet.
- Activer la suppression protection sur le bucket (prevent_destroy).
Configuration backend (dans infrastructure/terraform/staging/main.tf) :
terraform {
backend "s3" {
bucket = "nex-terraform-state-009001720821"
key = "staging/terraform.tfstate"
region = "eu-west-3"
dynamodb_table = "nex-terraform-locks"
encrypt = true
}
}Validation
aws s3 ls | grep nex-terraform
aws dynamodb describe-table --table-name nex-terraform-locks --query "Table.TableStatus"PHASE 2 — VPC & RÉSEAU
Objectif
Créer le réseau isolé dans lequel toute l'infrastructure vivra. C'est la fondation — une erreur ici impacte tout le reste.
Instructions pour l'agent
Créer le module infrastructure/terraform/modules/vpc/.
Architecture réseau :
VPC 10.0.0.0/16
│
├── Subnets publics (2 AZ)
│ ├── 10.0.1.0/24 (eu-west-3a) — ALB, NAT Gateway
│ └── 10.0.2.0/24 (eu-west-3b) — ALB, NAT Gateway
│
├── Subnets privés (2 AZ)
│ ├── 10.0.10.0/24 (eu-west-3a) — Pods EKS
│ └── 10.0.20.0/24 (eu-west-3b) — Pods EKS
│
└── Subnets données (2 AZ)
├── 10.0.100.0/24 (eu-west-3a) — RDS, Redis
└── 10.0.200.0/24 (eu-west-3b) — RDS, RedisComposants réseau :
- Internet Gateway attaché au VPC.
- NAT Gateway : 1 seul en staging (dans public-a pour économiser). 2 en production (un par AZ pour la haute dispo). Elastic IP associée.
- Route tables : une publique (0.0.0.0/0 → IGW), une privée (0.0.0.0/0 → NAT), une data (0.0.0.0/0 → NAT).
- DNS hostnames et DNS support activés sur le VPC.
Tags Kubernetes obligatoires sur les subnets — sans ça, EKS ne pourra pas créer les load balancers :
- Subnets publics :
kubernetes.io/role/elb = 1 - Subnets privés :
kubernetes.io/role/internal-elb = 1 - Tous :
kubernetes.io/cluster/nex-staging = shared
Recommandations :
- 3 couches de subnets (public/privé/data) au lieu de 2. La couche data isole physiquement les bases de données des pods applicatifs. Même si un pod est compromis et qu'il a accès au réseau privé, il ne peut pas scanner le réseau data sauf si le Security Group l'autorise explicitement.
- Le NAT Gateway coûte ~35 €/mois. En staging un seul suffit. Si la zone A tombe, les pods en zone B perdent leur accès internet sortant — acceptable en staging.
Validation
# VPC existe
aws ec2 describe-vpcs --filters "Name=tag:Project,Values=nex" --query "Vpcs[0].VpcId" --region eu-west-3
# 6 subnets
aws ec2 describe-subnets --filters "Name=tag:Project,Values=nex" --query "length(Subnets)" --region eu-west-3
# Attendu : 6
# NAT Gateway actif
aws ec2 describe-nat-gateways --filter "Name=tag:Project,Values=nex" --query "NatGateways[0].State" --region eu-west-3
# Attendu : availablePHASE 3 — SECURITY GROUPS
Objectif
Définir la matrice de communication réseau. Le principe : tout est fermé par défaut, on ouvre uniquement ce qui est nécessaire.
Instructions pour l'agent
Créer dans infrastructure/terraform/modules/vpc/security_groups.tf un Security Group par composant :
sg-alb — Load Balancer (point d'entrée) :
- Inbound : 443 depuis 0.0.0.0/0 (trafic HTTPS via Cloudflare)
- Inbound : 80 depuis 0.0.0.0/0 (redirect HTTPS)
- Outbound : tout vers les subnets privés
sg-eks-nodes — Nœuds Kubernetes :
- Inbound : tout depuis sg-alb (le LB route vers les pods)
- Inbound : tout depuis sg-eks-nodes (communication inter-pods)
- Inbound : 443 depuis le CIDR VPC (API server ↔ kubelets)
- Outbound : 5432 vers sg-rds
- Outbound : 6379 vers sg-redis
- Outbound : 443 vers 0.0.0.0/0 (pull images, appels API externes : Firebase, Resend)
sg-rds — PostgreSQL :
- Inbound : 5432 depuis sg-eks-nodes uniquement
- Outbound : aucun
sg-redis — Redis :
- Inbound : 6379 depuis sg-eks-nodes uniquement
- Outbound : aucun
ATTENTION — Piège EKS avec les Security Groups :
EKS crée automatiquement un Security Group cluster (différent de
sg-eks-nodesdéfini dans Terraform). Ce SG auto-généré est celui réellement attaché aux nœuds du node group managé. Par conséquent, les règles inbound desg-rdsetsg-redisdoivent autoriser à la foissg-eks-nodesET le SG cluster auto-généré par EKS.Après la création du cluster (Phase 7), récupérer le SG cluster :
bashaws eks describe-cluster --name nex-staging --region eu-west-3 \ --query "cluster.resourcesVpcConfig.clusterSecurityGroupId" --output textPuis ajouter ce SG en inbound sur
sg-rds(port 5432) etsg-redis(port 6379). Sans ça, les pods ne pourront pas joindre RDS ni Redis (ETIMEDOUT /no pg_hba.conf entry... no encryption).
Recommandations :
- Ne jamais ouvrir les SG RDS ou Redis à 0.0.0.0/0, même temporairement pour debug. Utiliser kubectl port-forward à la place.
- En production on pourra restreindre le 443 inbound de sg-alb aux seules IPs Cloudflare (plages publiées par Cloudflare). En staging on laisse ouvert pour simplifier.
- Chaque SG doit avoir une description claire et des tags.
Validation
aws ec2 describe-security-groups --filters "Name=tag:Project,Values=nex" \
--query "SecurityGroups[].GroupName" --region eu-west-3
# Attendu : sg-alb, sg-eks-nodes, sg-rds, sg-redis
# Vérifier que le SG cluster EKS est dans les inbound de sg-rds
aws ec2 describe-security-groups --group-ids <sg-rds-id> --region eu-west-3 \
--query "SecurityGroups[0].IpPermissions"
# Attendu : le SG cluster EKS apparaît en source sur port 5432