月額$1,000掛かっていたAWS-NatGateway通信料金をほぼゼロまで圧縮した話

この記事は [うるる Advent Calendar 2022](https://qiita.com/advent-calendar/2022/uluru) 2日目の記事です。


## はじめに
AWSのPrivateサブネットにおける通信リソースとしてNatGatewayがありますが、
その汎用性の高さからサブネット内の通信環境の構築の上では何かと依存しがちです。
しかしNatGatewayは単価が比較的高く、適切な構成にしないと高額課金に繋がります。
**そして私たちはこれに依存する構成で構築した結果、請求額が爆増するという失敗をしました。**

そこで今回は私たちが失敗した事例を踏まえつつ、
どのようなソリューションを用いて解決に至ったのかについて解説していきたいと思います。


### この記事で語るもの
- 私たちがNatGatewayの活用において失敗したこと
- その失敗に対して使用したAWSサービスと内容の概要

### この記事で語らないもの
- AWSのリソースに関する詳細な説明、構築方法

またこの記事に記載している金額、サービス名称などはすべて2022年11月30日現在のものになります。


## あらためて、サブネットとNatGatewayについて簡単なおさらい
そして冒頭で述べたとおりサブネットにはPublicサブネットとPrivateサブネットの2種類があります。
ざっくり説明すると外界から見える場所はPublicサブネット、
外界から見えない場所をPrivateサブネットという感じですね。

Privateサブネットへの配置は外界からの直接的なアクセス手段が無いことで
セキュリティ性を上げることができるメリットがあります。
しかし一方でそのままだとVPCの外にアクセスすることもできません。

そこでPrivateサブネットから外界に対して通信を実施する方法として
**便利かつ汎用的なものとしてNatGateway** というものがあるのですが、
**$0.062/GB なので意外と高い。**

つまり、通信が多く発生するサービスをPrivateサブネットへリソース配置すると
**外界から隠される安全性と引き換えに高額な通信コストを払う形になりうるのです。**

## 私たちがやってしまった失敗
世の中のWebページの傾向を調べるために汎用的なWebクローラーを試験的に運用し、
HTMLページの情報を収集しておりました。
そのアプリケーションはPrivateサブネット ＋ NatGatewayを通した通信で構築されておりました。

また収集した大量のデータに対して加工処理をするため、
PrivateサブネットにFargateを用いたBatch処理を実装しておりました。

ライブラリや外部コンテナも活用していたので1台あたり1GB程度、
それも複数台並列で毎日数回起動する設計です。
そしてこちらもNatGatewayを通って通信する設計になっておりました。

![名称未設定ファイル-ページ1のコピー.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267820/2a54fdfe-5c41-3f5b-b88f-c458d29fb370.png)

…はい、もうお分かりですね。**通信容量が爆増し、請求額が跳ね上がりました。**

請求額が想定よりも高く出ていることに違和感を覚え、
AWSのCostExploerで見てみたらNatGatewayの請求額が `$1,000/month` も掛かっておりました。
（その時の冷や汗たるや…。。。）

ここから私たちのコスト削減に向けた挑戦が始まります。

## この課題にどう立ち向かったのか
NatGatewayの通信料金が高いことを見て通信が発生している箇所を洗い出しました。
結論として前述のものがNatGatewayの通信の殆どを占めていた為、
**これらに対し3つの対策で通信費の削減** を実施しました。順番に解説していきます。


### WebクローラーをInternetGateway(Publicサブネット)経由に変更した
端的に言うとWebクローラーを動かすサブネットをPrivateからPublicに変更しました。
いきなり「えっ」と言われそうな修正ですね。

![名称未設定ファイル-ページ1のコピーのコピー.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267820/df85bc6f-07ac-8855-2486-b4cf31fc5bc1.png)

Webクローラーはその特性上、外界との通信が多く発生する傾向にあります。
そしてPublicサブネットに配置した場合はInternetGateway経由での通信となりますが、
**こちらはなんと通信料金が無料です。**

そもそもの話、Privateサブネットに配置したい意図はどういうものかを考えてみると
**外界から隠してセキュリティリスクを軽減する**ことにあります。
しかしながらWebクローラーのコンテナはビジネス的にクリティカルなデータを扱っていない為、
万が一、別に外から見えたとしてもほぼリスクはない。


こうした背景から**コストとリスクの天秤が釣り合っていないと判断**し、
SecurityGroupなどの保護を掛けた上で敢えてPublicサブネット上で運用するという決断をしました。


### ECRのコンテナPULL時にPrivateLink＋プルスルーキャッシュの活用
こちらはバッチコンテナのお話。
こちらはビジネス上、価値のあるデータに整形する処理をしている為Public化は出来れば避けたかったのと
発生している通信はほとんどAWS内の世界に閉じていることからPrivateサブネット上で実施する前提で検討をしました。

問題となっているコンテナは2つのコンテナイメージを使用しており、
1つは自前でECRにアップロードしているもの、もう1つはDockerHubから直接取得しているものでした。
こちらの問題はPrivateLink＋プルスルーキャッシュを使うことで解決しました。
順番に解説します。

![名称未設定ファイル-ページ1のコピーのコピーのコピー.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267820/643c8b3c-7743-4d58-cfc5-aae7a36269e2.png)


#### ECRへの通信費削減 → PrivateLinkの活用
ECRはAWS内での通信となるため、PrivateLinkを使用することでコスト削減を狙いました。
こちらはNatGatewayを経由しない形でECRを始めとしたAWSのリソースに接続できるという代物。
（※最後の方に参考記事を添付致します）

PrivateLinkの使用料金は `$0.01/GB + $0.014/時`
NatGatewayと違って時間料金が掛かってくる点に注意が必要ですが、
通信料金は6分の1まで減るので通信容量が大きい場合により高い効果を発揮します。

#### DockerHubへの通信 → プルスルーキャッシュの活用
DockerHubへの通信はAWS外への通信となるため、PrivateLinkだけでは対応が出来ません。
そこでプルスルーキャッシュの出番となります。
これは最初の1回だけNat経由でPullしてしまえば
あとはPrivateLink経由でイメージを取得できるようになるという代物。

これにより外部公開されているコンテナに対しても通信費の圧縮を行なうことが出来ました。


### Dockerコンテナイメージのダイエット
最後はそもそもの通信の絶対量を減らすための取り組み。

もともとはPythonの全部入りベースイメージを使用しており、1GB超の重量級コンテナでした。
こちらをPython-slimにベースイメージを変更することで300MB強までダイエットに成功しました。

これにより通信容量の圧縮に貢献をしたことはもちろんですが、
コンテナが軽量化されたことでbuild時間の軽減やECSの起動時間短縮(=Pull時間の短縮)にも繋がっております。

全部入りのベースイメージを使用している場合はslimやalpineに変更するだけで
大幅に軽量化が出来る可能性があるので肥大化しているコンテナがある場合は検討してみることをおすすめします。


## これによりどれぐらい削減できたのか
**平均 `$30.00~40.00/day` 掛かっていたNatGateway料金をほぼゼロにすることが出来ました！**

![スクリーンショット 2022-12-01 0.48.44.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/267820/474299e3-661b-80e8-aff9-a1e4c6faa74b.png)
▲グラフの青い部分がNatGateway通信料金

代わりにVPCエンドポイント料金と通信料金が増える形となりましたが、
こちらは `$4.00~5.00/day` ほどなので、
**差し引きでおおよそ `$30/day` 、月額にして `$900.00/month`になります。**
今の為替レートで換算するとなかなかの金額ですね。。。
それなりのスペックのEC2やRDSを運用できる金額が丸々浮いたことになります。

通信費用はおざなりになりがちですが、塵も積もればなんとやら。
本当に馬鹿になりません。

## まとめ
いかがだったでしょうか。
**NatGatewayでそのまま運用していると思わぬ課金が発生してしまうことがよく分かったと思います…笑**
各リソースの通信ルートはコスト分析をしないとなかなか表面化してこないものですが、
適切な通信ルートを設定することで、コストの適正化をはかっていきましょう！

最後になりますが、ここに記載した内容はチームメンバーによる提案・実装によって実現できたものが殆どです。
コスト課題に対して実直に調査し、実現して頂いたことに感謝です。ありがとうございました！


明日は [KONTA2019](https://qiita.com/KONTA2019)さんによる記事です！乞うご期待！


## 参考
ECRとPrivateLink： https://qiita.com/KurokawaKouhei/items/9389f36420ebaa0390bd