CloudformationでECSを構築するときの注意点

172
NO IMAGE

現象

AWSのCloudformationで以下のようにECSのクラスターとサービスを同時に作成しようとしたところ、 "Unable to assume the service linked role. Please verify that the ECS service linked role exists." というエラーが発生した。(※テンプレートの細部は省略)

AWSTemplateFormatVersion: "2010-09-09"
Description: "ECS"
Resources:
  ECSCluster:
      Type: "AWS::ECS::Cluster"
      Properties:
          ClusterName: "TestCluster"
          CapacityProviders:
            - "FARGATE_SPOT"
            - "FARGATE"

  ECSService:
      Type: "AWS::ECS::Service"
      Properties:
          ServiceName: "backend-server"
          Cluster: !GetAtt ECSCluster.Arn
          LoadBalancers:
            -
              TargetGroupArn: !ImportValue target-group
              ContainerName: "server"
              ContainerPort: 8080
          DesiredCount: 1
          LaunchType: "FARGATE"
          PlatformVersion: "LATEST"
          TaskDefinition: !Ref ECSTaskDefinition
          DeploymentConfiguration:
              MaximumPercent: 200
              MinimumHealthyPercent: 100
              DeploymentCircuitBreaker:
                  Enable: false
                  Rollback: false
          NetworkConfiguration:
              AwsvpcConfiguration:
                  AssignPublicIp: "ENABLED"
                  SecurityGroups: ...
                  Subnets: ...
          HealthCheckGracePeriodSeconds: 0
          SchedulingStrategy: "REPLICA"

  ECSTaskDefinition:
      Type: "AWS::ECS::TaskDefinition"
      Properties:
          ContainerDefinitions:

しかもこのエラーは初回のみで、2回目以降は発生しない。また、手動でECSを構築したことがある場合にも発生しない。

原因

Cloudformationのマニュアルを読んでいたら以下のような記述があった。

If your account has already created the Amazon ECS service-linked role, that role is used by default for your service unless you specify a role here. The service-linked role is required if your task definition uses the awsvpc network mode or if the service is configured to use service discovery, an external deployment controller, multiple target groups, or Elastic Inference accelerators in which case you should not specify a role here. For more information, see Using service-linked roles for Amazon ECS in the Amazon Elastic Container Service Developer Guide.

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-resource-ecs-service.html

Under most circumstances, you don't need to manually create the service-linked role. For example, when you create a new cluster (for example, with the Amazon ECS first-run experience, the cluster creation wizard, or the AWS CLI or SDKs), or create or update a service in the AWS Management Console, Amazon ECS creates the service-linked role for you, if it does not already exist.

https://docs.aws.amazon.com/AmazonECS/latest/developerguide/using-service-linked-roles.html#create-service-linked-role

つまり、ECSをいい感じに動作させるための「サービスにリンクされたロール」が必要になるものの、多くの場合はAWSが勝手に作ってくれるのでわざわざ手動で作る必要はない。

しかしCloudformationなど手動作成以外の方法でECSを構築する場合、どうもこれらサービスにリンクされたロールが作成されて利用可能になる前に処理が進んでしまい、エラーとなっているようだ。

解決方法

以下のようなCloudformationを定義して、ECSの構築の前にサービスにリンクされたロールを作成すればよいようだ。

AWSTemplateFormatVersion: "2010-09-09"
Description: "Service linked role"
Resources:
  AWSServiceLinkedRole:
    Type: AWS::IAM::ServiceLinkedRole
    Properties:
      AWSServiceName: ecs.amazonaws.com