Aller au contenu

NAT Gateway vs instance NAT — la falaise de coût sortant et quand les endpoints VPC retournent la question

NAT Gateway est infogéré et multi-Gbps. L'instance NAT est moins chère à petite échelle. Aucun n'est la réponse si les endpoints peuvent prendre le trafic. Voici le cadre de décision et les chiffres.

Une jeune pousse débrouillarde fait tourner une seule instance NAT t3.micro pour le VPC de développement et dépense presque rien sur le sortant. Le CTO lit un article sur NAT Gateway, bascule la production dessus pour l’histoire de haute disponibilité, et la facture du mois suivant arrive avec une ligne de traitement de données au GB qui est plus grosse que la flotte EC2. L’instinct est de revenir aux instances NAT. C’est la mauvaise réaction — la bonne est de regarder ce que le trafic est vraiment. La moitié des frais au GB sont pour des appels PUT/GET S3 qui devraient passer par un endpoint VPC de passerelle à coût de traitement nul. Le choix entre NAT Gateway et instance NAT est réel, mais le choix qui retourne la facture est de savoir si une portion du trafic devrait plutôt atteindre un endpoint.

Ce qui se passe

NAT Gateway est le service AWS infogéré. AWS l’exploite, le met à l’échelle (jusqu’à 45 Gbps par passerelle, ou 100 Gbps dans certaines régions) et vous donne un SLA de 99,95 % par AZ. Elle se déploie par AZ, a une Elastic IP publique et transmet le trafic IPv4 sortant des sous-réseaux privés vers Internet. Vous payez un tarif horaire par NAT Gateway (constant, peu importe le trafic) plus des frais au GB sur chaque octet qui passe. Les frais au GB sont ce qui tue les factures des charges sortantes lourdes. Pour une charge qui tire plusieurs dizaines de TB par mois à travers NAT — apt-get update à chaque boot, tirages d’images conteneur depuis des registres publics, trafic S3 qui ne passe pas par un endpoint de passerelle — la ligne au GB devient la ligne de coût dominante du VPC.

Instance NAT est une instance EC2 gérée par le client exécutant une pile NAT (l’AMI NAT AL2023, ou iptables masquerade sur une boîte Linux ordinaire). Vous payez le prix horaire de l’instance EC2 et le transfert de données sortant du VPC vers Internet — il n’y a pas de surfrais de traitement au GB. Une instance NAT t3.small sature autour de 5 Gbps dans de bonnes conditions. À faibles volumes de trafic l’instance NAT peut être 10× moins chère que NAT Gateway en dollars absolus. À hauts volumes, l’instance NAT sature avant que les économies au GB ne rattrapent.

Le point de défaillance unique sur une instance NAT est réel et bien connu. Une seule t3.small exécutant NAT est à un stop/start d’une coupure VPC de 5 minutes. La mitigation est un Auto Scaling Group de taille 1, derrière une instance NAT par AZ avec un basculement Route 53 ou un script qui retourne la table de routage sur échec de health check. La mitigation est du travail opérationnel — quelqu’un possède l’AMI, les correctifs, les mises à jour de noyau, le groupe de sécurité, le source/destination check désactivé. NAT Gateway n’a rien de ce travail, c’est pourquoi la plupart des équipes la choisissent dès que la facture n’est plus la principale préoccupation.

La troisième option, ce sont les endpoints VPC. Un endpoint de passerelle pour S3 ou DynamoDB est gratuit — aucun frais horaire, aucun frais au GB — et une modification de table de routage envoie le trafic pour ces services directement vers AWS sans jamais toucher le chemin NAT. Un endpoint d’interface pour les autres services AWS a un frais horaire par AZ et un frais au GB plus bas que celui de NAT Gateway. Pour les charges qui parlent beaucoup aux services AWS depuis des sous-réseaux privés, le bon mouvement est : endpoints d’abord, NAT pour ce qui reste.

Comment vérifier

La première mesure est « qu’est-ce qui passe vraiment par NAT ? ». Activez VPC Flow Logs sur le sous-réseau privé pour une période représentative (24 heures suffisent pour une charge à cycle quotidien) et regardez les destinations principales par compte d’octets.

# Dans CloudWatch Logs Insights, sur le log group des flow logs :
fields @timestamp, srcAddr, dstAddr, bytes
| filter action = "ACCEPT" and srcAddr like /^10\.20\./ and not dstAddr like /^10\./
| stats sum(bytes) as total_bytes by dstAddr
| sort total_bytes desc
| limit 50

Résolvez les IP de destination principales avec dig -x <ip> ou les données de plages IP d’AWS. Une charge SaaS typique de petite taille montrera :

  • Les IP de buckets S3 (plage s3.us-east-1.amazonaws.com) en tête, souvent 60 % du trafic. Celles-ci devraient être sur un endpoint de passerelle à coût nul.
  • Les IP du registre d’images ECR (plage api.ecr.us-east-1.amazonaws.com et pkg-containers.githubusercontent.com pour les tirages GHCR). ECR a un endpoint d’interface à tarif au GB plus bas ; GHCR peut être mis derrière un miroir de registre dans votre propre ECR.
  • Les IP DynamoDB à plus faible volume. Endpoint de passerelle, gratuit.
  • Les IP des gestionnaires de paquets (deb.debian.org, packagecloud.io, npm, PyPI). Ce sont du vrai sortant Internet — il passe par NAT quoi qu’il arrive. Mitigez avec un miroir de paquets privé si le volume est assez élevé.
  • Les IP d’API tierces (Stripe, SendGrid, Twilio). Vrai sortant Internet, aucun endpoint n’existe.

La deuxième mesure est le coût lui-même :

# Appel Cost Explorer pour le dernier mois complet, ciblé sur NAT
aws ce get-cost-and-usage \
  --time-period Start=2026-04-01,End=2026-05-01 \
  --granularity MONTHLY \
  --metrics UnblendedCost UsageQuantity \
  --filter '{"Dimensions":{"Key":"USAGE_TYPE_GROUP","Values":["EC2: NAT Gateway"]}}'

Comparez à l’équivalent en instance NAT pour la charge. Le point de bascule est approximativement :

  • En dessous de ~1 TB/mois par VPC : l’instance NAT gagne sur le coût, le risque de panne d’AZ unique est le prix.
  • 1–10 TB/mois : NAT Gateway est la valeur par défaut ; l’effort d’ingénierie pour maintenir un ASG d’instances NAT ne vaut pas les économies.
  • Au-dessus de 10 TB/mois : le tarif horaire de NAT Gateway est négligeable face au coût de traitement au GB. Le levier est sur le déploiement des endpoints, pas sur le type de NAT.

La correction

La procédure pour un VPC existant avec une grosse facture NAT :

  1. Activez les Flow Logs d’abord. Sans flow logs vous devinez. Avec eux vous avez l’histogramme octets-par-destination dont vous avez besoin pour décider.

  2. Ajoutez des endpoints de passerelle pour S3 et DynamoDB. Gratuit, instantané, et une modification de table de routage d’une ligne. Modifiez la table de routage privée pour ajouter une route pl-XXX → vpce-XXX (la prefix list est l’ID de la prefix list du service S3). La route est plus spécifique que 0.0.0.0/0 donc elle a la priorité. Vérifiez avec aws s3 cp depuis une instance de sous-réseau privé et regardez le flow log — l’IP source devrait maintenant être l’IP privée de l’instance routée à travers l’endpoint, pas l’IP publique de la NAT Gateway.

  3. Ajoutez des endpoints d’interface pour ECR et les autres services AWS à fort volume. Les endpoints d’interface ne sont pas gratuits — il y a un frais horaire par AZ plus un frais au GB — mais pour les charges qui tirent plusieurs GB d’images conteneur par jour, le calcul tient. Le motif est : déployer trois endpoints (un par AZ), activer la résolution DNS privée, et le SDK continue d’utiliser les mêmes noms d’hôtes *.amazonaws.com mais les résout vers les IP des endpoints.

  4. Décidez NAT Gateway vs instance NAT pour ce qui reste. Si le trafic NAT restant est en dessous de 1 TB par mois par VPC et que vous avez l’appétit opérationnel pour faire tourner un ASG d’instances NAT, l’instance NAT gagne sur le coût. La mise en place est :

    # Lancer une instance NAT depuis l'AMI NAT AL2023
    aws ec2 run-instances \
      --image-id $(aws ssm get-parameter --name /aws/service/ami-amazon-linux-latest/al2023-ami-kernel-default-x86_64 --query Parameter.Value --output text) \
      --instance-type t3.small \
      --subnet-id subnet-public-1a \
      --security-group-ids sg-nat-instance \
      --user-data file://nat-init.sh
    
    # Désactiver source/destination check sur l'ENI de l'instance NAT
    aws ec2 modify-instance-attribute \
      --instance-id i-xxx \
      --no-source-dest-check
    
    # Mettre à jour la table de routage privée pour pointer le défaut vers l'instance NAT
    aws ec2 replace-route \
      --route-table-id rtb-private-1a \
      --destination-cidr-block 0.0.0.0/0 \
      --instance-id i-xxx
  5. Pour la production, par défaut NAT Gateway. Les heures qu’un ingénieur passe à maintenir un ASG d’instances NAT valent plus que les économies. L’exception est les VPC de développement où le trafic est léger et le coût compte.

La seule erreur à ne pas faire : déployer NAT Gateway dans une seule AZ et router tous les sous-réseaux privés vers elle. C’est à une panne d’AZ d’une coupure VPC complète, et cela ajoute des frais de transfert inter-AZ sur chaque octet des autres AZ. Des NAT Gateways par AZ sont la valeur par défaut correcte — le coût horaire de deux NAT Gateways supplémentaires est petit face au transfert inter-AZ qu’elles évitent.

L’autre règle qu’on tient : le coût NAT est un symptôme, pas une cause. Un VPC qui tire 50 TB/mois à travers NAT a une charge qui fait trop de choses sur le chemin public. La correction est de regarder ce qui génère ce trafic — généralement des tirages d’images conteneur et des mises à jour de gestionnaires de paquets qui devraient être mis en cache dans un miroir privé — et de réduire le volume, pas de changer de type de NAT et de passer à autre chose.

Pour le déploiement des endpoints en détail, voir Endpoints VPC pour S3, DynamoDB et interface. Pour la conception de sous-réseaux qui place le NAT au bon endroit, voir Conception de sous-réseaux multi-AZ.


Stack Harbor conçoit et audite les topologies VPC en production dans le cadre de Gestion AWS et des Environnements infogérés en continu. Si votre facture sortante a échappé à votre plan VPC, commencez par une consultation d’infrastructure.