kakakakakku blog

Weekly Tech Blog: Keep on Learning!

EventBridge Scheduler から ECS Task を実行する構成を Terraform で構築する

Amazon EventBridge Scheduler から Amazon ECS Task を定期的に実行する構成を Terraform で構築する機会があったのでまとめておく❗️Amazon EventBridge Scheduler とても便利 \( 'ω')/

tf ファイル

最初に完成形の tf ファイルを載せておく❗️今回は Amazon EventBridge Scheduler にフォーカスするために Amazon VPC 関連(サブネットやセキュリティグループなど)と Amazon ECS Task 関連は準備できている前提として値をベタ書きしている.実際に組み込むときには変数などに置き換えてもらえればと👌 スケジューリングもドキュメントに載っている cron サンプルを使った.

ちなみに Amazon ECS Task Definition では hello-world image を動かすように作ってある🎲

data "aws_iam_policy_document" "scheduler_permissions" {
  version = "2012-10-17"
  statement {
    actions = [
      "ecs:RunTask"
    ]
    resources = [
      "arn:aws:ecs:ap-northeast-1:000000000000:task-definition/hello-world:*",
      "arn:aws:ecs:ap-northeast-1:000000000000:task-definition/hello-world"
    ]
  }
  statement {
    actions = [
      "iam:PassRole"
    ]
    resources = ["*"]
    condition {
      test     = "StringLike"
      variable = "iam:PassedToService"
      values   = ["ecs-tasks.amazonaws.com"]
    }
  }
}

data "aws_iam_policy_document" "scheduler_assume" {
  statement {
    effect = "Allow"
    principals {
      type = "Service"
      identifiers = [
        "scheduler.amazonaws.com",
      ]
    }
    actions = [
      "sts:AssumeRole",
    ]
    condition {
      test     = "StringEquals"
      variable = "aws:SourceAccount"
      values   = ["000000000000"]
    }
  }
}

resource "aws_iam_role" "scheduler_role" {
  name = "scheduler-execution-role"
  inline_policy {
    name   = "permissions"
    policy = data.aws_iam_policy_document.scheduler_permissions.json
  }
  assume_role_policy = data.aws_iam_policy_document.scheduler_assume.json
}

resource "aws_scheduler_schedule" "eventbridge_scheduler" {
  name = "scheduler"

  flexible_time_window {
    mode = "OFF"
  }

  schedule_expression          = "cron(0/10 * ? * MON-FRI *)"
  schedule_expression_timezone = "Asia/Tokyo"

  target {
    arn      = "arn:aws:ecs:ap-northeast-1:000000000000:cluster/cluster"
    role_arn = aws_iam_role.scheduler_role.arn

    ecs_parameters {
      task_definition_arn = "arn:aws:ecs:ap-northeast-1:000000000000:task-definition/hello-world:1"
      launch_type         = "FARGATE"
      platform_version    = "LATEST"
      network_configuration {
        subnets          = ["subnet-xxxxxxxxxxxxxxxxx", "subnet-xxxxxxxxxxxxxxxxx"]
        security_groups  = ["sg-xxxxxxxxxxxxxxxxx"]
      }
    }
  }
}

アーキテクチャ図

ポイント1 : IAM Role(実行ロール)

Amazon EventBridge Scheduler の IAM Role は Amazon EventBridge Scheduler をコンソールで設定するときに自動的に作られる IAM Role Amazon_EventBridge_Scheduler_ECS_xxxxxxxxxx を参考にした.ecs:RunTaskiam:PassRole は最低限必要で,あとはリソースや条件を細かく指定しておけば OK👌 最終的に作られるポリシーは以下のようになる❗️

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": "ecs:RunTask",
            "Effect": "Allow",
            "Resource": [
                "arn:aws:ecs:ap-northeast-1:000000000000:task-definition/hello-world:*",
                "arn:aws:ecs:ap-northeast-1:000000000000:task-definition/hello-world"
            ]
        },
        {
            "Action": "iam:PassRole",
            "Condition": {
                "StringLike": {
                    "iam:PassedToService": "ecs-tasks.amazonaws.com"
                }
            },
            "Effect": "Allow",
            "Resource": "*"
        }
    ]
}

ポイント2 : Amazon EventBridge Scheduler(タイムゾーン)

Amazon EventBridge Scheduler で便利なのは「タイムゾーン」のサポートで,Amazon EventBridge Rules のように UTC に悩むことなく Asia/Tokyo を指定できる✌️

schedule_expression_timezone = "Asia/Tokyo"

ポイント3 : Amazon EventBridge Scheduler(スケジューリング)

スケジューリング設定では cron() で cron 式を使える.

schedule_expression          = "cron(0/10 * ? * MON-FRI *)"

もし規則的な実行をするだけで良いなら rate() を使えばもっとシンプルに書ける❗️

schedule_expression          = "rate(10 minutes)"

docs.aws.amazon.com

ポイント4 : Amazon EventBridge Scheduler(フレックスタイムウィンドウ)

デフォルトではオフだけど,フレックスタイムウィンドウを設定すると開始時刻を「ズラして」フレックスタイムウィンドウ内の "どこかしらで" 実行できる.レート制限があったりする場合に使える❗️

flexible_time_window {
  mode                      = "FLEXIBLE"
  maximum_window_in_minutes = 2
}

ポイント5 : Amazon EventBridge Scheduler(Amazon ECS RunTask API)

Amazon EventBridge Scheduler のターゲットとして Amazon ECS RunTask API を実行する場合は ecs_parameters ブロックで詳細な設定をする.今回は主に以下を設定した.設定できる項目の一覧は Terraform Registry のドキュメントに載っている📝

  • task_definition_arn(ECS Task Definition の ARN)
  • launch_type(起動タイプを EC2 / FARGATE / EXTERNAL から選ぶ)
  • platform_version(Fargate プラットフォームバージョンを LATEST1.4.0 のように設定する)
  • network_configuration(サブネット・セキュリティグループ・パブリック IP を設定する)

registry.terraform.io

関連記事

AWS EventBridge Terraform module を使って構築するなら以下の記事も読んでもらえればと💡

kakakakakku.hatenablog.com