AWSの費用が高いときのトラブルシューティング
先日、AWSからの請求を久しぶりに確認したところ、月額がいつの間にか4000円くらいになっていました。
AWSのコスト関連機能を使いながら原因を確認し、対応したため、トラブルシュートの流れをシェアします。
調査編
1. 費用がかかっているサービスの特定
- AWSマネジメントコンソールにログインし、AWS Cost Explorerを表示する。
- 適切な直近期間のレポートを表示する。
- 今回は2022年7月に作業したため、2022年6月一杯のレポートを、Dailyの粒度で表示した。
- レポートの上のほうのGroup byというペインから、Usage Typeを選択する。
ここまでで、用途ごとコスト/期間の積み上げ棒グラフと、グラフの元データになる表が表示される。
グラフだけ見ると初日がすごく高く見えるが、これは税。
実際には、表からもわかるように東京リージョンのDynamDB Write/ReadCapacityUnitが大半のコストを占めている。
※以降、Write/ReadCapacityUnitは、W/RCUや、(書き込み/読み込み)キャパシティユニットとも呼称する。
ここまでで、費用がかかっている機能の特定はできました。
補足:DynamoDB キャパシティユニットについて
本旨はコストトラブルシュートの流れをシェアすることですが、予備知識としてDynamoDBのキャパシティユニットについて、簡単に説明しておきます。
キャパシティユニット(CU)という単位でテーブル毎の処理性能(読み書きできる回数)を指定し、使用量ではなく性能に対して支払いが発生します。
例:あるテーブルの性能が1CUで月100円なら、50CUにすると50倍の読み書きができて、月5000円。
厳密には少し違うところもあるので、もし詳細知りたい場合は公式ドキュメントをどうぞ。
※実際には、キャパシティユニットには複数のプランが複数ありますが、今回はその1つである「プロビジョニングモード」を前提にしています。
2. 当該サービスで費用がかかっている原因の特定
2-1. 当該機能の料金体系のおさらい
DynamoDBのキャパシティユニットの料金体系について、公式を見て確認
東京リージョンでのキャパシティユニットの料金は以下。
ただし、毎月25W/RCU(アカウントごと、リージョンごと)が無料になる。
これは、請求単位に直すと、約18000CU-Hrs(キャパシティユニット時間)となる。
25キャパシティユニット * 24時間 * 30日 = 18000CU-Hrs
2-2. 事象の特定
手順1. で表示したCost Explorerのグラフを見ると、キャパシティユニットによる課金は6/14あたりから発生している。
無料枠である約18000CU-Hrsを13日間で使い切るということは、ざっくり1ヶ月間では40000CU-Hrsを使ったと仮説が立てられる。
実際に手順2-1.の料金をもとに、上記仮説における書き込みキャパシティユニットの料金を計算してみると
(40000-18000)WCU-Hrs * 0.000742USD/Hrs = 16.3USD
となり、概ね辻褄が合った。
AWS Billingで請求書を確認すると、無料枠から溢れた書き込みキャパシティユニットは21,720 WCU-Hrsとなっており、上記計算式とも整合している(上記計算式だと22,000 WCU-Hrs) 。
これで事象が把握できました。
対処編
1. リソースの確認
実際に東京リージョンのDynamoDB Tablesを見てみたところ、本番稼働させているTableの他、使っていない8個のテーブルが放置されていた。
それぞれ書き込み/読み込みキャパシティユニットは5CUとなっており、これにより合計30000CU-Hrs程度を無駄に消費していた模様。
(5 * 8)CU * 24時間 * 30日 = 28800CU-Hrs
※AWS CDKでDynamoDB Tableを作成した場合、キャパシティユニットのデフォルトは5CUとなる。
2. リソースの修正/削除
本セクションはDynamoDBに対するコスト削減の詳細なので、趣旨から逸れますが、参考まで。
2-1. 不要なテーブルの削除
放置していた不要テーブルを削除した。
AWS CDKでデプロイされていたため、併せて不要なCloudFormation Stackも削除しておいた。
2-2. 本番稼働テーブルの性能の見直し
DynamoDBのキャパシティ戦略は大きく3つある。
- プロビジョニング:一定のキャパシティユニットを時間あたりで買う
- プロビジョニング + Auto Scaling :キャパシティユニットを幅で指定することで、ワークロードが小さいときは課金料を抑えつつ、スパイク時のスケールも可能にする
- オンデマンド:割高だが、使った分だけの課金となり、スケール可能。ただし、無料枠はない
https://docs.aws.amazon.com/ja_jp/amazondynamodb/latest/developerguide/HowItWorks.ReadWriteCapacityMode.html (再掲)
もともと1. の戦略を取っており、キャパシティユニットは3CUとなっていた。
試算の結果、2. が最もコストを抑えられることが分かったため、そちらに修正した。
【修正後の設定値イメージ】
上記キャパシティ戦略を取る際の、AWS CDKのサンプルコードも別記事で公開します。
※ DynamoDB経験者向け:GSIも、テーブルから独立してキャパシティユニット戦略を指定します。今回は、GSIや他テーブルも全てプロビジョニング + Auto Scalingにしました。
3. 事後確認
10日後に、コスト状況を確認した。
※例えばEC2だと、Auto Scaling Groupが効いてたせいで、インスタンスを落とした数分後には新たに立ち上がっていて、コスト削減できていなかった、ということがよく起きる。
AWS Billingで7/10時点での7月請求を確認。
このまま行くと16500W(R)CU-Hrs程度に落ち着きそうな見込みであり、半分以下まで改善されていることが実際に確認できた。
補足:再発防止
AWS Budgetsを利用すると、AWSの費用が想定より上振れているときに通知を知ることができる。
なお、Budgetを作成するだけでは通知が来ないことに注意。BudgetにAlertを紐付ける設定を行う。
今回は予算10USDに対して、予測が200%(20USD)となった際にメールが発火されるように設定した。
追伸1
DynamoDBは無料枠もあって安いので、S3のように激安のイメージが先行していましたが、無料枠を超えるとインスタンス系とそんなに変わらない費用になってきますね。
今回の記事で「DynamoDBくらい複雑な料金体系でも、こうやって地道に調査すれば自信を持って対策打てそうだな」というイメージを持っていただければ嬉しいです。
AWS SAP資格を来年更新しないといけないので、諸々思い出していかないといけないな、と思いました。
追伸2
この記事はMagicodeから移転しました。
2022年7月あたりの記事となります。
よければTwitterもフォローお願いします!
@sumiren_t
Discussion