Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

NAT Gateway のトラフィック急増をコスト効率よく捕捉するサーバーレス構成

By Tomer RadianFeb 25, 202510 min read

このページはEnglishDeutschEspañolFrançaisItalianoPortuguêsでもご覧いただけます。

NAT Gateway で突発的に発生するトラフィック急増の課題

AWS の Network Address Translation(NAT)Gateway で突発的なトラフィック急増に対応するのは簡単ではありません。VPC Flow Logs はネットワークトラフィックを把握するうえで有用ですが、常時記録し続けると不要なストレージコストがかさみ、平常時にはほとんど役に立たない大量のデータに埋もれてしまいます。

もし、トラフィックの急増を検知したときだけ VPC Flow Logs を有効化できたらどうでしょうか。

本記事では、あらかじめ設定した閾値をトラフィックが超えたときに、一時的な VPC Flow Logs レコーダーを動的に作成する仕組みを紹介します。データ保管量を最小限に抑えてコストを節約しつつ、想定外のトラフィックを調査・把握するために必要な情報を確実に取得できます。

NAT Gateway を通るトラフィックに注意すべき理由

NAT Gateway の利用には料金がかかります。稼働しているだけでも課金され、北バージニアリージョンでは 1 時間あたり $0.045 です。さらに、通過するトラフィック量に対しても 1GB(送受信)あたり $0.045 が課金されます。これは S3 のようなリージョンリソース宛も含め、NAT Gateway を通過するすべてのトラフィックが対象です。

これは思いのほか早く積み上がります。データ 1TB あたりの料金は次のとおりです。

1,024GB × $0.045 = $46.08

10TB なら $460。

といった具合です。

本記事を執筆するきっかけは、あるお客様からのご相談でした。NAT Gateway 経由のトラフィックが突発的に 35TB まで急増し、1 回の急増ごとに想定外の追加コストが $1,600 発生していたのです。原因がまったく分からず、かといって 1 か月間ずっと VPC Flow Logs を有効化したくはない(理由は後述の VPC Flow Logs のコストに関するセクションを参照)、というご相談でした。

VPC Flow Logs の仕組み

分かりやすく解説されている AWS の公式ドキュメントから引用します。

VPC Flow Logs は、VPC 内のネットワークインターフェイスを出入りする IP トラフィックの情報をキャプチャできる機能です。フローログのデータは、Amazon CloudWatch Logs、Amazon S3、Amazon Data Firehose のいずれかに発行できます。フローログを作成すると、設定したロググループ、バケット、配信ストリーム上でフローログレコードを取得・参照できます。

フローログは、たとえば次のような場面で役立ちます。

\* 過度に制限されたセキュリティグループルールの診断

\* インスタンスへ到達するトラフィックの監視

\* ネットワークインターフェイスを出入りするトラフィックの方向の判定

フローログのデータはネットワークトラフィックの経路外で収集されるため、ネットワークのスループットやレイテンシーには影響しません。ネットワーク性能への影響を気にせず、フローログを作成・削除できます。

本記事および付属のリポジトリでは、トラフィックを記録して Amazon CloudWatch Logs 内の指定ロググループに取り込み、すべてのトラフィックログを保持して分析できるようにする方式を扱います。

NAT Gateway に対して VPC Flow Logs をデフォルト設定で有効にすると、ログは次の形式で記録され、対応する CloudWatch ロググループで確認できます。

CloudWatch Logs に出力された典型的な Flow Logs レコード

VPC Flow Logs を常時記録するコスト

本記事では記録データを CloudWatch ロググループに保存する前提のため、ログに取り込まれるデータに伴うコストを把握しておくことが重要です。CloudWatch Logs の料金はこちらを参照してください。

たとえば、10 個の NAT Gateway を運用しており、各サービスからインターネットへ毎秒 1,000 件のリクエストを送信し、1 リクエストにつき応答が 1 件だけ返ってくるとしましょう。このトラフィックを VPC Flow Logs で記録すると、毎秒 2,000 レコード(送信 1,000 件+応答 1,000 件)が CloudWatch Logs に取り込まれます。

1 レコードのサイズを 100 バイトと仮定します(詳細度によってこれより小さくも大きくもなり得ます)。1 か月で CloudWatch Logs に取り込まれるレコードの総サイズは次のとおりです。

10(NAT Gateway 数)× 2,000(レコード/秒)× 100(バイト/レコード)× 86,400(秒/日)× 30.5(月平均日数)= 5,270,400,000,000 バイト

つまり 1 か月で約 5.2TB が取り込まれることになります。

10TB までは取り込み 1GB あたり $0.5 のレートで計算されるため、このデータを 1 か月取り込むコストは次のようになります。

5,200GB × $0.5(/GB)= 月額 $2,600(Infrequent Access ログクラスに設定された CloudWatch ロググループに取り込めば、その半額の $1,300 に抑えられます)

ここで、捕捉したいトラフィック急増は月に 1〜2 回しか発生せず、継続時間は 15 分程度に過ぎないものの、その間に大量のデータが NAT Gateway を通過する、というケースを考えてみます。

ここで注意したいのは、通過するデータ量が多いからといって VPC Flow Logs に作成されるレコード数が必ずしも増えるわけではない、という点です。

たとえば、NAT Gateway を通して 10MB のファイルを 1 つ送る場合と、1KB のファイルを 1 つ送る場合を比べてみてください。NAT Gateway を通過するファイルにつき、作成されるレコードはどちらの場合も 1 件のみです。10MB のファイルは 1KB のファイルより大きくても、生成される VPC Flow Log レコードは 1 件で、これは 1KB のファイルでも同様です。

一方、NAT Gateway のトラフィック料金は通過量が桁違いに増えるため、10⁰⁴ 倍もの規模に跳ね上がります。

こうした急増を、月単位で VPC Flow Logs を記録し続ける費用を払うことなく捕捉したい、というのが今回の狙いです。

VPC Flow Logs を一時的にトリガーする

このソリューションでは、NAT Gateway のトラフィックが特定の閾値を超えたときに VPC Flow Logs を記録します。たとえば NAT Gateway の通常のトラフィックが毎分 10MB であれば、毎分 100MB を一定時間超えた場合にアラームを発報するよう設定できます。

VPC Flow Logs は急増を検知してから作成されるため、ごく短時間で終わる急増には不向きです。急増自体はそれほど長くなくてもかまいませんが、記録が確実に開始されるためには 3 分以上継続する必要があります。

ソリューションのアーキテクチャ

本ソリューションは、インストール時に指定した NAT Gateway ごとに CloudWatch Alarm を作成します。

これらのアラームは EventBridge ルールで検知され、Step Function が起動されます。

Step Function は、アラーム状態となった NAT Gateway の VPC Flow Logs 記録を開始する役割を担います。その後、記録済みのデータは残したまま VPC Flow Logs の記録プロセスを削除します。記録終了時には、SNS がインストール時に指定したアドレスへメールを送信します。

本ソリューションは AWS SAM で実装されており、2 つの CloudFormation スタックで構成されます。1 つ目のスタックでは、デプロイをスムーズにするための CloudFormation マクロをデプロイします。マクロには次のものが含まれます。

  • 指定した NAT Gateway ごとに CloudWatch アラームを自動生成し、設定作業を簡素化するマクロ。
  • 文字列パラメータを整数に変換できないという CloudFormation の制約を回避するためのマクロ。

2 つ目のスタックでは、ソリューションの中核となる以下のコンポーネントを作成します。

  • DynamoDB テーブル: NAT Gateway ごとの記録回数と、アラームが「OK」状態に戻った際に使用するコールバックトークンを保持します。

(コールバックトークンは Step Function のタスク内で生成されます。タスクが実行されると、次のステップへ進む前に通知を待機します。アラームが「OK」状態に戻ったときに起動される Lambda 関数がそのトークンを読み取り、Step Function に「待機をやめて処理を再開せよ」と伝えるために使用します)。

これにより記録プロセスを管理し、アラーム解消後の処理再開もスムーズに行えます。

  • CloudWatch Alarms: 指定した NAT Gateway を監視し、定義した閾値を超えるトラフィックを検知します。
  • EventBridge ルール: ワークフローを制御するために 2 つの EventBridge ルールを設定します。1 つは CloudWatch アラームが発報されたときに Step Function を起動するルール、もう 1 つはアラームが「OK」に戻ったときに Lambda 関数を起動するルールです。このイベント駆動型のアプローチにより、トラフィックの変動へ即応できます。
  • Step Function: Step Function は VPC Flow Logs の作成・管理・削除を一貫して制御します。手順は次のとおりです。

— 設定した記録回数の上限に達していないことを確認し、不要な記録を防止します。

— NAT Gateway に紐づく各 ENI について VPC Flow Logs を作成し、詳細なトラフィック情報を取得します。

— アラームが「OK」に戻るか、設定された時間制限に達するまでワークフローを一時停止する待機ステートにより、十分な期間の記録を担保します。

— 記録済みのログは CloudFormation スタックのデプロイ時に指定した期間保持しつつ、VPC Flow Logs の構成を削除します。

— 指定した宛先に SNS でメール通知を送り、記録状況をタイムリーに共有します。

  • Lambda 関数:

関数は 2 つあります。1 つは Step Function から呼び出され、アラーム状態にある NAT Gateway の ENI を取得して、それらに対する VPC Flow Logs を作成します。もう 1 つは CloudWatch アラームが「OK」に戻った際に EventBridge ルールから起動され、DynamoDB から Step Function のコールバックトークンを取得して Step Function を呼び出し、処理を再開させます。

Step Function の構造は以下のとおりです。

効率的なログ保存と分析

本ソリューションでは、VPC Flow Logs の保存先として CloudWatch ロググループの Infrequent Access ストレージクラスを利用します。コスト効率に優れたストレージクラスでありながら、CloudWatch Logs Insights による効率的なクエリと分析にも対応します。

VPC Flow Logs データの分析

VPC Flow Logs の記録セッションが終了すると、作成された VPC Flow Logs グループへのディープリンクと、記録されたログストリームのプレフィックスを記載したメールが届きます。

本ソリューションは CloudWatch Logs Insights 用のクエリテンプレートをあらかじめ用意しており、収集データから意味のある示唆を引き出せます。CloudWatch Logs Insights を開き、「Saved Queries」セクションで「Serverless Auto VPC Flow Log Recorder」というクエリを選択して以下を Flow Log に対して実行すると、人が読みやすい形式で結果を出力できます。

fields @timestamp, @message
| parse @message "* * * * * * * * * * * * * *" as action, flowDirection, trafficPathNum, srcAddr, srcPort, dstAddr, dstPort, proto, bytes, type, pkt_srcaddr, SrcService, pkt_dstaddr, DstService
| display @timestamp, action, flowDirection,
if(trafficPathNum == 1, "Through another resource in the same VPC",
if(trafficPathNum == 2, "Through an internet gateway or a gateway VPC endpoint",
if(trafficPathNum == 3, "Through a virtual private gateway",
if(trafficPathNum == 4, "Through an intra-region VPC peering connection",
if(trafficPathNum == 5, "Through an inter-region VPC peering connection",
if(trafficPathNum == 6, "Through a local gateway",
if(trafficPathNum == 7, "Through a gateway VPC endpoint (Nitro-based instances only)",
if(trafficPathNum == 8, "Through an internet gateway (Nitro-based instances only)",
"unknown")))))))) as trafficPath,
srcAddr, srcPort, dstAddr, dstPort,
if(proto == 6, "TCP",
if(proto == 17, "UDP",
proto)) as protocol,
bytes, type, pkt_srcaddr, SrcService, pkt_dstaddr, DstService
| sort @timestamp desc
| limit 1000

以下はこのクエリの出力例で、VPC に S3 Gateway Endpoint が設定されていなかった様子を示しています。その結果、S3 へのトラフィックは NAT Gateway とインターネットを経由していました。

インターネット経由のトラフィックを特定する

本ソリューションは、VPC エンドポイントではなくインターネット経由で流れているトラフィックを特定する用途にも有効です。AWS サービス宛のトラフィックがインターネット経由で送られている場合、CloudWatch Logs Insights の出力の SrcService または DstService フィールドにそのサービス名が表示されます(S3 サービス宛トラフィックを示す前述の例を参照)。この情報をもとに、特定のサービスに対して VPC エンドポイントを設定すべきかを判断し、セキュリティ強化とコスト削減につなげられます。

付属の GitHub リポジトリ

本ソリューションの内容確認とインストール手順は、こちらの GitHub リポジトリからご覧いただけます。

お問い合わせ

本記事が皆さまのお役に立てば幸いです。さらに詳しく知りたい方や当社のサービスにご関心のある方は、お気軽にご連絡ください。お問い合わせはこちらから。

関連リンク

2025 年 2 月のアップデート

付属の GitHub リポジトリに、JSONata という新しいブランチを追加しました。このブランチには、JSONata と変数を活用してよりコンパクトかつ明快に書き直された Step Function ASL が含まれています。ASL 自体は SAM の YAML テンプレートから切り出され、テンプレートから参照される独立した JSON ファイルになっています。

ご紹介したソリューションは、NAT Gateway を通過するトラフィックの量が一定の閾値を超えたときにのみメタデータを記録するため、不要なデータのロギングとコストを削減できます。サーバーレス構成を採用しているため、何も記録していない間は料金が発生せず、コストをさらに抑えられます。