NAT Gateway のコストが気になるので CloudWatch ダッシュボードと仲良くなってみた

デフォルトで、環境に存在するリソースに関する CloudWatch ダッシュボードを自動で作成してくれるようになっています。便利ですね。今回は NAT Gateway のダッシュボードを覗いてみます。

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

どの NAT Gateway で料金がかかっているんだろう

コンバンハ、千葉(幸)です。

NAT Gateway の料金が気になる機会がありました。環境には多くの NAT Gateway が存在するため、まずはどの NAT Gateway でコストがかかっているのか確認したいと考えました。

デフォルトで用意されている CloudWatch ダッシュボードを覗いてみると多くのメトリクスが表示されます。

▲ メトリクスの種類が多いですね


パッと眺めてみたときに、似たようなメトリクス名が並んでいて混乱してしまいました。

  • BytesInFromDestination
  • BytesInFromSource
  • BytesOutToDestination
  • BytesOutToSource
  • PacketsInFromDestination
  • PacketsInFromSource
  • PacketsOutToDestination
  • PacketsOutToSource

30 分くらい眺めていたら意味が分かってきたので、理解した内容を記しておきます。

このエントリで書くこと

  • NAT Gateway のメトリクスの考え方
  • NAT Gateway ダッシュボードの見方
  • 特定の NAT Gateway を宛先にもつルートテーブルの確認の仕方

NAT Gateway についておさらい

メトリクスを確認する前に NAT Gateway の基本的な部分についておさらいしておきましょう。

NAT Gateway は VPC 内のクライアントに対して NAT デバイスとして機能します。より具体的に言うと NAPT を行ってくれます。IP アドレスだけでなくポートも変換してくれるため、1対多の変換に対応しています。

NAT Gateway

プライベートサブネット上のクライアントに対してインターネットへのアウトバウンド通信の経路を確保する用途で用いられることが多いため誤解されやすいですが、プライベート IP アドレスとグローバル IP アドレスの変換を行うのは NAT Gateway の役割ではありません

NAT Gateway はあくまで自身が持つプライベート IP アドレスと変換するだけで、「NAT Gateway のプライベート IP アドレスと NAT Gateway のグローバル IP アドレス」を変換するのはインターネットゲートウェイの役割です。

インターネット上ではなくオンプレミスを宛先とするケースを想定し、プライベートタイプの NAT Gateway を構成することも可能です。パブリックタイプであってもプライベートタイプであっても、通信方向は片方向のみです。(クライアントから宛先への方向の通信の開始のみ NAT Gateway は受け付ける。もちろん戻りの通信は正常に処理される。)

その他の仕様として以下が挙げられます。

  • サポートしているプロトコルは TCP、UDP、ICMP
  • IPv4 または IPv6 トラフィックをサポート
    • IPv6 トラフィックの場合 NAT64 を実行
  • 5Gbps の帯域幅をサポートし、自動的に 100 Gbps までスケールアップ
  • 100万パケット/秒をサポートし、自動的に 1,000万パケット/秒までスケールアップ
  • 一意の宛先ごとに 55,000 の同時接続をサポート
  • 使用するエフェメラルポートは 1024~65535

詳細は以下を参照してください。

NAT Gateway のデータ処理に関する課金

NAT Gateway は配置しているだけで1時間ごとに 0.062 USD の料金が発生します。(2022/12現在、東京リージョンの場合。以降も同様。)

さらに、データ処理量 1GB ごとに 0.062 USD の料金も発生します。ここでのデータ処理量は行きの通信・戻りの通信の双方を含みます。

このデータ処理量による料金が嵩んでいる場合、なるべく NAT Gateway を経由させない構成を取れないか検討するのがよいでしょう。いくつかのパターンが以下エントリで取り上げられています。

明確なアンチパターンは「S3 向けの通信を NAT Gateway を経由している」です。S3 向けの通信はゲートウェイ型の VPC エンドポイントを経由することで追加の料金なしで実現できます。

NAT Gateway S3 Endpoint

サブネットルートテーブルに追加のエントリが必要になる、というインパクトはありますが、料金の観点のほか「VPC エンドポイントポリシーによるアクセス先の制御」も可能となるため、採用することで大きなメリットが期待できます。

NAT Gateway のメトリクス一覧を確認する

NAT Gateway に関する CloudWatch メトリクスは以下ページにまとまっています。

勝手に番号を振ってまとめた表が以下です。

# メトリクス 単位 有用な統計 説明 対のメトリクス
1 ActiveConnectionCount カウント Max NAT ゲートウェイを介した同時アクティブ TCP 接続の総数 -
2 BytesInFromDestination バイト Sum NAT ゲートウェイが宛先から受信したバイト数 #5
3 BytesInFromSource バイト Sum VPC 内のクライアントから NAT ゲートウェイが受信したバイト数 #4
4 BytesOutToDestination バイト Sum NAT ゲートウェイ経由で宛先に送信されたバイト数 #3
5 BytesOutToSource バイト Sum NAT ゲートウェイ経由で VPC 内のクライアントに送信されたバイト数 #2
6 ConnectionAttemptCount カウント Sum NAT ゲートウェイ経由で試行された接続の回数 #7
7 ConnectionEstablishedCount カウント Sum NAT ゲートウェイ経由で確立された接続の数 #6
8 ErrorPortAllocation カウント Sum NAT ゲートウェイが送信元ポートを割り当てられなかった回数 -
9 IdleTimeoutCount カウント Sum アクティブ状態からアイドル状態に遷移した接続の数 -
10 PacketsDropCount カウント Sum NAT ゲートウェイによってドロップされたパケットの数 -
11 PacketsInFromDestination カウント Sum NAT ゲートウェイが宛先から受信したパケットの数 #14
12 PacketsInFromSource カウント Sum VPC 内のクライアントから NAT ゲートウェイが受信したパケットの数 #13
13 PacketsOutToDestination カウント Sum NAT ゲートウェイ経由で宛先に送信されたパケットの数 #12
14 PacketsOutToSource カウント Sum NAT ゲートウェイ経由で VPC 内のクライアントに送信されたパケットの数 #11

いくつかのメトリクスは他のメトリクスと比較することでより意味を持つようになります。それを「対のメトリクス」として表現しています。

InFrom と OutTo と Source と Destination

全 14 個のメトリクスのうち 8 個がこれに関するメトリクスです。#2~5,11~14 が該当します。

冒頭で「似たようなメトリクスが並んでいて混乱する」と挙げたのもこれらです。絵を描いたら簡単に理解できました。

NAT Gateway metric source destination

ここでは以下前提のもと図示していますが、他の構成でも考え方は同じです。

  • NAT Gateway がパブリックタイプ
  • 宛先がインターネット上のリソース
  • 送信元(クライアント)が EC2 インスタンス

行きの通信、戻りの通信ごとに対となる組み合わせがあります。

  • 行きの通信:InFromSource,OutToDestination
  • 戻りの通信:InFromDestination,OutToSource

これらは組み合わせごとに同じ値となるのが基本ですが、NAT Gateway の処理によってデータがロストする・ブロックされるといったことがある場合には差異が生じることになります。

Bytes と Packets

#2~5は Bytes 、#11~14は Packets のメトリクスとなっています。どちらのメトリクスでも傾向としては同じになるはずのため、好きなほうを選択してよいかと思います。

パッと「1パケットって何バイトくらいになるんだっけ?」というのが出てこなかったので調べ直しました。

調べ直したものの細かい部分の数字が自信がないのですが、おおよそ 50 ~ 1500バイトの中におさまるはずです。わたしの環境ではアウトバウンドでは 100 ~ 200 程度、インバウンドでは 1,000 程度がボリュームゾーンでした。

その他のメトリクス

#1. ActiveConnectionCount

アクティブな接続数に関するメトリクスです。TCP 接続に限定されることに注意してください。

#6. ConnectionAttemptCount と #7. ConnectionEstablishedCount

前者が試行の回数、後者が確立された回数です。後者の方が数が少ない場合、接続が成功していない試行があることを表します。

8. ErrorPortAllocation

0 より大きい場合、NAT Gateway が送信元ポートを割り当てられなかった接続があることを表します。先述の通り「一意の宛先ごとに同時接続数 55,000」がサポートされているため、このエラーが発生することは稀かと思います。

NAT ゲートウェイは送信先別に最大 55,000 の同時接続をサポートできます。この制限は、単一の送信先に 1 秒あたり約 900 の接続 (1 分あたり約 55,000 の接続) を作成する場合にも適用されます。送信先 IP アドレス、送信先ポート、またはプロトコル (TCP/UDP/ICMP) が変更された場合は、追加の 55,000 の接続を作成できます。55,000 を超える接続の場合は、ポートの割り当てエラーによる接続エラーの可能性が高くなります。これらのエラーは、NAT ゲートウェイの ErrorPortAllocation CloudWatch メトリクスを表示することでモニタリングできます。

9. IdleTimeoutCount

アクティブ状態からアイドル状態に遷移した接続の数を表します。以下を満たした場合アイドル状態に遷移するとのことです。

  • アクティブな接続が正常に閉じられなかった
  • 350 秒アクティビティがなかった

10. PacketsDropCount

NAT Gateway の一時的な問題によりパケットがドロップされた場合にこのメトリクスが記録されます。トータルのトラフィックに対してこの値が 0.01 % を超える場合、サービスヘルスダッシュボードを確認すること、とのことです。

(逆説的に考えると、その程度を閾値にサービスヘルスダッシュボードで障害として記録されるものと推察できます。)

NAT Gateway の CloudWatch ダッシュボードを覗いてみる

メトリクスの意味が理解できたところで、改めて NAT Gateway の CloudWatch ダッシュボードを覗いてみます。

特に設定をしていなくても、自動でダッシュボードを用意してくれています。CloudWatch コンソールから、「ダッシュボード」→「自動ダッシュボード」→「VPC NAT Gateways」に遷移します。

CloudWatch_Management_Console_NAT_Gateway_dashbord

改めて確認することで、以下の傾向が確認できました。

  • 特定の NAT Gateway で多くのデータ処理が発生している
  • アップロードよりダウンロードの比重が大きい

CloudWatch_Management_Console_NAT_Gateway-2148428

特定の NAT Gateway 向けのルートを持つルートテーブルを確認する

データ処理量が多い NAT Gateway が特定できたので、その NAT Gateway を使用しているクライアントにあたりをつけたいです。環境には多くの VPC 、サブネット、ルートテーブルが存在していたため、コンソールからの確認が難しく、以下の AWS CLI コマンドを用いました。

$ aws ec2 describe-route-tables\
 --filters "Name=route.nat-gateway-id,Values=nat-xxxxxxx"\
 | jq -c  '.RouteTables | sort_by(.Tags[] | select(.Key == "Name").Value) | .[] | [(.Tags[] | select(.Key == "Name").Value),.RouteTableId,.VpcId,.Associations[].SubnetId]'
["RouteTable1","rtb-xxxxxxxxxx","vpc-yyyyyyyyyy","subnet-zzzzzzzzzzz"]
["RouteTable2","rtb-xxxxxxxxxx","vpc-yyyyyyyyyy","subnet-zzzzzzzzzzz","subnet-aaaaaaaaaa"]
...

--filtersで NAT Gateway ID を指定してフィルタリング指定しています。これは以下エントリの内容を踏襲しています。

--filters "Name=route.nat-gateway-id,Values=nat-xxxxxxx","nat-yyyyyyy"のように NAT Gateway を複数指定すれば OR 条件でフィルタリングできます。

また、以下のように指定すれば、「特定の NAT Gatewey 宛のルートをもち、かつ S3 VPC エンドポイント宛のルートを持つ」という AND 条件のフィルタリングが可能です。

$ aws ec2 describe-route-tables\
 --filters "Name=route.nat-gateway-id,Values=nat-xxxxxxx,nat-yyyyyyy"\
           "Name=route.destination-prefix-list-id,Values=pl-61a54008"\
| jq '.RouteTables[].RouteTableId' | sort # 任意の処理

pl-61a54008は東京リージョンの S3 のプレフィックスリストを表します。)

"Name=route.destination-prefix-list-id,Values=pl-61a54008"を条件に加えた時とそうでない時とで結果に差異が出る場合、「NAT Gateway 向けのルートを持つが S3 用のゲートウェイエンドポイント向けのルートを持たない」ルートテーブルがあるということになるので、重点的に確認をするとよいでしょう。

ひとまずここまでで特定の NAT Gateway を経由するクライアントが存在するサブネットまで絞り込みができました。

終わりに

NAT Gateway のメトリクスに関する CloudWatch ダッシュボードと仲良くなりたい、というエントリでした。

いろいろ話が発散してしまいましたが、一番書きたかったのは以下のメトリクスの違いです。

  • BytesInFromDestination
  • BytesInFromSource
  • BytesOutToDestination
  • BytesOutToSource
  • PacketsInFromDestination
  • PacketsInFromSource
  • PacketsOutToDestination
  • PacketsOutToSource

Source とか Destionation の考え方は以下の通りで、

NAT Gateway metric source destination

1 パケットあたりおよそ 50 ~1500 バイトである、という点を押さえてもらえれば大丈夫です。

何らか参考になれば幸いです。

以上、 チバユキ (@batchicchi) がお送りしました。