本日も乙

ただの自己満足な備忘録。

VPCフローログを利用したNAT Gatewayのトラフィックコストの分析とVPCエンドポイントとの使い分けに関する考察

AWS NAT Gateway(以下、NAT Gateway)は、フルマネージドの NAT ゲートウェイです。プライベートサブネットに配置されているEC2、AWS Lambda などのリソースがインターネットへデータ転送するときは、NAT Gateway が便利です。データ通過に対する料金($0.062/GB)が発生するため、何でも NAT Gateway 経由でデータ通過させると多大なコストが発生してしまいます。

NAT Gateway のデータ通過に対するコストを最適化するにあたって、最も多く通信している送信元と送信先を特定しなければなりませんが、NAT Gateway および CloudWatch メトリクスだけでは特定することができません。本記事では VPC フローログによって VPC 内のトラフィックを Amazon Athena(以下、Athena)で分析できるように設定し、NAT Gateway に関するトラフィックを分析する方法を紹介します。また、NAT Gateway のコストを最適化するために VPC エンドポイントとの使い分けについて考察を述べます。

VPCフローログの設定

VPC のマネジメントコンソール画面に行き、「フローログ」タブから「フローログを作成」を選択します。

以下のように設定します。S3 バケット ARN は各自の環境に置き換えてください。

項目
名前 flowlogs
フィルタ すべて
最大集約間隔 10 分間
送信先 Amazon S3 バケットに送信
S3 バケット ARN arn:aws:s3:::hogehoge-vpcflowlogs
ログレコード形式 カスタム形式
ログ形式 後述

ログ形式は以下の通りです。

${version} ${account-id} ${interface-id} ${srcaddr} ${dstaddr} ${srcport} ${dstport} ${protocol} ${packets} ${bytes} ${start} ${end} ${action} ${log-status} ${pkt-src-aws-service} ${pkt-dst-aws-service} ${flow-direction} ${traffic-path} ${pkt-srcaddr} ${pkt-dstaddr}

並び順はこの通りでなくてもいいですが、Athena テーブル作成時にカラムの並び順と揃える必要があります。メタデータはすべてを入れる必要はありませんが、ログ形式は後から変更ができないため、後で必要になりそうなものは含めておいたほうがよいでしょう。特に ${pkt-src-aws-service}${pkt-dst-aws-service}${pkt-srcaddr}${pkt-dstaddr} は今回の分析でとても重要なので忘れずに追加してください。

setting-vpc-flow-logs

Athena テーブルの作成

データベースは default を指定しておきます。以下のクエリでテーブルを作成します。日単位でパーティションを分割していますが、ログ量が多くて Athena のクエリ実行に時間がかかる場合は時間単位でパーミッションを分割してください。Partition Projection を有効にしておくことで、データが増えてもパーティションを作成する必要はないのでとても便利です。

CREATE EXTERNAL TABLE IF NOT EXISTS vpc_flow_logs (
  version int,
  account string,
  interfaceid string,
  sourceaddress string,
  destinationaddress string,
  sourceport int,
  destinationport int,
  protocol int,
  numpackets int,
  numbytes bigint,
  starttime int,
  endtime int,
  action string,
  logstatus string,
  pktsrcawsservice string,
  pktdstawsservice string,
  flowdirection string,
  trafficpath string,
  pktsrcaddr string,
  pktdstaddr string,
)
PARTITIONED BY (`date` string)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ' '
LOCATION 's3://hogehoge-vpcflowlogs/prefix/AWSLogs/<AWSアカウントID>/vpcflowlogs/ap-northeast-1/'
TBLPROPERTIES
(
  "skip.header.line.count" = "1",
  "projection.enabled" = "true",
  "projection.date.type" = "date",
  "projection.date.range" = "2020/01/01,NOW",
  "projection.date.format" = "yyyy/MM/dd",
  "projection.date.interval.unit" = "DAYS",
  "storage.location.template" = "s3://hogehoge-vpcflowlogs/prefix/AWSLogs/<AWSアカウントID>/vpcflowlogs/ap-northeast-1/${date}"
);

テーブルを作成したら、以下のクエリでフローログが取得できることを確認します。

SELECT * FROM "default"."vpc_flow_logs" limit 10;

以上で設定は完了となります。

クエリ例

実際に NAT Gateway に関するデータ量を Athena から調べてみます。以下のような構成を前提にします。

example-vpc-network

項目 IP アドレス
VPC IPv4 CIDR 10.0.0.0/16
EC2 インスタンスのプライベート IP アドレス 10.0.1.5/32
NAT Gateway のプライベート IP アドレス 10.0.2.100/32

ケース1

NAT Gateway を介して最も多くトラフィックを送信している送信元と送信先を特定します。

SELECT
  sourceaddress,
  pktdstaddr,
  pktsrcawsservice,
  pktdstawsservice,
  SUM(numbytes) AS bytesTransferred
FROM "default"."vpc_flow_logs"
WHERE
  regexp_like(sourceaddress, '10.0')
  AND destinationaddress = '10.0.2.100'
GROUP BY sourceaddress, pktdstaddr, pktsrcawsservice, pktdstawsservice
ORDER BY bytesTransferred DESC
LIMIT 5

NAT Gateway を介するトラフィックの場合、destinationaddress(VPC フローログのメタデータは dstaddr)と pktdstaddr(VPC フローログのメタデータは pkt-dstaddr)の値は異なります。destinationaddress には NAT Gateway のプライベート IP アドレスが記録され、pktdstaddr には、インターネット上の最終的な送信先 IP アドレスが記録されます。pktdstawsservice(VPC フローログのメタデータは pkt-dst-aws-service)は pktdstaddr の IP アドレスが AWS サービスで使用されている場合、その AWS サービスが記録されます。

例えば、以下の表のような結果を得たとします。pktdstawsservice に Amazon DynamoDB(以下、DynamoDB)が記録されていることから、VPC エンドポイントを設定する前に DynamoDB にクエリなどの操作を行ったことで NAT Gateway 経由で通信していたことがわかります。

※ AWS 以外の IP アドレスは Examples です。

sourceaddress pktdstaddr pktsrcawsservice pktdstawsservice bytesTransferred
1 10.0.1.5 54.240.225.178 - AMAZON 8721269
2 10.0.1.5 203.0.113.1 - - 29720
3 10.0.1.5 52.94.8.36 - DYNAMODB 11176
4 10.0.1.5 13.33.29.13 - CLOUDFRONT 7639
5 10.0.1.5 203.0.113.2 - - 5674

DynamoDB の VPC エンドポイントを設定した後に集計すると、NAT Gateway を経由しなくなることがわかります。

sourceaddress pktdstaddr pktsrcawsservice pktdstawsservice bytesTransferred
1 10.0.1.5 203.0.113.1 - - 29720
2 10.0.1.5 203.0.113.2 - - 19720
3 10.0.1.5 203.0.113.3 - - 11460
4 10.0.1.5 52.119.220.170 - AMAZON 4104
5 10.0.1.5 52.119.222.137 - AMAZON 3961

ケース2

NAT Gateway からインターネットへのアウトバウンドにおいて、トラフィック量がもっとも多い送信先を探します。

SELECT
  destinationaddress,
  pktsrcawsservice,
  pktdstawsservice,
  SUM(numbytes) AS bytesTransferred
FROM "default"."vpc_flow_logs"
WHERE
  NOT regexp_like(destinationaddress, '10.0')
  AND sourceaddress = '10.0.2.100'
GROUP BY sourceaddress, destinationaddress, pktsrcawsservice, pktdstawsservice
ORDER BY bytesTransferred DESC
LIMIT 10

このクエリの WHERE 句の条件が分かりづらいかもしれませんが、NAT Gateway の視点に立つとわかりやすいです。NAT Gateway から見てインターネット(グローバル IP アドレス)へのトラフィックに限定したいので、sourceaddress(VPC フローログのメタデータは srcaddr)は NAT Gateway のプライベート IP アドレスになります。destinationaddress(VPC フローログのメタデータは dstaddr)はグローバル IP アドレスに限定したいので VPC CIDR(10.0.0.0/16)を除外します。

ケース3

ケース2の逆で、VPC 内部の EC2 インスタンスなどが NAT Gateway を介したダウンロードのトラフィック量がもっとも多い送信元を探します。

SELECT
  sourceaddress,
  pktsrcawsservice,
  pktdstawsservice,
  SUM(numbytes) AS bytesTransferred
FROM "default"."vpc_flow_logs"
WHERE
  NOT regexp_like(sourceaddress, '10.0')
  AND destinationaddress = '10.0.2.100'
GROUP BY sourceaddress, destinationaddress, pktsrcawsservice, pktdstawsservice
ORDER BY bytesTransferred DESC
LIMIT 10

ケース2 同様に NAT Gateway の視点に立ってみます。NAT Gateway から見て、インターネット上のホストから送信されてきたトラフィックに限定したいので destinationaddress(VPC フローログのメタデータは dstaddr)は NAT Gateway のプライベート IP アドレスになります。sourceaddress(VPC フローログのメタデータは srcaddr)はグローバル IP アドレスに限定したいので VPC CIDR(10.0.0.0/16)を除外します。

コスト最適化ポイント

NAT Gateway のトラフィック量を分析できたので、次にどうやってコスト最適化をするかについて考えます。例えば、先述のケース3において以下のような結果を得られたとします。memo 欄は IP アドレスやシステムのユースケースを洗い出して調査した結果、利用している AWS サービス名だと仮定します。

sourceaddress pktsrcawsservice pktdstawsservice bytesTransferred memo
1 54.240.225.178 AMAZON - 805306368000 Amazon ECR
2 52.94.8.36 DYNAMODB - 128849018900 DynamoDB
3 54.240.225.173 AMAZON - 10737418240 Session Manager
4 52.119.221.73 AMAZON - 8589934592 Amazon Systems Manager
5 13.33.29.13 CLOUDFRONT - 856579 CloudFront

S3、Dynamo DB は VPC エンドポイントを設定する

S3 と DynamoDB の VPC エンドポイントは作成してもお金がかからないゲートウェイタイプなので、必ず作成するようにしましょう。NAT Gateway のデータ通過料金が $0.062/GB(東京リージョン)なので、先ほどの表だと 128GB * $0.062 ≒ $8 が削減できます。

NAT Gateway にするか PrivateLink(VPC エンドポイント)にするか

すでに NAT Gateway が作成されている状況において、PrivateLink(VPC エンドポイント)経由でデータを通過させるかの損益分岐点について考えてみます。以下の表は NAT Gateway と PrivateLinkの料金です(東京リージョン、2021年5月現在)。

サービス名 項目 料金
NAT Gateway 処理データ $0.062/GB
NAT Gateway ゲートウェイ $0.062/h・個
PrivateLink VPC エンドポイント $0.014/h・個
PrivateLink 処理データ $0.01/GB

処理データの料金を比較すれば PrivateLink の方が安いのですが、VPC エンドポイントを1つ作成するたびに料金が発生します。さらに AZ 毎に VPC エンドポイントを作成する場合は AZ 数分かかります。例えば 3AZ に VPC エンドポイントを作成して 1ヶ月(730時間)稼働させたとすると、約 $30/月 かかります。

もし、外部ネットワークへの通信がいっさい必要ないシステムであれば、NAT Gateway のゲートウェイ料金よりも PrivateLink の VPC エンドポイント料金の方が安いので PrivateLink を使った方がコストは安いです。しかし、外部ネットワークへの通信が必要で NAT Gateway がある場合、どれぐらいのデータ量であれば PrivateLink の方が安くなるのでしょうか。

以下は NAT Gateway と PrivateLink のコスト損益分岐点を示したグラフです。

comparison-of-nat-gateway-and-private-link-costs

おおよそ 600GB 以上データ通過させる場合は PrivateLink にした方が安くなることがわかります。それを踏まえて上の NAT Gateway のトラフィック量の表を見た場合、Amazon ECR は約 800GB のデータが通過したため、PrivateLink の方がコストをおさえられます。Session Manager、Amazon Systems Manager は 600GB 以下なので NAT Gateway のままでいたほうがよさそうです。

参考URL