概要
前回に引き続きAWS関連の投稿になります。
前回はAppRunner (+Java + Micronaut) + CloudWatchの連携をしましたが、今回はECSのFargateタスクの連携を行います。
そんなわけで
今回の内容は以下にpushしてます。
今回も、Java側の内容は特には触れません。
ただMicronautはサーバーもバッチ処理も同じ感じで作れるので便利ですね。
ECS 側の設定
今回は、ECSのFargateを使ってのタスク処理を想定してるので、その設定を行います。
resource "aws_iam_role" "ecs_task_execution_role" { name = "ecsTaskExecutionRole" assume_role_policy = jsonencode({ Version = "2012-10-17", Statement = [ { Effect = "Allow", Principal = { Service = "ecs-tasks.amazonaws.com" }, Action = "sts:AssumeRole" } ] }) } resource "aws_iam_role_policy_attachment" "ecs_task_execution_role_policy" { role = aws_iam_role.ecs_task_execution_role.name policy_arn = "arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy" } resource "aws_iam_role_policy_attachment" "ecs_task_logging" { role = aws_iam_role.ecs_task_execution_role.name policy_arn = aws_iam_policy.cloudwatch_logs_policy.arn } resource "aws_ecs_cluster" "my_batch_cluster" { name = "my-batch-cluster" } resource "aws_ecs_task_definition" "my_batch_task" { family = "my-batch-task" network_mode = "awsvpc" requires_compatibilities = ["FARGATE"] cpu = "256" memory = "512" execution_role_arn = aws_iam_role.ecs_task_execution_role.arn task_role_arn = aws_iam_role.ecs_task_execution_role.arn container_definitions = jsonencode([ { name = "my-batch-container" image = "${aws_ecr_repository.apprun-ecr-repository.repository_url}:latest" essential = true command = ["cli", "hello"] logConfiguration = { logDriver = "awslogs" options = { awslogs-group = aws_cloudwatch_log_group.ecs_log_group.name awslogs-region = data.aws_region.current.name awslogs-stream-prefix = "ecs" } } } ]) }
今回、DockerのイメージはAppRunnerと同じものを指定しており、コマンドを command = ["cli", "hello"] みたいにオーバーライドすることでタスク処理として対応するようにしてます。
もちろんそれぞれでDockerのイメージを作成するので問題ないです(むしろそっちが普通のやり方でしょうね)
AppRunnerから呼び出すための設定
AppRunnerからECSのタスクを呼び出すにはそれ相応の権限が必要なので、それも追加します。
# ECSタスクを実行するためのIAMポリシー resource "aws_iam_policy" "ecs_run_task_policy" { name = "AppRunnerECSRunTaskAccess" description = "Allows AppRunner to run ECS tasks" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = [ "ecs:RunTask", "ecs:DescribeTasks", "ecs:ListTasks", "ecs:StopTask", "ecs:DescribeTaskDefinition" ] Resource = "arn:aws:ecs:${data.aws_region.current.name}:${data.aws_caller_identity.current.account_id}:task-definition/*" // 必要に応じてリソースARNを修正 } ] }) } # AppRunnerがECSタスク実行ロールをパスするためのIAMポリシー resource "aws_iam_policy" "pass_role_policy" { name = "AppRunnerPassRolePolicy" description = "Allows AppRunner to pass the ECS task execution role" policy = jsonencode({ Version = "2012-10-17" Statement = [ { Effect = "Allow" Action = "iam:PassRole" Resource = aws_iam_role.ecs_task_execution_role.arn } ] }) } resource "aws_iam_role_policy_attachment" "pass_role_policy_attachment" { role = aws_iam_role.apprunner_role.name policy_arn = aws_iam_policy.pass_role_policy.arn } resource "aws_iam_role_policy_attachment" "apprunner_ecs_run_task_policy_attachment" { role = aws_iam_role.apprunner_role.name policy_arn = aws_iam_policy.ecs_run_task_policy.arn }
こちら補足すると、こちらの ecs_run_task_policy はAppRunnerがECSのタスクを実行するために必要となる権限セットになります。
一方で、 pass_role_policy は、実行するタスクに特定のロールを付与するために必要な権限です。
あとはデプロイしてAppRunnerの特定のエンドポイントを呼び出せば、ECSのタスクが実行されるようになります。
補足:ECSのジョブ終了に関して
ECSのタスクは、基本的にはDockerが終了のシグナルを遅れば終了するはずなのですが、そのシグナルが何故かずっと送られないという自体がこの作成中に発生しました。 (Micronautを使ってるからなのかな)
その場合は、明示的にexitをコード上から呼び出してあげることでちゃんと終了するようです。






