AutoScalingのスケジュール【備忘録】

# はじめに
AWSを利用しているとよく使うであろう[アプリケーションの Auto Scaling](https://docs.aws.amazon.com/ja_jp/autoscaling/application/userguide/what-is-application-auto-scaling.html)ですが、スケジュールで増減させる設定を追加したときの備忘録です。
※EC2のAuto Scalingについては触れません。
# 概要
### 対象サービス

|Resource type|Possible values|Describe|
|:-----------|:------------|:------------|
|Amazon ECS サービス|ecs:service:DesiredCount|ECSサービスの希望タスク数|
|スポットフリートリクエスト|ec2:spot-fleet-request:TargetCapacity|スポットフリートのリクエスト数|
|Amazon EMR クラスター|elasticmapreduce:instancegroup:InstanceCount|EMRインスタンスグループのインスタンス数|
|AppStream 2.0 のフリート|appstream:fleet:DesiredCapacity|AppStream 2.0フリートの希望容量|
|DynamoDB テーブルとグローバルセカンダリインデックス|dynamodb:table:ReadCapacityUnits|DynamoDBテーブルのプロビジョニングされた読み取りキャパシティーユニット|
||dynamodb:table:WriteCapacityUnits|DynamoDBテーブルのプロビジョニングされた書き込みキャパシティーユニット|
||dynamodb:index:ReadCapacityUnits|DynamoDBグローバルセカンダリインデックスのプロビジョニングされた読み取りキャパシティーユニット|
||dynamodb:index:WriteCapacityUnits|DynamoDBグローバルセカンダリインデックスのプロビジョニングされた書き込みキャパシティーユニット|
|Aurora レプリカ|rds:cluster:ReadReplicaCount	Aurora|DBクラスター内のAuroraレプリカの数。Aurora MySQL互換版およびAurora PostgreSQL互換版で利用可能|
|Amazon SageMaker|sagemaker:variant:DesiredInstanceCount|Amazon SageMakerモデルのエンドポイントバリアントのEC2インスタンスの数|
|独自のアプリケーションまたはサービスにより提供されるカスタムリソース（[詳細](https://github.com/aws/aws-auto-scaling-custom-resource)）|custom-resource:ResourceType:Property|独自のアプリケーションまたはサービスによって提供されるカスタムリソース用のスケーラブルなディメンション|

### 機能
|Scaling type|API|Describe|
|:-----------|:------------|:------------|
|ターゲット追跡スケーリング|PutScalingPolicy|特定の CloudWatch メトリクスのターゲット値に基づいてリソースをスケーリングします。[TargetTrackingScalingPolicyConfiguration](https://docs.aws.amazon.com/ja_jp/autoscaling/application/APIReference/API_TargetTrackingScalingPolicyConfiguration.html)|
|ステップスケーリング|PutScalingPolicy|超過アラームのサイズによって異なる一連のスケーリング調整値に基づいてリソースをスケーリングします。[StepScalingPolicyConfiguration](https://docs.aws.amazon.com/ja_jp/autoscaling/application/APIReference/API_StepScalingPolicyConfiguration.html)|
|スケジュールスケーリング|[PutScheduledAction](https://docs.aws.amazon.com/ja_jp/autoscaling/application/APIReference/API_PutScheduledAction.html)|日付と時刻に基づいてリソースをスケーリングします。|

# スケジュールによるAuto Scaling
`aws application-autoscaling put-scheduled-action...`にて設定できる。
### パラメータ
設定時に必須のパラメータは下記4つ

* `--service-namespace`
* `--scheduled-action-name`
* `--resource-id`
* `--scalable-dimension`

以下は利用可能なパラメータ

* `--schedule`
* `--start-time`
* `--end-time`
* `--scalable-target-action`
* `--cli-input-json`
* `--generate-cli-skeleton`

[awscliコマンドリファレンス](https://docs.aws.amazon.com/cli/latest/reference/application-autoscaling/put-scheduled-action.html)

### スケジュール設定
スケジュールの設定方式ですが、下記パラメータにて設定していきます。
`--schedule (string)`

|Expression|Format|
|:-----------|:------------|:------------|
|日時指定|at(*yyyy* -*mm* -*dd* T*hh* :*mm* :*ss* )|
|Rate式|rate(*value*  *unit* )|
|Cron式|cron(*fields* )|

e.g.)
**日時指定**

```bash:date&nbsp;schedule
aws application-autoscaling put-scheduled-action --service-namespace ecs --scheduled-action-name ecs-task-run --schedule "at(2019-06-02T18:00:00)" --resource-id service/hoge-cluster/fuga-task --scalable-dimension ecs:service:DesiredCount --scalable-target-action MinCapacity=4
```
**Rate式**

```bash:rate&nbsp;schedule
aws application-autoscaling put-scheduled-action --service-namespace ec2 --scheduled-action-name hourly-spot-request --schedule "rate(1 hour)" --resource-id spot-fleet-request/hogehogefugafuga --scalable-dimension ec2:spot-fleet-request:TargetCapacity --scalable-target-action MinCapacity=2
```
**cron式**

```bash:cron&nbsp;schedule
aws application-autoscaling put-scheduled-action --service-namespace dynamodb --scheduled-action-name my-recurring-action --schedule "cron(30 15 * * ? *)" --resource-id table/HogeTable --scalable-dimension dynamodb:table:ReadCapacityUnits --scalable-target-action MinCapacity=8
```
RateやCronについてはAWS独自の書き方なので[公式](https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html)が一番詳細に書いてあり、わかりやすかったです。

# おしまい
タスクを定期的にスケールアウト/インさせたかったため今回は追加しました。古いコンテナをkillしたかったのですが、思い通りにスケールインしてくれないので原因は調査中です。
### おまけ
こんなスケジュールを追加してみたのですが、上記のとおり落ちないコンテナくんがいるのでふむ…って感じです。

```go:ecs_task.tf
resource "aws_appautoscaling_target" "hogehoge-task" {
  max_capacity       = 10
  min_capacity       = 2
  resource_id        = "service/hogecluster/hogehoge-task"
  role_arn           = "${var.ecs_iam_role}"
  scalable_dimension = "ecs:service:DesiredCount"
  service_namespace  = "ecs"
}

resource "aws_appautoscaling_scheduled_action" "hogehoge-task-out" {
  name               = "hogehoge-task-scale-out"
  service_namespace  = "${aws_appautoscaling_target.hogehoge-task.service_namespace}"
  resource_id        = "${aws_appautoscaling_target.hogehoge-task.resource_id}"
  scalable_dimension = "${aws_appautoscaling_target.hogehoge-task.scalable_dimension}"
  schedule           = "cron(0 * * * ? *)"

  scalable_target_action {
    min_capacity = 4
    max_capacity = 10
  }
}

resource "aws_appautoscaling_scheduled_action" "hogehoge-task-in" {
  name               = "hogehoge-task-scale-in"
  service_namespace  = "${aws_appautoscaling_target.hogehoge-task.service_namespace}"
  resource_id        = "${aws_appautoscaling_target.hogehoge-task.resource_id}"
  scalable_dimension = "${aws_appautoscaling_target.hogehoge-task.scalable_dimension}"
  schedule           = "cron(15 * * * ? *)"

  scalable_target_action {
    min_capacity = 2
    max_capacity = 10
  }
}
```

スケジュールサービスで楽できると思ったんだけどな。。