EventBridge SchedulerでECSタスクの定期実行（まず動かしたい人向け


https://docs.aws.amazon.com/ja_jp/eventbridge/latest/userguide/scheduler.html

Event Bridge Schedulerを使ってECRからpullしたイメージをECSで定期実行する設定方法をご紹介します
ECS周りの設定は既に済んでるものと仮定しての説明となります点ご了承ください

ECSで実行するアプリケーションはSpring BatchでApplicationRunnerを起動するものとなっております（後述しますが、実行するバッチ種類を指定するためにコンテナに対してパラメータを付与します）
![eventbridge.drawio.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/d52b6896-c3d3-e852-47c4-223376cad504.png)

## 早速設定してみる

### スケジュール名と説明
このあたりは機能に直接影響があるものではないので、わかりやすい識別子を設定して次へ行きます
![スクリーンショット 2023-04-04 9.20.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/053ac190-cfde-d4bc-7a62-1487df2a29b3.png)

### スケジュールのパターン
毎日０時に起動するよう設定していきたいと思います
cron式はUNIX系OSお馴染みのものです！
具体的に設定できる値についてはawsの方でもわかりやすくドキュメント化してくださってるのでこちらを参照
https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html
![スクリーンショット 2023-04-06 9.50.33.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/6b1ffdbd-3f4c-92b9-24f1-6856c4b944b9.png)


### 時間枠
タイムゾーンを設定（デフォルトのまま）して次画面へいきます
![スクリーンショット 2023-04-04 9.21.51.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/643187e5-7f40-20b7-85dd-4e094179390f.png)

### ターゲットの詳細
次画面に遷移すると色々なAWSサービスの色々な操作を選択できる画面が表示されます
今回は既に存在するECSクラスタ、タスク定義を使ってECSタスクを実行する目的なので「RunTask」を選択します
![スクリーンショット 2023-04-04 9.32.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/24eade16-0adf-4e0c-9a26-a3fce2fe4ceb.png)

### RunTask
RunTaskに必要なさまざまな設定をしていきます

ECSクラスターとECSタスク定義をここで選択します
プルダウン展開で選択候補値をだしてくれます
![スクリーンショット 2023-04-04 9.37.52.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/e213f936-0426-9ea8-ed94-3f318bfa8075.png)
コンピューティングオプション選択は注意が必要です
- プラットフォームのバージョン
- サブネット
- セキュリティグループ
はそれぞれ手入力が必要です（*2023/04/04現在）
プラットフォームのバージョンは「LATEST」で良いと思います
他は各サービスメニューからサブネットID、セキュリティグループIDをコピーして貼り付けましょう（他のサービスはこの辺の選択がプルダウンになっているのでそのうち対応されると筆者は思ってます）

また、自動割り当てパブリックIPは「有効」にしてください
しないとこちらのエラーが発生します・・！ [ECRからpullできない？](#-ECRからpullできない？)
![スクリーンショット 2023-04-04 9.38.15.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/6e2f406c-acaf-9a35-6378-52157c5bf732.png)

デフォルトからの変更点は「実行コマンドを有効化」している点です
![スクリーンショット 2023-04-04 9.38.35.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/108674fc-bf84-8c0d-a118-692d86169d0c.png)

今回は起動するバッチの種類をアプリケーションに対して引数で渡したいため、コマンドの上書きを行います
[はまったポイント](#-コマンドの上書き指示でエラー)
```json
{
	"containerOverrides": [
		{
			"name": "batch",
			"command": [
				"--batch.execute=sample"
			]
		}
	]
}
```

![スクリーンショット 2023-04-04 9.38.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/e2feaa51-25d8-24cc-d248-cf6dad1e6914.png)

### スケジュールの状態 / 再試行ポリシーとデッドレターキュー
本タスクは24時間に1度起動なので、イベント最大経過時間はデフォルトのままにしました
再試行回数はデフォルト185回ですが、失敗するパターンとすればプログラムやデータに何らかの考慮不足があるときなので3回程度としました（もちろん機能が違えば失敗するパターンも違ってくるので応じて判断していただければと思います）
![スクリーンショット 2023-04-05 9.39.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/87cdde3a-866a-fec3-c73e-7225596055b5.png)

### 暗号化 / アクセス許可
これらはデフォルトのままとしました
実行ロールについては TODO
![スクリーンショット 2023-04-05 9.40.19.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/976de983-8ba5-cf52-e729-faab9845d6fa.png)

### 設定完了
あとは画面に従って操作を進めれば設定完了です
![スクリーンショット 2023-04-06 9.38.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/09cb5fb3-f4e9-2df4-bf09-7e75496f7304.png)


## まず、起動成功した or エラーってどう見るの
起動できているかどうかの確認は、[CloudTail](https://ap-northeast-1.console.aws.amazon.com/cloudtrail/home?region=ap-northeast-1#/events?EventName=RunTask)から確認できそうです
イベント時刻をみると15分おきにRunTaskが実行されているのが確認できます

![スクリーンショット 2023-04-06 9.46.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/a5d56463-9464-10c6-ae95-a4b4bc97110a.png)

#### エラーの場合
エラーコードの箇所にエラーの種類が表示されます（今回サンプルで示しているケースだと「InvalidParameterException）
![スクリーンショット 2023-04-06 9.53.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/2dabfff3-16c4-b1db-cd7f-629715913895.png)

詳細を確認するには、画面下部のイベントレコードを確認します
InvalidParameterExceptionで検索してみてください
エラーを発生させるために、RunTask > コンピューティングオプション > 起動タイプ を未指定にしてみました
![スクリーンショット 2023-04-06 9.59.11.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/2bd4c62b-cdba-be53-9d24-8379ed457dee.png)

#### 成功の場合
![スクリーンショット 2023-04-07 9.59.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/001670b9-7201-551a-a948-4625c8c3961b.png)


# 設定中はまったこと
## コマンドの上書き指示でエラー
```json
{
	"containerOverrides": [
		{
			"command": [
				"--batch.execute=sample"
			]
		}
	]
}
```
構築初期、調べに調べて捻り出したコマンド上書きの設定値がこちらで、正しいものと比べるとnameが欠落してました
コマンドの上書き指示になにを渡したら良いかが当時参考文献少なく、結構ハマりました
こちらのドキュメントを参照することで何を設定したら良いか、なにが必須なのかがわかりました！
https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/APIReference/API_ContainerOverride.html

実際のエラー情報
![スクリーンショット 2023-04-11 10.37.34.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/efa05fb6-4976-cbc8-36e2-bcffd97e3b1a.png)
```
~~ 略 ~~
    "errorCode": "InvalidParameterException",
    "errorMessage": "name cannot be blank.",
    "requestParameters": {
        "platformVersion": "LATEST",
        "overrides": {
            "containerOverrides": [
                {
                    "command": [
                        "--batch.execute=sample"
                    ]
                }
            ]
        },
~~ 略 ~~
```

## because no identity-based policy allows the ecs:RunTask action
```
"errorMessage": "User: arn:aws:sts::xxx:assumed-role/Amazon_EventBridge_Scheduler_ECS_yyy/zzz is not authorized to perform: ecs:RunTask on resource: arn:aws:ecs:ap-northeast-1:xxx:task-definition/sample-def because no identity-based policy allows the ecs:RunTask action"
```
※ 2023/04/04現在 自動生成の実行ロールを指定している場合はこのエラーは発生しません
本記事では触れてませんが、実運用ではアクセス許可に設定する実行ロールを「既存のロールを使用」して独自で定義したポリシーをアタッチしてました。
また、その実行ロールを複数のスケジュールで共有しておりました。
上記の条件で以下のようなポリシーを定義している場合はエラーが発生しますので注意です

### 悪い例
Resourceに指定するECSタスク定義に「:*」の指定がある
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:RunTask"
            ],
            "Resource": [
                "arn:aws:ecs:ap-northeast-1:xxxx:task-definition/development-batch-def:*"
            ],
            "Condition": {
                "ArnLike": {
                    "ecs:cluster": "arn:aws:ecs:ap-northeast-1:xxxx:cluster/development"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringLike": {
                    "iam:PassedToService": "ecs-tasks.amazonaws.com"
                }
            }
        }
    ]
}
```

### 良い例
Resourceに指定するECSタスク定義ARNに「:*」の指定がない
```json
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ecs:RunTask"
            ],
            "Resource": [
                "arn:aws:ecs:ap-northeast-1:xxxx:task-definition/development-batch-def"
            ],
            "Condition": {
                "ArnLike": {
                    "ecs:cluster": "arn:aws:ecs:ap-northeast-1:xxxx:cluster/development"
                }
            }
        },
        {
            "Effect": "Allow",
            "Action": "iam:PassRole",
            "Resource": [
                "*"
            ],
            "Condition": {
                "StringLike": {
                    "iam:PassedToService": "ecs-tasks.amazonaws.com"
                }
            }
        }
    ]
}
```

実際のエラー情報
![スクリーンショット 2023-04-13 10.01.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/323088/12bc9e5a-53b4-f080-9777-c2c7c80e3d76.png)
```
~~ 略 ~~
    "errorCode": "AccessDenied",
    "errorMessage": "User: arn:aws:sts::894229353696:assumed-role/Amazon_EventBridge_Scheduler_ECS_8840c322a4/xxxx is not authorized to perform: ecs:RunTask on resource: arn:aws:ecs:ap-northeast-1:894229353696:task-definition/development-batch-def because no identity-based policy allows the ecs:RunTask action",
    "requestParameters": null,
    "responseElements": null,
~~ 略 ~~
```