ECS初回構築時に自動作成されるIAMロール「AWSServiceRoleForECS」とTerraformでの予期せぬ挙動
AWSServiceRoleForECSとは
ECSを作成すると、勝手に作られるIAMロール。Terraformでaws_ecs_cluster
リソースを作ったときにも自動作成される。Service-Linked Rolesというヤツの一種らしい。
公式ドキュメントから、AWSServiceRoleForECSについての説明を引用する。
Amazon Elastic Container Service では、AWS Identity and Access Management (IAM) の「サービスにリンクされたロール」を使用します。
ほとんどの状況では、サービスにリンクされたロールを手動で作成する必要はありません。たとえば、新しいクラスターを作成する (たとえば、Amazon ECS の初回実行、クラスターの作成ウィザード、AWS CLI または SDK) か、AWS マネジメントコンソールでサービスを作成または更新するときに、存在しない場合は Amazon ECS によりサービスにリンクされたロールが作成されます。
すごくざっくり言えば、このIAMロールは「ECSをいい感じに動かしてくれる君」である。
リソース詳細
AWSServiceRoleForECSが具体的にどんな権限を持っているか確認してみよう。アタッチされているIAMポリシーを見てみると、ENIやELB・Route53周りの権限を持っていることが分かる。
$ aws iam get-role --role-name AWSServiceRoleForECS { "Role": { "Description": "Role to enable Amazon ECS to manage your cluster.", "AssumeRolePolicyDocument": { "Version": "2012-10-17", "Statement": [ { "Action": "sts:AssumeRole", "Effect": "Allow", "Principal": { "Service": "ecs.amazonaws.com" } } ] }, "MaxSessionDuration": 3600, "RoleId": "AROAJLAXPZR6O4INQMVBW", "CreateDate": "2018-08-02T00:27:03Z", "RoleName": "AWSServiceRoleForECS", "Path": "/aws-service-role/ecs.amazonaws.com/", "Arn": "arn:aws:iam::123456789012:role/aws-service-role/ecs.amazonaws.com/AWSServiceRoleForECS" } } $ aws iam list-attached-role-policies --role-name AWSServiceRoleForECS { "AttachedPolicies": [ { "PolicyName": "AmazonECSServiceRolePolicy", "PolicyArn": "arn:aws:iam::aws:policy/aws-service-role/AmazonECSServiceRolePolicy" } ] } $ aws iam get-policy --policy-arn arn:aws:iam::aws:policy/aws-service-role/AmazonECSServiceRolePolicy { "Policy": { "PolicyName": "AmazonECSServiceRolePolicy", "Description": "Policy to enable Amazon ECS to manage your cluster.", "CreateDate": "2017-10-14T01:18:58Z", "AttachmentCount": 1, "IsAttachable": true, "PolicyId": "ANPAIVUWKCAI7URU4WUEI", "DefaultVersionId": "v4", "Path": "/aws-service-role/", "Arn": "arn:aws:iam::aws:policy/aws-service-role/AmazonECSServiceRolePolicy", "UpdateDate": "2018-03-22T01:20:59Z" } } $ aws iam get-policy-version --policy-arn arn:aws:iam::aws:policy/aws-service-role/AmazonECSServiceRolePolicy --version-id v4 { "PolicyVersion": { "CreateDate": "2018-03-22T01:20:59Z", "VersionId": "v4", "Document": { "Version": "2012-10-17", "Statement": [ { "Action": [ "ec2:AttachNetworkInterface", "ec2:CreateNetworkInterface", "ec2:CreateNetworkInterfacePermission", "ec2:DeleteNetworkInterface", "ec2:DeleteNetworkInterfacePermission", "ec2:Describe*", "ec2:DetachNetworkInterface", "elasticloadbalancing:DeregisterInstancesFromLoadBalancer", "elasticloadbalancing:DeregisterTargets", "elasticloadbalancing:Describe*", "elasticloadbalancing:RegisterInstancesWithLoadBalancer", "elasticloadbalancing:RegisterTargets", "route53:ChangeResourceRecordSets", "route53:CreateHealthCheck", "route53:DeleteHealthCheck", "route53:Get*", "route53:List*", "route53:UpdateHealthCheck", "servicediscovery:DeregisterInstance", "servicediscovery:Get*", "servicediscovery:List*", "servicediscovery:RegisterInstance", "servicediscovery:UpdateInstanceCustomHealthStatus" ], "Resource": "*", "Effect": "Allow" } ] }, "IsDefaultVersion": true } }
AWSServiceRoleForECSの削除
公式ドキュメントに下記の記載があるとおり、
IAM を使用してサービスにリンクされたロールを削除するには、まずそのロールにアクティブなセッションがないことを確認し、すべての AWS リージョンのすべての Amazon ECS クラスターを削除する必要があります。
ECS Cluster が存在する状態で削除しようとすると、削除に失敗する。実際にやってみるとちゃんとエラーが出た。
AWSServiceRoleForECSのリンクをクリックしてみると、こんな感じ。
「リソースを表示」ボタンをクリックすると、具体的になんのリソースがあるからダメなのか分かる。
ドキュメントの記載通り、ECS Clusterを全部削除すると、このIAMロールも削除できる。
Terraform使用時の予期せぬ挙動
初回のみ発生するエラー
aws_ecs_cluster
リソース作成時にも、AWSServiceRoleForECSは自動作成される。そのため、一見すると、TerraformでECSを構築する場合でも、特に考慮は必要ないように思える。
しかし、実際にはaws_ecs_cluster
と同時にaws_ecs_service
を構築しようとするとエラーが出る。しかも初回のみ。実際に表示されるエラーメッセージは下記のようなものだ。
* aws_ecs_service.ecs: InvalidParameterException: Unable to assume the service linked role. Please verify that the ECS service linked role exists. status code: 400, request id: fd9180b6-9aa6-11e8-bacf-772b1e327bd2 "nginx"
このエラーが出たあと、もう一度 terraform apply
すると、正しくaws_ecs_service
リソースが作成される。つまり、aws_ecs_cluster
リソース作成時に、自動的にAWSServiceRoleForECSが作成されるわけだが、aws_ecs_service
リソースから参照できるようになるまでには、タイムラグがあるということだ。
対処方針
この挙動は、はじめてECSを構築するときに、エンジニアを無駄に戸惑わせる。特にAWS Organizationsなどで、たくさんAWSアカウントを作ると、遭遇率が上がる。
よって、この問題への対処方法としては2つ。
- 初回だけエラーが出るのを無視して、もう一度applyする
- 事前にAWSServiceRoleForECSを作成しておいて、それからECSを構築する
1番については、AWSServiceRoleForECSの挙動を正しく理解している人にとっては問題ないが、当然こんなマニアックな仕様を知っている人はほぼいない。よって、メンドウだが、2番を採用すべきだろう。
TerraformでAWSServiceRoleForECSを作成するのは簡単である。
resource "aws_iam_service_linked_role" "ecs" { aws_service_name = "ecs.amazonaws.com" }
aws_iam_service_linked_roleリソースの詳細は、Terraformのドキュメントを参照してほしい。
まとめ
ECS初回構築時に自動作成されるIAMロール「AWSServiceRoleForECS」について紹介した。ECS Cluster作成時に自動作成されることを説明し、Terraform使用時の予期せぬ挙動と対処法を示した。
非常にマニアックな挙動であり、そもそもこんなことを気にする人はほとんどいないと思うが、見知らぬ誰かの役に立てば幸いだ。