こんにちはますのです。
ECSのタスクスケジュール機能、使っていますか??
タスクスケジュール機能を利用して1日1回、バッチを動かす処理をFargateで利用しています。
その際に直面した課題が1つ。
タスク定義を更新したら手動で最新版を設定する必要がある
今回はこちらの課題をクリアするために「EventBridge」を利用しました。
参考:【小ネタ】ECSのタスクスケジュールはEventBridgeから登録するとタスク定義の最新リビジョンから起動できる
やりたいこと
主に今回のやりたいことはこんな感じです。
- コード管理はGithubで実施
- タスク定義の更新は「Github Actions」を利用
- コードが変更されたタイミングでGithubActionsが起動
- ECSの起動はFargate環境で1日1回のみ
- Fargate起動時に最新のタスク定義を必ず展開する
EventBridgeを設定する
手順はAWSの公式ドキュメントを参照
参考:スケジュールされたタスクを作成する
- ターゲットタイプ:AWSのサービス
- ターゲットを選択:ECSタスク
- タスク定義リビジョン:最新
- カウント:(起動する台数)
コンピューティングオプションではFargateを選択します。
- 起動タイプ:Fargate
- プラットフォームのバージョン:(空欄)
– (オプション) Fargate 起動タイプが指定されている場合、Platform version(プラットフォームのバージョン)で、使用するプラットフォームのバージョンを指定します。プラットフォームのバージョンが指定されない場合、LATESTプラットフォームのバージョンが使用されます。11-dより参照:https://docs.aws.amazon.com/ja_jp/AmazonECS/latest/developerguide/scheduled_tasks.html
このあたり、自動で入力されれば嬉しいなぁ…。
IAMロールの作成でハマりました
わたしはIAMロールの設定に気付かず1日調査で潰しました。
自動で作成されるIAMロールの場合、リビジョンが最新のものを実行しようとするとエラーが出ます。
解決方法としては2つあります。
- 既存のロールを使用を選択し「ecsEventsRole」を設定する
- 自動作成のIAMロールを修正する
ざっくりな理解ですが、
ECSの全リソースに対して「ecs:RunTask」の権限を持っているよ。というロールになります。ちなみに、自動作成のIAMロールは「ECSの特定リソースのみ」「ecs:RunTask」の権限を持っていロールです。
権限周りを厳密に管理したい場合は、自動作成されたIAMロールを修正する必要があります。
以降の内容でメモを残します。
自動で作成されるIAMロール(EventBridge_Invole_ECS)の中身
ここから下は私のメモになります。
理解を深めたい方向けとなるので、動かせるようになれば良いという方は「ecsEventsRole」を設定してお試しください。
自動作成されるIAMロールの中身
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:RunTask"
],
"Resource": [
"arn:aws:ecs:*:123456789012:task-definition/task-py-sh:*"
],
"Condition": {
"ArnLike": {
"ecs:cluster": "arn:aws:ecs:*:123456789012:cluster/py-test-cluster"
}
}
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"*"
],
"Condition": {
"StringLike": {
"iam:PassedToService": "ecs-tasks.amazonaws.com"
}
}
}
]
}
何がエラーとなっていたか?
以下の部分の「(タスク定義名):*」にやられました。
"Resource": [
"arn:aws:ecs:*:123456789012:task-definition/task-py-sh:*"
どうやらリビジョン最新の場合は「(タスク定義名):latest」ではなく、「(タスク定義名)」のみとなります。
つまり、「:」が含まれないためアクセス権限が付与されていないのです。
CloudTrailでエラーログを確認する
しっかりbecause no identity-based policy allows the ecs:RunTask action",
というのが出ていますね。
権限足りないからアクセス不可ですよってことらしい。
"eventSource": "ecs.amazonaws.com",
"eventName": "RunTask",
"awsRegion": "(リージョン名)",
"sourceIPAddress": "events.amazonaws.com",
"userAgent": "events.amazonaws.com",
"errorCode": "AccessDenied",
"errorMessage": "User: arn:aws:sts::123456789012:assumed-role/Amazon_EventBridge_Invoke_ECS_123456789/abcdefghijklmn is not authorized to perform: ecs:RunTask on resource: arn:aws:ecs:123456789012:task-definition/(タスク定義名) because no identity-based policy allows the ecs:RunTask action",
自動で作成されるIAMロール(EventBridge_Invole_ECS)を修正する
Resourceタグの「:」を削除します。
こんな感じ。
"Resource": [
"arn:aws:ecs:*:123456789012:task-definition/task-py-sh*"
こうすることでリビジョン指定が無くてもワイルドカードで一致するのでAccessDeniedを避けられます。
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"ecs:RunTask"
],
"Resource": [
"arn:aws:ecs:*:123456789012:task-definition/task-py-sh*"
],
"Condition": {
"ArnLike": {
"ecs:cluster": "arn:aws:ecs:*:123456789012:cluster/py-test-cluster"
}
}
},
{
"Effect": "Allow",
"Action": "iam:PassRole",
"Resource": [
"*"
],
"Condition": {
"StringLike": {
"iam:PassedToService": "ecs-tasks.amazonaws.com"
}
}
}
]
}
設定完了後:ECSクラスター>タスクのスケジュールに追加される
EventBridgeに設定を追加後、下図のようにECSクラスター内「タスクのスケジュール」に追加されます。
タスク定義に記載されているタスク名の後ろにリビジョン「:(数字)」が消えていますね。
これで必ず最新のタスク定義が実行されるようになります。
それともCLIとかで無理やりやらんとダメ?と重い腰でした。
EventBridgeでサクサクっと出来ると知れて良かったです。しかし、簡単じゃん!と思っていたところ、思わぬところで躓きました。
AWSさん改善してくれたら嬉しいなぁと思ったので届けこの思い。
参考資料
AWS builders-flash:サーバーレスのイベントバスって何 ? Amazon EventBridge をグラレコで解説
classmethod:【小ネタ】ECSのタスクスケジュールはEventBridgeから登録するとタスク定義の最新リビジョンから起動できる