AWSコストを見直したら5人日で年間約220万円の削減ができました

※この記事は モチベーションクラウドシリーズ [Advent Calendar 2022](https://qiita.com/advent-calendar/2022/mcs) の3日目の記事です。

# これは何？
こんにちは、リンクアンドモチベーション SREグループの久原です。
昨今、急激な円安の流れによって外資系サービスのコスト高騰は喫緊の課題になっています。
今回は上記に対してAWSコストの見直しを実施したので、それについて記事を書こうと思います。

# どれくらいコストを削減したのか？
結論から話すと、年間で **約 220万円** ものコスト削減ができました。
それに対してかかった工数は、調査検討〜対応含めて**約5人日**でした。
AWSリソースの利用規模やコスト最適化の実施状況によってどれくらい削減できるかは異なりますが、AWSを利用しているけどコストはあまり気にしていない...という方は是非記事を読んでみてください。

# 何をしたのか？
AWSのコスト最適化の基本的な原則は[こちら](https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/wat.pillar.costOptimization.ja.html)を参照ください。
今回弊社では、上記記載のある基本的なプラクティス中でも比較的コストパフォーマンスの高いと判断した以下3つを実施しました。

- Saving PlansのカバレッジUP
- RDSリザーブドインスタンスのカバー率UP
- 最新世代インスタンス利用

### ①[Saving Plans(SP)](https://aws.amazon.com/jp/savingsplans/)のカバレッジUP
一言で言うと、 **EC2やFargateの利用料を予約購入することで割引になるソリューション** です。
似たようなソリューションとして[リザーブドインスタンス(RI)](https://aws.amazon.com/jp/ec2/pricing/reserved-instances/)というものがあります。しかし、SPの方が **圧倒的に** 予約の自由度が高いです。
詳細は[比較記事](https://dev.classmethod.jp/articles/ec2-reserved-instances-savings-plans-comparison/)をご覧いただければと思いますが、SPの強みをまとめると以下です。

- インスタンスタイプの制限がない(後述するリザーブドインスタンスは予約するタイプを指定しなければならない)
- リージョンの制限がない
- どのコンピューティングシステム(EC2, Fargate, Lambda)でも使える

SPを購入することで、現状使っているAWSリソースに対して"いい感じ"に割引を効かせてくれます。

### ②[RDSリザーブドインスタンス](https://aws.amazon.com/jp/rds/reserved-instances/)のカバー率UP
一言で言うと、**RDSインスタンスを予約購入することで割引になるソリューション** です。
①で記載したものはコンピューティングシステムに対する予約購入ですが、こちらはRDSに対する予約購入になります。残念ながらRDSのSaving Plansは提供されていませんが、リザーブドインスタンスを購入できればかなりの費用削減が期待できます。

### ③最新世代インスタンス([AWS Graviton](https://aws.amazon.com/jp/ec2/graviton/))利用
一言で言うと、 **現状のインスタンスタイプを最新世代にすることで、同スペックで金額を抑えられるソリューション** です。
予約購入(SP, RI)は1年ないし3年間の継続利用を前提としたソリューションになりますが、こちらはそのような縛りは一切なく同スペックで価格を抑えることができる優れものです。

EC2の`m5.xlarge`を例に取ると、以下の表([参照](https://aws.amazon.com/jp/ec2/pricing/on-demand/))のように同じvCPU, メモリ容量を搭載しているタイプにおいて約20%ものコスト削減が見込めます。

| インスタンスタイプ | オンデマンドの時間単価 | vCPU | メモリ | 
| ------------------ | ---------------------- | ---- | ------ | 
| `m6g.xlarge`(最新世代)         | **0.198 USD**              | 4    | 16 GiB | 
| `m5.xlarge`(旧世代)          | **0.248 USD**              | 4    | 16 GiB | 

# どう削減したのか？
3つそれぞれについて、具体的にやったことを記載します。
**以下で示す手順は2022年11月時点で我々が実施した手順であり、実際に実施する際は公式の手順を参考に行ってください。**

## Saving PlansのカバレッジUP
基本的に[公式の手順](https://aws.amazon.com/jp/blogs/news/savings-plan-faq/)に則って購入を進めました。
以下に、実際に我々が行った手順を記載します。

1. カバレッジの確認
2. 推奨事項の確認
3. 推奨されるSaving Plansの内容を確認し、購入

### ①カバレッジの確認
まずは現状のカバレッジを確認します。

payerアカウントでログイン > AWS Cost Explorer > SavingPlans > カバレッジレポート
![b948b170-9ed8-3ffa-fc4a-c6953d3df1dc.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/732e1f01-9338-0933-e63e-c6fc0ba5435d.png)


既に弊社ではSaving Plansの購入を行っていたのですが、先月の平均カバレッジが50%でした。つまりまだ半分のリソースはオンデマンド料金で賄っているということです。このカバレッジを100%に近づけるために、追加でSaving Plansを購入します。

### ②推奨事項の確認
AWS Cost Explorer > SavingPlans > 推奨事項
![7b16aa24-81b1-734b-3670-06779e1b5318.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/b04d2e39-af04-c233-10fa-03e2db77bea6.png)


以下の項目を選択することで、自動でおすすめのコミットメント額を提示してくれます。

- Saving Plans タイプ
- 推奨事項レベル
- Saving Plans 期間
- 支払いオプション
- 基準とする直近の期間

基準とする直近の期間は、事前にCost Explorerで直近のAWSコストの変動の確認と将来の拡大・縮小を見据え、適切な期間を設定します。

### ③推奨されるSaving Plansの内容を確認し、購入
提示されたコミットメント額を確認してカートに追加します(この時点では課金は発生しません)
カートに追加された内容と前払い金額をよく確認して、注文書を送信します。

以上です。インスタンス側の切替や検証の必要もなければ、ダウンタイムも一切発生せずオンデマンドからSaving Plansの料金に切り替わるので非常に工数のかからない施策です。


## RDSリザーブドインスタンスのカバー率UP
基本的に[公式の手順](https://aws.amazon.com/jp/rds/reserved-instances/)に則って購入を進めました。
以下に、実際に我々が行った手順を記載します。

1. 購入するDBインスタンスをリストアップする
2. 実際にReserved DB Instanceを購入する

### ①購入するDBインスタンスをリストアップする
まずは**最低1年間、現状のインスタンスタイプで稼働を続ける見通しがある**DBインスタンスをリストアップします。

### ②実際にReserved DB Instanceを購入する
上記をリストアップできたら、早速購入作業に入ります。
RDS > リザーブドインスタンス
![4af3e4e7-0d91-d162-516f-c5ff162e5568.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/a6cee45c-ad2d-f70a-cc6e-83d33ac58900.png)


上記画像の項目を記載していきます。
気をつけるべきは、 **この画面で「送信」ボタンをクリックすると購入が確定してしまう** 点です！
特に以下のような間違えはあるかもしれません。気をつけましょう。

- aurora-mysql と mysql を間違える
- インスタンスクラス xlarge と large を間違える
- オファリングタイプ前払いする予定ではなかったのに All Upfront にしてしまう


## 最新世代インスタンス利用
基本的に[公式の手順](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/Overview.DBInstance.Modifying.html)に則って購入を進めました。
以下に、実際に我々が行った手順を記載します。

1. 変更先のインスタンスクラスの確認
2. 移行リスクの洗い出し、実際に移行するインスタンスの決定
3. 開発環境にて、本番同等の最新世代インスタンス環境の構築
4. 検証の実施
5. 既存の本番環境の切り替え

### ①変更先のインスタンスクラスの確認
まず、既存環境のインスタンスタイプと最新世代のインスタンスタイプを並べます。
下の表は弊社の現状のEC2, RDSのインスタンスタイプの設定値です。
#### EC2

| 環境 | 現状      | 最新世代   | 
| ---- | --------- | ---------- | 
| 開発 | t3.medium | t4g.medium | 
| 本番 | m5.xlarge | m6g.xlarge | 

#### RDS

| 環境 | 現状         | 最新世代      | 
| ---- | ------------ | ------------- | 
| 開発 | db.t3.medium | db.t4g.medium | 
| 本番 | db.r5.large  | db.r6g.large  | 

### ②移行リスクの洗い出し、実際に移行するインスタンスの決定
移行リスクとしては主に以下を懸念していました。

- EC2: IntelベースからArmベースになることによる影響
- EC2RDS両方: 切り替え時のダウンタイム発生

1つ目について、t3・m5系においてはIntelのx86系のCPUを用いていますが、t4g・m6g系はArmベースの[AWS Gravitonプロセッサ](https://aws.amazon.com/jp/ec2/graviton/)を用いています。よって、インスタンスタイプを変更するだけで正常に切り替えができるという単純なものではありません。
同様に、RDSもGravitonプロセッサ対応のインスタンスがあります。こちらは **AWSマネージドな部分が大きいため、EC2よりもインスタンスタイプ変更によるリスクが少ないと考え、RDSの移行のみを採用** しました。
2つ目について、2022年11月時点ではRDSの切り替えにおいてダウンタイムを避ける難易度が高いことがわかったため、メンテナンス期間を設けての実施を行いました。

### ③開発環境にて、本番同等の最新世代インスタンス環境の構築
リスクが少ないと言えど、いきなり本番環境のインスタンスタイプを変更することは避けるべきです。我々はタイプ変更に問題がないことを確認するため、以下の2つの検証を実施しました。

- E2Eテストの実施
- 弊社サービスの主要APIにおける性能試験の実施

上記の準備として、開発環境にて`db.r6g.large`のRDSを構築し、既存のサーバーと接続しました。
構築の際に既存の環境との差分はインスタンスタイプの設定のみです。
![51d3005d-c504-0506-0d7e-20411ca501b3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/4f59c479-7c7c-43d0-7619-65b316ae0e78.png)


### ④検証の実施
E2Eテストについては、以前弊社の社内ブログにて私が執筆した[記事](https://link-and-motivation.hatenablog.com/entry/2022/07/12/105033)にあるように、Autifyで自動化しております。そのため、上記のRDSと接続した開発環境のURLに置換して実行ボタンを押すだけで完了しました。
![0e0107bf-6d67-efe0-ab78-416de4a0570c.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/18752abc-d8a0-1aaf-27a2-6704ef99d1bf.png)


性能試験について、弊社では[Distributed Load Testing on AWS](https://aws.amazon.com/jp/solutions/implementations/distributed-load-testing-on-aws/)で自動化をしています。
今回は`db.r5.large`から`db.r6g.large`への変更で[理論上スペックが下がることはない](https://aws.amazon.com/jp/rds/instance-types/)ため、弊社サービスの主要APIに絞って試験実施をしました。

### ⑤既存の本番環境の切り替え
検証においてインスタンスタイプを切り替えても問題がないことを確認したので、既存環境の切り替えをしていきました。
しかし、切り替えにおいて避けて通れなかったのが **ダウンタイム** です。
マルチAZ配置を適用していましたが、[フェイルオーバーにおけるダウンタイム](https://aws.amazon.com/jp/premiumsupport/knowledge-center/rds-mysql-downtime-impact/)が1~2分程度発生してしまいます。
そのため弊社のカスタマーサポートチームと連携し、早朝にメンテナンス期間を設けて切り替えを行いました。
実際の作業としては[こちら](https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/modify-multi-az-db-cluster.html)に記載のあるように、簡単な手順で切り替え作業を終えることができました。

# まとめ
上記3つ施策の実施結果のまとめです。

### ①Saving PlansのカバレッジがUP！
左半分(10月)に比べてカバレッジがUPしました。とはいえMAXカバレッジが100%に達していないのでもう少し追加購入ができそうです。定期的にCost Explorerにてモニタリングをして追加購入を行なっていくのが良いと思います。
![スクリーンショット 2022-11-29 20.03.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/b647e6b4-f509-fb0a-d879-3328f962af26.png)

### ②RIの購入完了！
こちら一例になりますが、購入したインスタンスを予約一覧を確認することができました。
![スクリーンショット 2022-11-29 20.06.07.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/385d11dd-172b-2da2-eac7-f01ba57f279d.png)

### ③RDSの最新世代化完了！
無事、`db.r6g.large`への切り替えが完了し、変わらず正常に運用ができています。
![スクリーンショット 2022-11-29 20.08.05.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2340929/62571643-7d4c-0cde-b56f-0ffd7efaf614.png)
この移行作業、直近のAWSのアップデートで発表があった[RDSのBlue/Greenデプロイメント](https://aws.amazon.com/jp/blogs/aws/new-fully-managed-blue-green-deployments-in-amazon-aurora-and-amazon-rds/)を利用すればダウンタイム無し(=メンテナンス無し)で対応ができたのでは...もしGravitonへの切り替えの際には検討してみると良いかもしれません(我々は未実施なので実際に可能かどうかの保証はできません)。

### 最後に
今回我々が実施した施策はあくまで[こちら](https://wa.aws.amazon.com/wellarchitected/2020-07-02T19-33-23/wat.pillar.costOptimization.ja.html)に記載があるとおり、AWSが推奨する基本的なベストプラクティスになります。
しっかりと日々Cost Explorerを用いてコストをモニタリングし、適切にSaving Plansやリザーブドインスタンスを購入することで無駄なくAWSサービスを利用することができると考えています。