🦖

[AWS]ECS+EventBridgeで最新リビジョンでタスクを実行できるようにするためのTerraformの設定

2022/09/14に公開

Opt Fitエンジニアの@KAZYPinkSaurusです。

先日自分用のメモに書いた記事がそれなりに見てもらえて喜んでいるこの頃です。

https://zenn.dev/optfit/articles/df7b0b84487a41

やりたいこと

今回はAWS ECS+EventBridgeで常に最新リビジョンでタスクを実行できるようにするためのTerraformの設定について書き記します。

背景

これまでAWS Lambdaを用いてバッチ処理しているシステムがありました。
サービスの急成長に伴いバッチの実行時間がLambdaの最大実行時間である15分に近づいてきました。

そこでバッチ処理をECSに移行することにしました[1]

アーキテクチャ

ECSのタスクをEventBridgeから定期実行してもらいます。
ArchitectureFig

実行環境

❯❯❯❯ terraform -v
Terraform v1.1.8
on darwin_amd64
+ provider registry.terraform.io/hashicorp/aws v4.25.0

マシンはM1のMacです。

実装

イベントのルールはaws_cloudwatch_event_ruleリソースを使って作成します。
今回は毎晩深夜2時に定期実行するようにcron記法で設定しました。

タイムゾーンはUTS+0なのでJSTでは9時間前にする必要があります。

スケジュールされたイベントはすべて UTC+0 のタイムゾーンを使用

スケジュールに従って実行する Amazon EventBridge ルールの作成

event_rule.tf
resource "aws_cloudwatch_event_rule" "this" {
  name                = "everyday2am"
  schedule_expression = "cron(0 17 * * ? *)" # JST 2AM
}

次に定期実行する対象の設定をしていきます。
aws_cloudwatch_event_targetリソースで作成します。

TerraformでECSのタスク定義を作成するとついついそのリソースのARNを指定してしまいがちなのですがそれでは最新のリビジョンが常に実行されません。
なぜならタスク定義はリソースごとにリビジョンを持つからです。

これがポイントです。

例えばsample_defというタスク定義であれば

arn:aws:ecs:<region>:<account id>:task-definition/sample_def
# ecs_task_definitionのARNを直接渡すと以下のようになってしまう。
# arn:aws:ecs:<region>:<account id>:task-definition/sample_def:1

を渡します。

assign_public_ipをTrueとする場合はECSの起動タイプの方はタスク定義で指定していたとしてもlaunch_typeをFARGATEと指定しましょう[2]

event_target.tf

resource "aws_cloudwatch_event_target" "this" {
  rule     = aws_cloudwatch_event_rule.this.name # 先程作ったルール
  arn      = var.aws_ecs_cluster_arn
  role_arn = aws_iam_role.eventbridge.arn # 下で作成しているIAM Role
  ecs_target {
    # NOTE: リビジョンなしのARNを指定することで常に最新になる
    task_definition_arn = replace(aws_ecs_task_definition.this.arn, "/:\\d+$/", "") 
    launch_type         = "FARGATE"
    network_configuration {
      subnets          = var.subnet_ids
      security_groups  = var.security_groups
      assign_public_ip = true # 必ずtrueにする必要はない
    }
  }
}

タスクのリビジョンが常に最新になっていることがコンソール上で確認できました。

latest

IAM Role

EventBridgeがECSタスクを実行を実行できるうよなIAM Roleを作っていきます。
権限の制限を間違えるとイベントブリッジが失敗してしまうのでご注意ください。

iam_role.tf
resource "aws_iam_role" "eventbridge" {
  name               = "eventbridge-role"
  assume_role_policy = data.aws_iam_policy_document.assume_role.json

  inline_policy {
    name   = "ecs-task-execution"
    policy = data.aws_iam_policy_document.inline_policy.json
  }
}

data "aws_iam_policy_document" "inline_policy" {
  statement {
    actions   = ["ecs:RunTask"]
    # 実行できるタスク定義を制限
    resources = [replace(aws_ecs_task_definition.this.arn, "/:\\d+$/", "")]
    
    condition {
      test     = "ArnLike"
      variable = "ecs:cluster"
      # タスクを実行するクラスターを制限
      values = [var.aws_ecs_cluster_arn] 
    }
  }
  
  statement {
    actions   = ["iam:PassRole"]
    # PassRoleできるIAM Roleを制限
    resources = [
       var.task_execution_role, # ECSタスクの実行ロール
       var.task_role, # ECSのタスクロール
    ]
    condition {
      test     = "StringLike"
      variable = "iam:PassedToService"
      # PassRoleする先をecsタスクに制限
      values = ["ecs-tasks.amazonaws.com"] 
    }  
  }
}

data "aws_iam_policy_document" "assume_role" {
  statement {
    principals {
      type        = "Service"
      # eventbridgeがこのIAM Roleを使えるようにする
      identifiers = ["events.amazonaws.com"] 
    }
    actions = ["sts:AssumeRole"]
  }
}

Amazon EventBridge でのアイデンティティベースのポリシー (IAM ポリシー) の使用

さいごに

タスク定義のARN指定方法をちょっと変えるだけで最新のリビジョンが常に反映されるようになりました。デプロイが楽になった反面、誤ったタスク定義をデプロイしてしまった際は注意が必要です。

次回はタスク失敗時に再実行するための仕組みをテーマにしたいなと思っています。

それではまた。

🔔採用情報

ジム施設向けDXソリューションGYMDXではエンジニアを積極採用中です。
ジュニア層のエンジニアからリーダー職まで幅広く募集しています。

2022年7月にプレシリーズAラウンドにて資金調達を実施しました。
https://prtimes.jp/main/html/rd/p/000000015.000055404.html

リードエンジニア

https://herp.careers/v1/optfit/GpvSeC-fA995

バックエンドエンジニア

https://herp.careers/v1/optfit/KsDmlZ1VhTmU

脚注
  1. もちろんAWS Batchでもいいんですよ ↩︎

  2. 指定しないと "Assign public IP is not supported for this launch type."というエラーが出ました。明言はされていないがこのエラーはEC2を起動させようとしたときに出るものと同じなのでEC2を指定している扱いになっている可能性がある。または何も指定していないことでこのエラーが出ている可能性がある。ちなみにエラーはCloud Trailから見られます。
    ↩︎

Opt Fit テックブログ

Discussion