La semaine dernière, j'ai reçu une alerte d'anomalie de coûts AWS. L'alerte pointait vers mon compte de formation (où je fais mes démos et aussi mes POCs), signalant une charge inattendue de 29 $ sous — étrangement — Amazon Elastic Block Store. Le type d'utilisation racontait cependant une tout autre histoire : NatGateway-Bytes. 659 Go de données avaient transité par ma NAT Gateway en six jours.
J'avais récemment déployé un agent vocal sur Bedrock AgentCore Runtime en mode VPC, utilisant une NAT Gateway pour l'accès internet sortant (nécessaire pour le relais TURN WebRTC) — voir mon billet de blog ici. Le VPC avait été créé spécifiquement pour cet agent, donc le suspect était évident. Mais je voulais des preuves concrètes avant de tirer des conclusions. Était-ce le trafic WebRTC ? Autre chose ?
Début de l'investigation
Mon premier réflexe a été de consulter les métriques CloudWatch de la NAT Gateway. La métrique BytesOutToDestination (trafic du conteneur vers internet) ne montrait que 2,1 Go au total sur les six jours. Négligeable. Mais BytesInFromDestination (trafic d'internet vers le conteneur à travers la NAT) racontait une tout autre histoire :
| Date | Entrant via la NAT |
|---|---|
| 26 mars | 6,3 Go |
| 27 mars | 240,3 Go |
| 28 mars | 149,1 Go |
| 29 mars | 149,8 Go |
| 30 mars | 102,3 Go |
| 31 mars | 15,0 Go |
| 1er avril | 5,4 Go (journée partielle) |
Ce déséquilibre entre les flux entrants et sortants plaidait contre WebRTC comme responsable du trafic.
De plus, la métrique ActiveConnectionCount montrait un nombre stable d'environ 90 connexions 24h/24, même quand personne n'utilisait l'agent. Le pattern horaire était remarquablement régulier — alternant entre ~850 Mo et ~430 Mo par heure, en continu.
Pour en avoir le cœur net, j'ai vérifié CloudTrail pour les événements InvokeAgentRuntime entre le 28 et le 30 mars. Zéro. Aucune activité utilisateur pendant la période avec le trafic le plus intense. L'agent était complètement inactif.
Activation des VPC Flow Logs
J'avais besoin de voir d'où venait le trafic. J'ai activé les VPC Flow Logs (j'aurais dû le faire dès le premier jour ? Bah, c'était un POC !) sur le VPC, en les envoyant vers un groupe de logs CloudWatch, et j'ai lancé une requête Logs Insights pour identifier les plus gros consommateurs :
stats sum(bytes) as totalBytes by srcAddr, dstAddr, dstPort
| sort totalBytes desc
| limit 20
Les résultats sur une fenêtre de deux heures montraient une poignée d'adresses IP responsables de tout le trafic lourd :
52.216.58.42 -> 10.0.0.144: 31175 270.1 MB
16.15.207.229 -> 10.0.0.144: 62935 263.7 MB
16.15.191.63 -> 10.0.0.144: 25320 263.6 MB
52.216.12.24 -> 10.0.0.144: 12542 115.8 MB
3.5.16.209 -> 10.0.0.144: 30762 113.4 MB
16.15.199.52 -> 10.0.0.144: 49632 113.3 MB
54.231.160.154 -> 10.0.0.144: 55754 29.6 MB
L'adresse 10.0.0.144 est l'IP privée de la NAT Gateway. Tout le trafic transitait depuis des IP externes, à travers la NAT, vers les ENI du conteneur AgentCore dans les sous-réseaux privés.
Identification de la source
J'avais besoin de savoir à quel service appartenaient ces IP. J'ai utilisé mon outil does-this-ip-belong-to-aws, qui vérifie les IP par rapport aux plages IP officielles AWS publiées sur https://ip-ranges.amazonaws.com/ip-ranges.json.
Chaque IP à fort trafic correspondait à Amazon S3 en us-east-1 !
Tout le trafic — jusqu'au dernier gigaoctet — était des téléchargements S3 transitant par la NAT Gateway.
Le correctif : S3 Gateway Endpoint
Le correctif est simple et gratuit. Un S3 Gateway VPC Endpoint route le trafic S3 directement via le réseau AWS, contournant entièrement la NAT Gateway. Contrairement aux interface endpoints, les gateway endpoints n'ont ni frais horaires ni frais de traitement de données.
resource "aws_vpc_endpoint" "s3" {
vpc_id = aws_vpc.main.id
service_name = "com.amazonaws.${var.aws_region}.s3"
route_table_ids = [
aws_route_table.private.id,
aws_route_table.public.id,
]
}
Un terraform apply et les coûts de transfert de données de la NAT Gateway tombent à quasi zéro.
Ce qui soulève une question plus large : pourquoi ne pas toujours avoir un S3 Gateway Endpoint dans un VPC ? C'est gratuit, ça se crée en une seule ressource, et ça prévient exactement ce genre de surprise. Si vous créez des VPC avec des sous-réseaux privés et des NAT Gateways, ajoutez un S3 Gateway Endpoint par défaut. Il n'y a aucun inconvénient. Les S3 Gateway endpoints sont bons pour votre portefeuille, sinon pour votre âme.
La cause racine : recyclage du warm pool
Après avoir ouvert un ticket de support, l'équipe du service Bedrock AgentCore a identifié la cause racine.
AgentCore Runtime maintient un warm pool de VM pour garantir des invocations à faible latence. Chaque VM du pool télécharge l'image du conteneur depuis ECR — et ECR stocke les couches d'images dans S3. Mon image de conteneur faisait environ 435 Mo compressée.
Trois facteurs se sont combinés pour produire la facture de 659 Go :
Premièrement, les 21 appels API UpdateAgentRuntime que j'ai effectués le 27 mars (une journée de débogage et redéploiement intensifs) ont chacun déclenché un cycle asynchrone de re-provisionnement du warm pool. Plusieurs séries de provisionnement de 10 VM, chacune téléchargeant l'image de 435 Mo, ont produit le pic de ~240 Go observé ce jour-là.
Deuxièmement, le warm pool a continué à recycler les VM les jours suivants pour les garder fraîches et prêtes. Avec 10 VM téléchargeant chacune l'image périodiquement, le trafic stable de ~150 Go/jour du 28 au 30 mars est cohérent avec un recyclage régulier.
Troisièmement, après environ 72 heures sans invocations, le warm pool a automatiquement réduit sa taille de 10 VM à 1 VM. Cela explique la chute de ~150 Go/jour à ~15 Go/jour le 31 mars.
Le recyclage du warm pool est un comportement attendu de la plateforme — c'est ce qui permet à AgentCore de servir les requêtes avec une faible latence. Le problème était que tous ces téléchargements S3 passaient par ma NAT Gateway à 0,045 $/Go au lieu de rester sur le réseau interne AWS.
Lancer autant de VM pour si peu d'invocations me semble un peu comme tirer au bazooka pour tuer une mouche ; je me demande si c'est soutenable... Cela dit, AWS a un bon historique de gestion d'activités rentables à grande échelle : qui suis-je pour juger ?
Quoi qu'il en soit, l'équipe du service a promis de mettre à jour la documentation pour que pas (trop) d'utilisateurs ne se retrouvent face à ces charges (franchement) indues.
Points à retenir
Si vous utilisez Bedrock AgentCore Runtime en mode VPC, trois choses à garder en tête :
Ajoutez un S3 Gateway Endpoint à votre VPC. C'est gratuit et ça élimine ce qui s'est avéré être la source dominante de coûts de transfert de données de la NAT Gateway — les téléchargements d'images ECR par le warm pool. AWS a confirmé qu'ils mettent à jour leur documentation VPC pour recommander cela plus visiblement. Il n'y a véritablement aucune raison de ne pas en avoir un dans chaque VPC avec des sous-réseaux privés.
Soyez attentif à la taille de votre image de conteneur. Mon image de 435 Mo, téléchargée par un warm pool de 10 VM avec recyclage régulier, a généré des centaines de gigaoctets de transfert. Réduire l'image (builds multi-étapes, moins de dépendances, base Alpine) réduit directement ce coût — même avec le endpoint S3 en place, des images plus petites signifient des démarrages à froid plus rapides.
Surveillez vos métriques NAT Gateway tôt. Les métriques
BytesInFromDestinationetBytesOutToSourcedans CloudWatch vous montreront si quelque chose d'inattendu se passe. Je ne m'en suis rendu compte que grâce à l'alerte d'anomalie de coûts — à ce moment-là, 29 $ avaient déjà été dépensés. Les VPC Flow Logs combinés avec CloudWatch Logs Insights ont rendu le diagnostic simple une fois que j'ai regardé.
Paul Santus est consultant cloud indépendant chez TerraCloud. Il accompagne les organisations dans la construction et le déploiement d'applications IA sur AWS. Retrouvez-le sur LinkedIn.

Top comments (0)