CloudFormation でECSEventsを作成すると CloudWatch Events IAM ロールが登録されないっぽい

Fargate 使っててなんだかよくわからん現象に遭遇したので改めて検証してみた次第。
 
何が起こったか
とりあえず箇条書きで。
  • Fargateで起動するECSイベントをCloudFormationで作成
  • しかし、指定時間になっても処理が実行されない
  • CloudWatchLogsを見ると、呼び出しに失敗している様子
  • 登録したECSEventsをManagement Consoleからみると、CloudWatch Events IAMロールが未設定("新しいロールの作成”)のまま
  • ECSEventsの編集ページにて、何も変更せずに更新するとCloudWatch Events IAMロールが(ecsEventsRole)が登録された
  • CloudWatch Events IAMロールが登録されて以降はEventsの実行に成功するようになった
 
検証
  1. ECSクラスタを作成する
  2. 1で作ったECSクラスタにECSEventsを登録するCloudFormationを実行する
  3. 2で作成されたECSEventsが正常に実行されるか確認する
(ちなみに2で登録するECSEventsでは適当にAPIリクエストを発行して取得した結果を標準出力する、というようなコードを適当に用意した。)
 
1
検証用のECSクラスタは流行りの AWS CDK の "aws-ecs-patterns"を使った。これを実行するとVPC, Subnet, ECSクラスタなどが一括して作成される。便利。
import cdk = require("@aws-cdk/core");
import ecs = require("@aws-cdk/aws-ecs");
import ecsPatterns = require("@aws-cdk/aws-ecs-patterns");
 
export class AppEcsVpcStack extends cdk.Stack {
  constructor(scope: cdk.Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);
 
    const cluster = new ecs.Cluster(this, "AppCluster", {
      clusterName: "AppCluster"
    });
  }
}
 
CloudFormationのテンプレートは以下の通り。
Ref`で参照しているところは既に登録済みのリソースIDとかarnをセットしている。
(ところで、CFnに設定する値って、リソースIDの場合とArnの場合があって非常にわかりづらい。ドキュメントにも「〜の値」くらいにしか書いてないし。)
 
Resources:
  CloudWatchEvent:
    Type: AWS::Events::Rule
    Properties:
      Name: rubyapp-event
      Description: run ruby code
      ScheduleExpression: rate(10 minutes)
      State: ENABLED
      Targets:
        - Arn: !Ref ECSClusterArn
          RoleArn: !Ref ECSTaskRoleArn
          Id: rubyapp
          EcsParameters:
            LaunchType: "FARGATE"
            TaskCount: 1
            TaskDefinitionArn: !Ref ECSTaskDefinitionArn
            PlatformVersion: "LATEST"
            NetworkConfiguration:
              AwsVpcConfiguration:
                AssignPublicIp: ENABLED
                SecurityGroups:
                  - !Ref SecurityGroup
                Subnets:
                  - !Ref Subnet
 
3
それでCloudFormationを実行した結果。
 
やっぱり「CloudWatch Events IAMロール」が登録されていない。
この状態で何も変更せずに更新ボタンを押したところ、 `ecsEventsRole`がセットされた。
更新をフックに何も指定されていなければ`ecsEventsRole`をセットするような仕様になっているのかもしれない。 で、CFnの場合はそれが漏れていたって感じではなかろうか。
ecsEventsRoleが登録されて以降はECSEventsは正常終了になりました。
 
(追記)
この件についてAWSサポートに問い合わせた。
 
  • CFnからのECSEvents登録ではCloudWatch IAM ロールは自動作成されない。CFnで登録する場合は CloudWatch IAM ロールもCFnで登録してからRoleArnで指定する
  • CloudWatch IAMロールは CFnの`RoleArn`で登録する(ここは僕の設定値が間違っていた)
Resources:
  CloudWatchEvent:
    Type: AWS::Events::Rule
    Properties:
        ~
      Targets:
        - Arn: !Ref ECSClusterArn
          RoleArn: !Ref ECSTaskRoleArn
 
RoleArn に`ecsEventsRole`のArnを指定したところうまくいった。
 
うーん。
ちょっと悔しい気分なのは、
 
> RoleArn
> ターゲットの呼び出しに使用されるロールの Amazon リソースネーム (ARN)
 
ドキュメントにはこのように記載されているのだけど、
この説明文とconsole上のラベルの「CloudWatch IAM ロール」が同じだとはなかなか気づかないよ。。