column

コラム

NAT Gatewayのコスト分析で、S3ゲートウェイエンドポイントのありがたさに気づいた

  • TAG

    タグ未登録
  • UPDATE

    2022/06/01

こんにちは。DX事業部の宮國です。

 

今回は、とあるAWSアカウントでNAT Gatewayのコストが問題になり、調査をした際の手順をまとめてみようと思います。

 

NAT Gatewayへのデータ転送量高騰検知

あるAWSアカウントでデータ変換処理を実施した日のコストを確認したところ、想像以上に跳ね上がっていて、

中でもNAT Gateway(EC2その他に分類)が高くなっていたことを検知しました。

 

 

NAT Gatewayの料金は以下の課金体系です。

  • NAT Gateway 1台あたりの料金 $0.062/時

  • 処理データあたりの料金 $0.062/GB

 

今回の場合、処理データに対する課金が大半を占めていることがわかります。

この課金がかかるべくしてかかっているのか、削減の余地があるのか調べるために、

まずはNAT Gatewayに関わる通信の状況を確認することにしました。

 

【調査】VPCフローログの分析

NAT Gatewayに関わる通信の状況を可視化するため、今までただ有効化するだけだったVPCフローログを分析することにしました。

※分析する際、クラスメソッドさんのブログを大いに参考にさせていただきました。

 

NAT Gatewayへの転送

まずはNAT Gatewayへの転送量が多いIPを確認します。

 

コンソールから、VPC→フローログを選択して、VPC Flow logが吐かれているロググループを確認します。
 
その後、CloudWatch→ ログ→ログのインサイトを選択し、検索するロググループと時間を選択して、以下のクエリを実行します。
(NGW IPとVPC CIDRはよしなに置き換えます)
 
filter (dstAddr like '<NGW IP>') and isIpv4InSubnet(srcAddr, '<VPC CIDR>') 
| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr
| sort bytesTransferred desc
| limit 10
 
結果は以下の通りで、上位3つのsrcAddr→NatGatewayIPへのデータ転送量が圧倒的であることが判明しました。
 
--------------------------------------------------
|   srcAddr    |   dstAddr    | bytesTransferred |
|--------------|--------------|------------------|
| 10.26.XX.XX  | NATGatewayIP | 6237807012445    |← ★
| 10.26.XX.XX  | NATGatewayIP | 5011831072081    |← ★
| 10.26.XX.XX  | NATGatewayIP | 4743680925700    |← ★
| 10.26.XX.XX  | NATGatewayIP | 17185058578      |
| 10.26.XX.XX  | NATGatewayIP | 16327307092      |
| 10.26.XX.XX  | NATGatewayIP | 10823661056      |
| 10.26.XX.XX  | NATGatewayIP | 6190193868       |
| 10.26.XX.XX  | NATGatewayIP | 5212032630       |
| 10.26.XX.XX  | NATGatewayIP | 2351302096       |
| 10.26.XX.XX  | NATGatewayIP | 2014917735       |
--------------------------------------------------

 

NAT Gatewayからの転送

次にNAT Gatewayからの転送量が多いIPを確認するために以下のクエリを実行します。

srcAddrにNAT GatewayのIPを指定します。

filter (srcAddr like '<NGW IP>') and not isIpv4InSubnet(dstAddr, '<VPC CIDR>') 
| stats sum(bytes) as bytesTransferred by srcAddr, dstAddr
| sort bytesTransferred desc
| limit 10
 
結果は以下の通りでした。
 
----------------------------------------------------
|   srcAddr    |    dstAddr     | bytesTransferred |
|--------------|----------------|------------------|
| NATGatewayIP | 52.219.YY.YY   | 59577406111      |
| NATGatewayIP | 52.219.YY.YY   | 50602399278      |
| NATGatewayIP | 52.219.YY.YY   | 50367397004      |
| NATGatewayIP | 52.219.YY.YY   | 50301804231      |
| NATGatewayIP | 52.219.YY.YY   | 50155587711      |
| NATGatewayIP | 52.219.YY.YY   | 49633473151      |
| NATGatewayIP | 52.219.YY.YY   | 49609148011      |
| NATGatewayIP | 52.219.YY.YY   | 49579273692      |
| NATGatewayIP | 52.219.YY.YY   | 49569382299      |
| NATGatewayIP | 52.192.YY.YY   | 49567720916      |
----------------------------------------------------

「52.219~」からはじまるIPに対するデータ転送が多いことがわかりました。

 

【調査】IPの特定

NAT Gatewayへの送信元IPの確認

次は、NAT Gatewayへのデータ転送量が多かった上位3つのIPのリソースを特定するため、

EC2→ネットワーク&セキュリティ→ネットワークインターフェイスからIPで検索します。

 

参考:Amazon VPC でこの不明な IP アドレスを所有しているリソースを見つけるにはどうすればよいですか?(AWSナレッジセンター)

 

すると、VPC内に配置したLambdaのENIであることが判明しました。

このVPC内Lambda→NAT Gatewayへの転送量が今回のコスト増の大きな要因となっていました。

NAT Gatewayからの送信先IPの確認

NAT Gatewayからの転送量で上位を占めていたのは、ほとんど「52.219~」からはじまるIPでした。

以下のコマンドでS3のIPレンジを調べて、S3であることを確認しました。

 

curl https://ip-ranges.amazonaws.com/ip-ranges.json | jq -r '.prefixes[] | select(.service=="S3") | .ip_prefix' | grep 52.219 | sort -n

参考:Amazon S3 で使用される IP アドレス範囲を確認するにはどうすればよいですか ?(AWSナレッジセンター)

データ変換処理後、データをS3へ格納する際の通信である可能性が高そうだと判断しました。

 

これらのVPC Flow Logsの調査から、VPC内Lambda→NAT Gateway→S3 の通信の過程で大量に課金されていることがわかりました。

【対策】S3ゲートウェイエンドポイントの作成

NAT Gatewayの課金高騰の原因が特定できたので、対策を練ります。

今回はVPC内リソース→VPC外AWSリソース向けの通信で課金されていたので、VPCエンドポイントが有効そうです。

VPC エンドポイントは、VPC内リソースから、Internet Gatewayを経由せずにS3などのVPC外のAWSリソースにアクセスするためのサービスです。

その中でも今回は大半がS3宛なので、S3ゲートウェイエンドポイントを利用する案が良さそうです。(接続元のリソースをパブリックサブネットに配置する案は、Lambdaのため棄却)

S3にはゲートウェイ型のVPCエンドポイントとインターフェイス型のVPCエンドポイントの2種類が存在しますが、

ゲートウェイ型のVPCエンドポイントは追加料金なしで利用できます。

 

今回の場合、このゲートウェイ型のVPCエンドポイントを利用することで、

VPC Lambda→NAT Gateway→S3 だった経路が

VPC Lambda→Gateway VPC Endpoint for S3→S3 となるので、

NA Gatewayの処理データ量に対する課金の大半は削減できるということになります。

 

また、この経路変更は、エンドポイントの作成とルートテーブルの設定変更で吸収できるので、

接続元がエンドポイントの指定方法を変える必要がありません。

最小の設定変更でコストを削減できそうです。

 

以下の手順で設定します。

VPC→エンドポイント→エンドポイントを作成 からS3ゲートウェイエンドポイントを選択します。

適用するVPCと、エンドポイントを使用するルートテーブルを選択します。

基本的にはこれだけです。ルートテーブルの変更は自動で反映されます。

参考:ゲートウェイエンドポイントを作成する(AWS)

 

これにより、VPC Lambda→S3への通信が、VPC Lambda→Gateway VPC Endpoint for S3→S3 となりました。

 

【確認】カスタムフィールド込みのVPC Flow logsを作成

せっかくなので、想定した経路でS3に通信できているかを確かめたくなりました。

これを確認するうえで、先ほどと同じfilterを使って分析するのも手ですが、より確実にやるために以下の方法をとりました。

VPC Flow logsにはtraffic-pathフィールドというものがあります。

このフィールドは、トラフィックが宛先に到達するまでに、どのようなパスを通ったかを数字で表します。

このフィールドはデフォルトでは出力されないので、traffic-pathフィールド込みのVPC Flow logsを改めて作成し、改めてデータ変換処理を実施しました。

 

新しく作成したVPC Flow logsで以下のクエリを実行します。

filter (srcAddr like '<Lambda ENI IP>') 
| filter (@message like 'S3 egress')
| limit 10

 

すると、ログの末尾に「ACCEPT OK – S3 egress 7」と表示されていました。

traffic-pathフィールドの「7」はゲートウェイ VPC エンドポイントを経由していることを表す数字なので、想定したルートでS3にアクセスできていることを確認できました。

なぜこのような構成になっていたか

こうして、設定変更を加えた結果、NAT Gatewayのコストの高騰は収まったのですが、そもそもなぜこのような構成になっていたのでしょうか。

まず、データ変換処理用LambdaをVPC内リソースにしていた理由はEFSをマウントするためでした。

開発当時はLambdaの一時領域が512MBまでだったので(現在は10GB)、一時領域としてEFSをマウントする必要があり、VPC内リソースとしていたとのことでした。

 

また、なぜプライベートサブネットのリソースがNAT Gateway経由でS3にアクセスするようになってしまっていたかですが、正直言って考慮漏れでした。

  • 今まで携わっていた案件で、NAT Gatewayの料金が無視できないレベルになった経験がなかった。
  • プライベートサブネットのリソースからS3への通信がこれほど大量になるワークロードだと思っていなかった。
  • VPCエンドポイントはセキュリティの文脈で必要になるものであって、コスト削減の文脈で役立つということを理解していなかった。

といったところが原因でした。

 

まとめ

ゲートウェイエンドポイントの利用によって、開発の最中でしたが、少ない変更で大幅にコストを抑えることができました。

セキュリティの文脈でVPC Endpointの利用を検討し採用するケースは認識していたのですが、

プライベートサブネットのリソース→S3、DynamoDBへの通信が多く見込まれる場合、

既に導入されているであろうNAT Gatwayをそのままなんとなく使うのではなく、ゲートウェイエンドポイントを併用するのが、コストの文脈でも適切だと実感しました。

ほとんどデメリットがないような気がしているので、これからはゲートウェイエンドポイントを導入するのを基本線にしようと思いました。

 

今回は以上です。

 

RECOMMEND

おすすめ記事一覧