ローコードで始めるインフラコスト削減

# はじめに

Futureアドベントカレンダー20日目です。（遅れてごめんなさい）
19日は @orangekame3 さんの「[量子コンピュータとジャンケンする](https://qiita.com/orangekame3/items/2f1cde38a92f1289cd69)」でした。
Futureのアドベントカレンダーを書くのは3年目で、毎年この時期になると時が経つのが早いのを感じます。

さて、私が所属しているプロジェクトでは継続的にインフラコストの見直しを実施しており、リザーブドインスタンスの適用やECSタスク数の削減、不要なリソースの削除等を行ってきました。

その結果月に約＄1,000程度、年換算で約＄120,000（※日本円で140万円）のコスト削減に成功しました。（※$1=115円）

そして、次の対応として総コストの中で多くの割合を占めるRDSのコスト削減を行なっていきたいと考えており、今回はその"検証"をしたいと思います。
内容としては平日は検証環境のRDSを自動で稼働させ、土日祝はRDSを自動で停止させるというものです。当社は土日祝休みなので、開発環境に関しては利用していないのに稼働している状態（= 無駄にコストが発生している）となっており、ここの無駄を削減したいと考えています。

# 削減コスト

ちなみにRDSを停止させることにより、削減できる費用はDBインスタンスの起動時間に対する課金です。（インスタンスが停止されている間でもプロビジョニングされたストレージとバックアップストレージに対する請求は行われます。）

■参考
> 一時的なテストや毎日の開発作業のために、断続的に DB インスタンスを使用する場合、コスト削減のため、Amazon RDS DB インスタンスを一時的に停止できます。DB インスタンスが停止している間は、プロビジョニングされたストレージ (プロビジョニングされた IOPS を含む) とバックアップストレージ (指定された保存期間内の手動スナップショットと自動バックアップを含む) は請求されますが、DBインスタンス時間は課金されません
> https://docs.aws.amazon.com/ja_jp/AmazonRDS/latest/UserGuide/USER_StopInstance.html

# 要件整理

実現したい要件を簡単に整理します。

* 土日祝になったら自動的にRDSを停止させる。 （★今回の検証対象）
* 土日祝明けはRDSを自動で起動させる。

# 利用サービス

以前はLambda関数を使用してカスタムロジックを記述したり、CloudWatchのイベントルールを作成したりする必要がありましたが、人員リソース・工数がそこまでかからないよう、今回はローコードで対応できるところはローコードで対応して、RDSを土日祝は自動で停止してコスト削減させるようにしていきたいと思います。

利用するサービスを以下に記載します。

* [RDS](https://aws.amazon.com/jp/rds/)
* [リソースグループ](https://docs.aws.amazon.com/ARG/latest/userguide/resource-groups.html)
* [Systems Manager Change Calendar（変更カレンダー）](https://docs.aws.amazon.com/ja_jp/systems-manager/latest/userguide/systems-manager-change-calendar.html)
* [Systems Manager Automation runbook](https://docs.aws.amazon.com/systems-manager-automation-runbooks/latest/userguide/automation-runbook-reference.html)

## RDS起動

今回の停止対象となるRDSを起動します。

RDS作成後、リソースグループを作成するため、タグを付与します。
今回は、Keyを`Action`、Valueを`StartStop` とします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/9443eb3c-9107-7b5e-f8b5-e4bd2f110486.png)

## リソースグループの作成

次に、タグ付けされたAmazon RDS DBインスタンスのリソースグループを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/0408904d-7077-23fd-b036-f54ddb314c76.png)


## AWS Systems Manager Change Calendar とは

次に、Change Calendarから設定をしていきます。

Change Calendarは、簡単に説明すると、指定したアクションが実行できる日時とできない日時の範囲を設定することができるもので、イメージとしてはGoogleカレンダーに近いものになります。

### Change Calendarにスケジュールを設定する

#### 祝日の設定

まず、RDSを停止させる祝日のイベント設定から行います。

Change Calendar（変更カレンダー）ではデフォルトでは日本の祝日のデータが含まれていないため、Googleカレンダーのics形式の祝日データを利用して祝日のイベント設定を行います。

AWS Systems Managerのサイドバーより、「カレンダーの変更」「変更カレンダーの作成」の順にクリックし、以下画面にアクセスします。

下画像の `Import calendar`で `.ics`形式のカレンダーファイルを読み込むことができます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/64d66058-2751-0939-5a83-aa94aeb03eac.png)

祝日のデータを取得するため、GoogleカレンダーからiCal形式のデータをダウンロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/57d68066-89a6-7d09-039c-e51d54109ac6.png)


ダウンロードした、 `basic.ics` をImport calendarにセットし、カレンダーを作成します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/af0b7549-e4d7-6fb4-44f8-57f7d49de006.png)

作成されたカレンダーを確認すると、祝日のデータが取り込まれたカレンダーが表示されていることがわかります。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/e3ff7cd5-82ce-3ee1-b8a2-6ee1d30a07d0.png)

#### 土日の設定

次に土日の設定を行います。
作成されたカレンダーにはまだ土日の `イベント` が設定されていないため、コンソール画面から設定していきます。

`イベントを作成` をクリック

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/72f49654-cf53-9951-0e9b-e5faa397b043.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/a2b54ec7-5485-c709-eaf3-19e5c9bd43ca.png)


これで土日のイベントを作成することができ、RDSを起動しない時間帯を設定することができました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/7f2b5ad8-6db3-f928-af52-d4353ee239ab.png)


# オートメーションの作成

次に行うのは、オートメーションの作成を行います。
AWS SystemsManagerには、オートメーションをすぐに開始できるように、事前定義された雛形を用意してくれています。今回は要件に合致する、`AWS-StopRdsInstance` を利用したいと思います。

`AWS-StopRdsInstance` 選択して、`アクション` -> `ドキュメントのクローン作成` を押下します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/02a6ad84-d1ae-e8b0-7422-96139c3c20f9.png)

`AWS-StopRdsInstance` の内容は以下のとおりです。
まず最初に、RDSのインスタンスが起動中かどうかを確認し、起動中だった場合にはインスタンスを停止させます。その後、正常にRDSが停止されたか確認をするメソッドを呼び出します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/16490247-c013-28a9-b825-15a0744b3652.png)

# 土日祝日の判定を追加

作成したオートメーションに土日祝日の判定を追加します。

ステップを追加を押下し、ChangeCalendarのStateを確認するようなステップを追加します。

ここで呼び出すGetCalendarStateというAPIの仕様は以下に記載されています。
レスポンスのStateは「OPEN」と「CLOSED」の二種類があり、カレンダー上の有無によってでStateが変わります。

> **get_calendar_state(*kwargs)**
> Gets the state of a Amazon Web Services Systems Manager change calendar at the current time or a specified time. If you specify a time, GetCalendarState returns the state of the calendar at that specific time, and returns the next time that the change calendar state will transition. If you don't specify a time, GetCalendarState uses the current time. Change Calendar entries have two possible states: OPEN or CLOSED .
> https://boto3.amazonaws.com/v1/documentation/api/latest/reference/services/ssm.html#SSM.Client.get_calendar_state より引用


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/6fc86d09-affc-cf14-56f3-e139dd02a7ca.png)


最終的なフローは以下の通りです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/df4f100a-b023-0255-93af-e4f5584ebe65.png)


# メンテナンスウィンドウの設定

このRDSの停止処理は定期的に実行することになるため、Maintenance Windowを設定します。

日次で午前00:05に起動するようにします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/d409e7bc-4f5b-41a5-f4bb-3654bcfedba8.png)

次にメンテナンスウィンドウのターゲットを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/0e372e59-f94c-1d06-0301-564f01799294.png)

`リソースグループを選択` を押下し、先ほど作成したリソースグループを指定します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/79e09505-9408-e0f3-a78a-224b58d733f0.png)

次に、すでに作成しているオートメーションを作成したMaintenance Windowに登録します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/4a563c71-222c-87c7-c956-6cae3889b3d9.png)

作成したオートメーションの名前を入力し、検索すると、先ほど作成した `stop-rds-instance` が検索結果として表示されるので、これを選択し、必要なパラメータを入力します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/3e5303d2-9ba5-532a-de9b-48f7103af837.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/eb9cf207-c0ce-3ab1-7db2-112eb684af0b.png)

以下のようにタスクがMaintenance Windowに紐づいていればOKです。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/54dc6cd3-e75e-ac1c-df8a-70be9cc08e42.png)

# 停止処理の確認

設定が完了し、処理の成功とRDSが停止していることを確認しました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/22533ca7-9c1f-29b4-6ab1-b43a2d8a61bc.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/3fd7c4ab-f5f7-0a18-4f27-90b4935273c2.png)

# 起動

これで土日祝はDBが停止するようになりましたが、平日になった時に自動で起動する処理が必要です。
ただ、起動の処理も今回利用したオートメーションが用意されていますので、上述した内容に沿って設定を行うことで、起動も自動化することが可能です。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/154482/b1a9ba0a-41aa-a93e-8034-9f35926fbad8.png)

# 最後に

今回は1行もコードを書くことなく、リソースの自動起動・停止の処理を検証することができました。一方で、ローコードはITの知識が浅い人でも使いやすいということが謳われている場面もありますが、今回のケースはAWSの基本的な知識（IAM）やITスキルが一定程度ないと厳しいなと感じます。

今回はどのように動かすことができるのかを確認することが目的だったため、検証環境のRDSに適用する場合はもう少し検証や設計を行いたいと考えています。

これからも引き続き、AWSの新しいサービスに注目しながら触っていきたいと思います。

21日は @uhey22e さんの「[スクワットが浅いと怒られる](https://qiita.com/uhey22e/items/34e1f70bd30cc95b5ebd)」です。

# 参考

- [Automatically stop and start an Amazon RDS DB instance using AWS Systems Manager Maintenance Windows](https://docs.aws.amazon.com/prescriptive-guidance/latest/patterns/automatically-stop-and-start-an-amazon-rds-db-instance-using-aws-systems-manager-maintenance-windows.html)