ECSサービスを時間指定でスケーリングする

## 目的
自分向けのメモ書きという感じですが、同じことをしたくて悩んでいる人の一助になれば。

このドキュメントで特定の時間(時間帯)にサービス負荷が上がることが事前にわかっている時にどうやったら手動対応が不要なのか分かるようになります。

## オートスケールじゃダメなの？
前提としてオートスケールではダメなのかというのがあると思います。
結論大丈夫な時とダメな時があります。

オートスケーリングはオートスケーリングの閾値を超えてから実際にスケーリングが始まるまでにタイムラグがあります。

こちらは実際にECSでCPUを60%ターゲット追跡で設定している時のcloudwatch alermの画面です。
閾値のところが「3 分内の3データポイントのCPUUtilization > 60」になっているのでこの場合3分間60%以上で稼働していないとスケールアウトが実行されません。
![スクリーンショット 2023-04-27 16.31.24.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/280595/381fb0e7-1b5f-a144-50d3-bf8e49fa541a.png)
またスケーリングが開始しても増やしていく台数が順次増えていく形なのでリクエストが短時間に過多になる場合はオートスケーリングでは間に合わないことがあります。

--
よくある例として広告を打った直後に一時的にアクセスが短時間で跳ね上がるケースや、特定の時間にアクセスが集中する仕組みになっている(毎日12時に先着キャンペーンが走る。同じ時間に告知が流れるetc)時にはあらかじめtaskの台数を増やすことが必要になります。

## 実際にどうやっていくのか
管理コンソールからは機能がない(多分)のでaws cliから実行する必要があります。
aws cliのインストールや基本的な使い方は他の方の記事をご参照ください。 :pray: 

↓参考でaws cliのインストール手順が書かれている公式ドキュメント

https://docs.aws.amazon.com/ja_jp/cli/latest/userguide/getting-started-install.html

### 時間指定のスケールアウト or スケールインのコマンド
2023-04-30 23:50:00にスケールアウトする設定の例
```bash
$ aws application-autoscaling put-scheduled-action \
--service-namespace ecs \
--resource-id service/{cluster name}/{service name} \
--scheduled-action-name {見分けがつくユニークな名前} \
--schedule "at(2023-04-30T14:50:00)" \
--scalable-dimension ecs:service:DesiredCount \
--scalable-target-action MinCapacity=10,MaxCapacity=20
```

毎日AM11:50にスケールアウトする設定の例
```bash
$ aws application-autoscaling put-scheduled-action \
--service-namespace ecs \
--resource-id service/{cluster name}/{service name} \
--scheduled-action-name {見分けがつくユニークな名前} \
--schedule "cron(50 02 * * ? *)" \
--scalable-dimension ecs:service:DesiredCount \
--scalable-target-action MinCapacity=10,MaxCapacity=20
```
公式ドキュメントはこちら

https://awscli.amazonaws.com/v2/documentation/api/latest/reference/application-autoscaling/put-scheduled-action.html

### ポイント
* スケールアウトするにしてもtaskが起動するのに時間がかかるので、スケールアウトして欲しい時間の数分前から立ち上げるようにしましょう(どれくらい前にしないといけないかは各プロダクトによって変わるので各自ご検討ください)
* 時間はUTCで指定する必要があります。日本の場合は-9時間した時間で指定することが必要です

### 各パラメータの説明
* `--service-namespace` 今回はECSのスケールの話なので `ecs` で固定
* `--scheduled-action-name` このオートスケール設定を変更・削除する時などのキーになるので分かる名前にすると良さそう
* `--schedule` スケールの実行タイミングを指定する。1回のみの時は `at(~~)`。定期実行は `cron(~~)`(cronの細かい書き方は別記事を見ていただければ)
* `--scalable-dimension` スケールの対象を指定するもので `ecs:service:DesiredCount` でOK
* `--scalable-target-action` どうなって欲しいかの値を指定すればOKで上のサンプルでは最小値10、最大値20のスケール設定に変更しています。(数字は適宜変えてもらえれば)


### 設定内容を確認する
```bash
$ aws application-autoscaling describe-scheduled-actions \
--service-namespace ecs
```

現在設定中の値を確認することができます
```bash
{
    "ScheduledActions": [
        {
            "ScheduledActionName": "******",
            "ScheduledActionARN": "arn:aws:autoscaling:ap-northeast-1:******:scheduledAction:******:resource/ecs/service/{cluster_name}/{service_name}:scheduledActionName/{scheduled-action-name}",
            "ServiceNamespace": "ecs",
            "Schedule": "at(2023-04-30T14:50:00)",
            "ResourceId": "service/{cluster_name}/{service_name}",
            "ScalableDimension": "ecs:service:DesiredCount",
            "ScalableTargetAction": {
                "MinCapacity": 10,
                "MaxCapacity": 20
            },
            "CreationTime": "2023-04-27T16:16:49.027000+09:00"
        }
    ]
}
```

## 削除したい場合
```bash
$ aws application-autoscaling delete-scheduled-action \
--service-namespace ecs \
--resource-id service/{cluster_name}/{service_name} \
--scalable-dimension ecs:service:DesiredCount \
--scheduled-action-name {scheduled-action-name}
```



## 参考

https://docs.aws.amazon.com/ja_jp/autoscaling/application/userguide/examples-scheduled-actions.html

https://dev.classmethod.jp/articles/ecs-scheduled-autoscaling/