Amazon SchedulerからCodeBuildを実行する

AWS CodeBuild

Amazon EventBridge Scheduler から CodeBuild を定期スケジュールで実行する方法の備忘録。AWS のマネジメントコンソールから設定する場合は 公式ドキュメントの Getting started with EventBridge Scheduler を見ながら設定すると良いでしょう。この記事では主に Terraform による構築方法を紹介します。Terraform は 1.7.3、AWS provider は 5.38.0 で動作確認しました。

目次

CodeBuild

aws_codebuild_project を参考に設定します。詳細は省略しますのでリンク先をご確認ください。environment_variable は後で扱うので残してあります。

resource "aws_codebuild_project" "example" {
...
environment {
    ...
    environment_variable {
      name  = "MY_VARIABLE"
      value = "foo"
      type  = "PLAINTEXT"
    }
    ...
  }
...
}

IAM Role

Scheduler から CodeBuild を実行するために IAM Role が必要です。ここは呼び出すサービスによって許可をする Action が異なります。CodeBuild を実行する場合は以下のように IAM Role を作成し、codebuild:StartBuild Action を許可します。

data "aws_caller_identity" "current" {}

resource "aws_iam_role" "scheduler_schedule" {
  name = "my-scheduler-schedule-role"

  assume_role_policy = jsonencode({
    Version = "2012-10-17",
    Statement = [
      {
        Effect = "Allow",
        Principal = {
          Service = "scheduler.amazonaws.com"
        }
        Action = "sts:AssumeRole",
        Condition = {
          StringEquals = {
            "aws:SourceAccount" = data.aws_caller_identity.current.account_id
          }
        }
      },
    ]
  })

  inline_policy {
    name = "CodeBuildStartPolicy"

    policy = jsonencode({
      Version = "2012-10-17",
      Statement = [
        {
          Effect = "Allow",
          Action = [
            "codebuild:StartBuild",
          ],
          Resource = [
            aws_codebuild_project.example.arn
          ]
        },
      ]
    })
  }
}

その他のサービスを呼び出したい場合は Using templated targets - EventBridge Scheduler を参考に設定をします。AWS マネジメントコンソールから作成するとサービスごとに必要な IAM Role を作ってくれるオプションがあるので、まず AWS マネジメントコンソールから IAM Role を作成し、その内容を Terraform に転記しても良いでしょう。

Scheduler

aws_scheduler_schedule を参考に設定します。このあと注目すべきポイントを解説します。

resource "aws_scheduler_schedule_group" "example" {
  name = "my-schedule-group"
}

resource "aws_scheduler_schedule" "example" {
  name       = "my-schedule"
  group_name = aws_scheduler_schedule_group.example.name

  flexible_time_window {
    mode = "OFF"
  }

  schedule_expression_timezone = "Asia/Tokyo"
  schedule_expression          = "cron(0 8 ? * 2-6 *)"

  target {
    arn      = aws_codebuild_project.example.arn
    role_arn = aws_iam_role.scheduler_schedule.arn

    retry_policy {
      maximum_retry_attempts = 0
    }

    input = jsonencode({
      environmentVariablesOverride = [
        {
          name  = "MY_VARIABLE",
          type  = "PLAINTEXT"
          value = "bar",
        },
      ]
    })
  }
}

cron 構文

Schedule types on EventBridge Scheduler | Cron-based schedules を参考に設定します。Linux の crontab とは書式が少し異なることに注意しましょう。

  schedule_expression_timezone = "Asia/Tokyo"
  schedule_expression          = "cron(0 8 ? * 2-6 *)"

target

呼び出したいサービスの ARN と、サービスを呼び出す権限を定義した IAM Role の ARN を設定します。

  target {
    arn      = aws_codebuild_project.example.arn
    role_arn = aws_iam_role.example.arn

target.input

サービスにパラメータを渡したい場合は input に設定をします。以下は CodeBuild に 環境変数を渡すときの例。CodeBuild で設定できるパラメータは AWS CodeBuild API Reference | StartBuild を参照。

  target {
    ...
    input = jsonencode({
      environmentVariablesOverride = [
        {
          name  = "MY_VARIABLE",
          type  = "PLAINTEXT"
          value = "bar",
        },
      ]
    })

その他のサービスで設定ができるパラメータは、Using templated targets - EventBridge Scheduler と、各サービスの API Reference を確認すると良いでしょう。

cron の定義とパラメータが異なる Schedule をいくつか定義したい場合

cron の定義とパラメータだけが異なる Schedule をいくつか定義したい場合は、以下のように for_each を使うとコード量が減ります。

variable "cron_schedules" {
  description = "cron schedule list and parameters"
  type = map(object({
    hour        = number
    minute      = number
    my_variable = string
  }))
  default = {
    "0700" = { hour = 7, minute = 0, my_variable = "foo" },
    "0800" = { hour = 8, minute = 0, my_variable = "bar" },
    "0900" = { hour = 9, minute = 0, my_variable = "baz" },
  }
}

resource "aws_scheduler_schedule" "example" {
  for_each = var.cron_schedules

  name       = each.key
  ...
  schedule_expression          = "cron(${each.value["minute"]} ${each.value["hour"]} ? * 2-6 *)"
  ...
  target {
    ...
    input = jsonencode({
      environmentVariablesOverride = [
        {
          name  = "MY_VARIABLE",
          value = each.value["my_variable"],
          type  = "PLAINTEXT"
        },
      ]
    })
  }
}
  

-技術ブログ
-