【AWSコスト削減】ECSやRDSを業務時間内だけ稼働させるとっても簡単な方法

# はじめに
弊社では、案件が始まるとAWSアカウントを3つ作成し、それぞれのアカウントで、社内検証用のdev環境・クライアントチェック用のstage環境・本番用のprod環境を構築する運用としています。
その中で、AWSからの請求額が高く、コストを抑える必要性が出てきています。

# サーバーってずっと稼働させる必要ないよね？
dev環境・stage環境のECSサービスのタスクやRDSインスタンスに関しては、本番運用で使うものではないので、夜中に稼働させる必要はありません。
業務時間内のみ稼働させるように仕組み化する事で、コスト削減が可能です。

# 方法

Step FunctionsとEventBridge Schedulerを使うことで簡単に実現できます。
私は普段CDKでインフラの構成を書くのですが、今回IaCを使ったことがない方でも設定できるよう、AWS管理画面から設定する方法について記載しようと思います。

# ECSのタスクを増やす

まずは、「朝の8:00にECSのタスク数を増やす場合」について説明します。


## Step Functions
- Step Functionsのページを開き、作成を押下します
![スクリーンショット 2024-10-07 16.19.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/2736447a-e857-2bcc-a04f-894b2e493701.png)

- 「{}コード」をクリックし、以下を記述し、作成を押下します
```
{
  "Comment": "ECSのサービスタスク数を増やす",
  "StartAt": "UpdateService",
  "States": {
    "UpdateService": {
      "Comment": "ECSのサービスタスク数を増やす",
      "Type": "Task",
      "Parameters": {
        "Cluster": "{{ECSクラスター名}}",
        "Service": "{{ECSサービス名}}",
        "DesiredCount": {{増やしたいタスク数}}
      },
      "Resource": "arn:aws:states:::aws-sdk:ecs:updateService",
      "End": true
    }
  }
}
```

![スクリーンショット 2024-10-07 16.24.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/3e39ee9b-e665-240e-cb71-2e7dbfd6d8f4.png)

- ロールの設定を表示を押下します

![スクリーンショット 2024-10-07 16.25.22.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/6478949b-9c29-ac67-552c-bf546f3fd33c.png)

- ステートマシン名の入力
ここで、ステートマシン名を入力します。Step Functions内で管理したい名前を入力してください。
また、実行ロールは、新しいロールを作成、という形にしましょう。
入力・選択が終われば次へ進んでください。

![スクリーンショット 2024-10-07 16.26.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/030c3ab0-c0f8-e582-0ffa-8a0182b9ed75.png)

- またまたロールの作成を確認、のダイアログが出ますが、そのまま確認を押下します

![スクリーンショット 2024-10-07 16.27.46.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/53990290-63f4-d25b-44cb-9aa80f727aa3.png)

まだIAMの権限が足りていませんが、ひとまずStep Functionsのステートマシンの作成が完了です。
![スクリーンショット 2024-10-07 16.28.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/5fbdd9dd-30ef-d86b-0d97-9ed603c1a836.png)

- IAM権限を追加するため、インラインポリシーを作成を選択します
私が作業した時はポリシーを作成してからアタッチしましたが、今回手順を少し簡単にするため、インラインポリシーを作成、という形にします

![スクリーンショット 2024-10-07 16.29.53.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/0aae7ee4-9245-74f4-4e34-40f4c2b4640b.png)


- ポリシーを作成します
![スクリーンショット 2024-10-07 16.32.12.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/ef9b34a8-bbc3-4429-bb99-28f235fa4bfb.png)

- IAMポリシーとして以下記述してください
最低限必要なポリシーを付与します。
```
{
  "Version": "2012-10-17",
  "Statement": [
	{
	  "Effect": "Allow",
	  "Action": "ecs:UpdateService",
	  "Resource": "{{ECSのARN}}"
	}
  ]
}

```

![スクリーンショット 2024-10-07 16.34.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/52269e38-666e-636e-9d6c-f73b28888a10.png)
![スクリーンショット 2024-10-07 16.34.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/5162dbd3-f1f0-58de-1bf0-01078c927301.png)


## EventBridge Scheduler
- Step Functionsの作成したステートマシンを選択し、EventBridgeルールを作成を押下します
![スクリーンショット 2024-10-07 16.35.42.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/61ea7d54-d527-f399-94d3-5b3efc47e792.png)

- スケジュールを選択すると、「EventBridge Schedulerで続行」のボタンが出るので押下します
![スクリーンショット 2024-10-07 16.36.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/7930da6c-23c2-fcdd-e083-20cbacaa3859.png)

- 遷移したページをスクロールします
![スクリーンショット 2024-10-07 16.36.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/ed2adee2-4bd4-1d9c-c1c4-596f9bee4bcb.png)

- 定期的なスケジュールを選択し、cron式を記述します
一旦8:00にしました。10:00とかでも良いかもしれません。
![スクリーンショット 2024-10-07 16.37.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/6ad8270b-007c-b7c7-042d-d71f83c4a571.png)

- フレックスタイムウィンドウはオフにし、次へを押下します
![スクリーンショット 2024-10-07 16.37.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/e37d337c-fd0a-15bf-f39f-63e1e86dd573.png)

- AWS Step FunctionsのStartExecutionを選択します
![スクリーンショット 2024-10-07 16.38.08.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/d2efed19-1a0f-7df2-cd1c-d6342326e96e.png)

- ステートマシン欄で、先ほど作成したステートマシンを選択し、次へを押下します
![スクリーンショット 2024-10-07 16.38.38.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/a31fb68f-55ac-0a57-3e1e-ab9f57c36a29.png)

- スケジュール完了後のアクションはNONEに設定し、再試行回数は1timesにします
![スクリーンショット 2024-10-07 16.40.30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/1399b11f-a7f0-089b-5688-4822cbf24f61.png)

- 実行ロールとしては新しいロールを作成し、次へを押下します
![スクリーンショット 2024-10-07 16.40.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/462fca07-d209-4cc6-b00f-1be627d22e57.png)

- 最後に、スケジュールを作成を押下します
![スクリーンショット 2024-10-07 16.40.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730383/5de5743f-1607-10f6-6249-a5df1cd63e10.png)


# ECSのタスク数を0にする

指定時刻にECSのタスク数を増やす場合と同じ手順です。
設定が異なる部分のみ、以下に記載します。

> - 「{}コード」をクリックし、以下を記述し、作成を押下します
```
{
  "Comment": "ECSのサービスタスク数を減らす",
  "StartAt": "UpdateService",
  "States": {
    "UpdateService": {
      "Comment": "ECSのサービスタスク数を減らす",
      "Type": "Task",
      "Parameters": {
        "Cluster": "{{ECSクラスター名}}",
        "Service": "{{ECSサービス名}}",
        "DesiredCount": 0
      },
      "Resource": "arn:aws:states:::aws-sdk:ecs:updateService",
      "End": true
    }
  }
}
```

> - 定期的なスケジュールを選択し、cron式を記述します

タスク数を0にしたい時刻が21:00だとすると、以下のように設定してください。

```cron (0, 21, *, *, ?, *)```


# RDSのインスタンスを停止する
こちらも同じ手順です。
設定が異なる部分のみ、以下に記載します。

> - 「{}コード」をクリックし、以下を記述し、作成を押下します
```
{
  "Comment": "RDSインスタンスの停止",
  "StartAt": "StopRDSInstance",
  "States": {
    "StopRDSInstance": {
      "Comment": "RDSインスタンスを停止",
      "Resource": "arn:aws:states:::aws-sdk:rds:stopDBInstance",
      "Type": "Task",
      "Parameters": {
        "DbInstanceIdentifier": "{{RDSインスタンスのDB 識別子}}"
      },
      "End": true
    }
  }
}
```

> - IAMポリシーとして以下記述してください
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "rds:StopDBInstance"
      ],
      "Resource": "{{DBインスタンスARN}}"
    }
  ]
}

```


# RDSのインスタンスを起動する
こちらも同じ手順です。
設定が異なる部分のみ、以下に記載します。

> - 「{}コード」をクリックし、以下を記述し、作成を押下します
```
{
  "Comment": "RDSインスタンスの起動",
  "StartAt": "StartRDSInstance",
  "States": {
    "StartRDSInstance": {
      "Comment": "RDSインスタンスを起動",
      "Resource": "arn:aws:states:::aws-sdk:rds:startDBInstance",
      "Type": "Task",
      "Parameters": {
        "DbInstanceIdentifier": "{{RDSインスタンスのDB 識別子}}"
      },
      "End": true
    }
  }
}
```

> - IAMポリシーとして以下記述してください
```
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "rds:StartDBInstance",
      ],
      "Resource": "{{DBインスタンスARN}}"
    }
  ]
}

```

# さいごに
全てのAWSアカウントに対して設定すれば、ちりつもで結構コスト削減できるのでは？？