0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

「EventBridge のタスク」って何のこと?ECS と EventBridge の登場人物を整理する

0
Last updated at Posted at 2026-08-31

はじめに

「ECS のタスクを EventBridge で定期実行したい」

やりたいことは明確なのに、コンソールを開くと手が止まる。EventBridge に「タスク」という項目が見当たらない。あるのは「ルール」と「スケジュール」だ。

それもそのはずで、EventBridge に「タスク」という資源は存在しない。API にもコンソールにもない。それでも人が「EventBridge のタスク」と言うのは、EventBridge から起動される ECS 側のタスクを指しているから。

しかも ECS 側の「タスク」も一枚岩ではない。タスク定義・タスク・サービスの3つが、日常会話では全部「タスク」に圧縮される。

つまり詰まる原因は手順ではなく、登場人物の名前が両サービスでねじれていることにある。

この記事では、両サイドの登場人物を並べて、その言い換えを不要にする。


全体図:往路と復路

まず全体像から。EventBridge と ECS の関係は一方通行ではなく、往復している。

  • 往路:EventBridge が ECS の RunTask API を代理で呼び、タスクを起こす
  • 復路:ECS がタスクの状態変化をイベントとして EventBridge に流す

この2つは独立した仕組みだ。片方だけ使うこともできる。

そして実際、「往路だけ組んで復路を組んでいない」構成はよくある。定時に起動する設定は入れたが、その結果を見る設定は入れていない、という状態。

👉 その構成がどうなるかというと、バッチが黙って死ぬ。定時に起動を試みて失敗しても、誰にも何も届かない。なぜそうなるかは第7節で回収する。


ECS 側の登場人物

ECS 側には4つ。

何か
クラスター タスクを動かす場所の論理的なまとまり
タスク定義 何をどう動かすかの設計図
タスク 設計図から起こされた実行中の実体
サービス 指定した数のタスクを維持し続ける常駐管理者

タスク定義はイミュータブルで、登録するたびリビジョン番号が増えていく。webserver:5 は、ファミリ名 webserver とリビジョン 5 の組み合わせ。番号を省略すると最新の ACTIVE リビジョンが使われる。

タスク定義とタスクは同じもの — 設計図と実体の関係。タスク定義そのものは何も動かさない。1つのタスク定義から何個でもタスクを起こせる。

サービスは「タスクを3つ動かし続けろ」と指示しておくと、落ちたぶんを立て直し続ける常駐の管理者。Web サーバーのような常駐プロセス向けの仕組みだ。

サービスがないとタスクは動かないRunTask を呼べば単発でタスクは起きる。サービスは「維持し続ける」役であって、起動の必須条件ではない。むしろバッチはサービスを使わない。1回走って終わるものを「維持」されても困る。

👉 RunTask でタスクを起こすとき、group を省略すると タスク定義のファミリ名が入る。family:<ファミリ名> という形になる。第7節でこのフィールドがまた出てくる。


EventBridge 側の登場人物

EventBridge 側には5つ。

何か
イベントバス イベントが流れてくる通り道
ルール バス上のイベントを条件で拾い、ターゲットに配る仕分け係
イベントパターン ルールが「どのイベントを拾うか」を書いた JSON の条件式
ターゲット ルールが発火したときに呼ぶ相手
スケジュール EventBridge Scheduler が持つ、時刻で発火する独立した資源

ECS は自分の状態変化を、何もしなくても既定のイベントバスへ流している。こちら側でバスに流すための設定は要らない。サービスによっては EventBridge へ流すことを明示的に有効化する必要があるものもあるが、ECS はその必要がない。

ルールはそのバスの上に置く仕分け係。イベントパターンという JSON の条件式にマッチしたイベントを、登録されたターゲットに配る。

スケジュール(EventBridge Scheduler)はバスを経由しない。時刻が来たら直接ターゲットを呼ぶ、独立した資源だ。図でバスと繋がっていないのはそのため。

EventBridge に「タスク」がある — ない。時間で何かを起こしたいなら Scheduler のスケジュール、イベントを拾って何かを起こしたいなら Rules のルール。この2つが「EventBridge のタスク」と呼ばれているものの正体。

ルールが処理を実行している — ルールは仕分けしかしない。実際に処理するのは常にターゲット側のサービス。「ルールを作ったのに動かない」の多くは、ルール自体は正しく発火していて、その後のターゲット呼び出しで失敗している。ルールの発火とターゲットの成功は別々に見る必要がある。


往路:EventBridge が ECS タスクを起こす

ターゲットに ECS を選ぶというのは、「ECS の RunTask API をあなたの代わりに叩く」という設定を書くことである。

だからそこには RunTask に渡すぶんの情報が要る。それが EcsParameters と呼ばれるまとまりで、中身はこうなっている。

  • 使うタスク定義の ARN
  • キャパシティプロバイダ戦略、または起動タイプ(launchType
    • 両方は指定できない。どちらも省くとクラスターの既定戦略が使われる
  • awsvpc ネットワークモード用のネットワーク設定(サブネットとセキュリティグループ)
    • launchTypeFARGATE の場合は必須

👉 EventBridge の設定でサブネットやセキュリティグループを聞かれるのは、EventBridge がネットワークを気にしているからではない。RunTask がそれを要求するから、代理で呼ぶ側が持たされているだけだ。

こうして起動したタスクもサービスが面倒を見てくれる — 見ない。単発の RunTask なのでサービス配下ではない。落ちても再起動されないし、望みの数を維持する仕組みも働かない。「ECS ならサービスが立て直してくれる」という常識はここでは効かない。

ターゲットの設定が通った=タスクが動くRunTask の呼び出しは非同期だ。API が受理されても、そこから先で失敗しうる。イメージが引けない、サブネットに外への経路がない、ロールが足りない。

「呼んだ」「起動した」「正常終了した」は全部別の事実である。 これがこの記事の背骨なので覚えておいてほしい。

👉 では往路の呼び出しが失敗したことはどこで分かるか。ECS 側には何も残らない。タスクが1つも生まれていないのだから当然だ。

EventBridge はターゲット呼び出しの失敗を CloudWatch メトリクスに出し、DLQ(デッドレターキュー)を設定していればそこにイベントを送る。DLQ のメッセージには ERROR_CODE が付き、NO_PERMISSIONSFAILED_TO_ASSUME_ROLE といった値を取る。

しかも権限不足や存在しないターゲットのような「リトライしても無駄なエラー」は、リトライされずに直接 DLQ へ送られる。次の節のロール設定を間違えたとき、最初に見るべき場所はここになる。


3つのロールが出てくる

往路には性格の違うロールが3つ登場する。ここが最大の山だ。

ロール 誰が引き受けるか 何のため
EventBridge のロール(ecsEventsRole EventBridge(events.amazonaws.com あなたの代わりに ecs:RunTask を呼ぶ
タスク実行ロール(ecsTaskExecutionRole ECS / Fargate 基盤(ecs-tasks.amazonaws.com イメージを引く、ログを送る、シークレットを読む
タスクロール タスクの中で動くアプリ(ecs-tasks.amazonaws.com アプリが S3 や DynamoDB を触る

タスク実行ロールとタスクロールは同じもの — 前者はタスクを立ち上げる側の権限、後者は立ち上がった中身が使う権限。切り分けは簡単で、イメージが引けない・ログが出ないなら前者、アプリが AccessDenied を吐くなら後者を疑う。

EventBridge ロール用の AWS 管理ポリシー AmazonEC2ContainerServiceEventsRole の中身は3つしかない。

  • ecs:RunTask
  • iam:PassRole(条件 iam:PassedToServiceecs-tasks.amazonaws.com
  • ecs:TagResource(条件 ecs:CreateActionRunTask

なぜ iam:PassRole が要るのか

EventBridge が RunTask を呼ぶとき、「このタスクにはこのタスク実行ロールとこのタスクロールを付けてくれ」と指定する。

これは自分が使わないロールを他人に渡す行為だ。もし誰でも自由にロールを渡せるなら、RunTask の権限しか持たない人が、管理者権限のタスクロールを指定してタスクを起動できてしまう。だから「そのロールを渡してよいか」が別の権限として切り出されている。それが iam:PassRole

👉 落とし穴はここ。上の管理ポリシーを使わずに自分でポリシーを書くなら、タスク実行ロールとタスクロールそれぞれの ARN を iam:PassRoleResource に並べる必要がある

これが抜けていると、ecs:RunTask は許可されているのにタスクが起動しない、という分かりにくい失敗になる。ECS のコンソールを見てもタスクは1つもいない。前節のとおり、痕跡は EventBridge 側の DLQ の ERROR_CODE に残る。


復路:ECS が EventBridge に流す

ここまでが往路。今度は逆向きの話。

ECS は自分の状態変化を勝手に EventBridge へ流している。そのための設定は要らない。必要なのは、流れてきているものを拾うルールを書くことだけだ。

ECS が送るイベントは8種類ある。

  • Container instance state change
  • Task state change
  • Deployment state change
  • Hook state change
  • Service action
  • Container instance health change
  • Daemon deployment state change
  • Daemon service action

バッチの死活を見たいなら Task state change を拾う。sourceaws.ecsdetail-type"ECS Task State Change"

実物の JSON は 200 行近くあるので、要点だけ抜き出すとこうなる。

{
  "detail-type": "ECS Task State Change",
  "source": "aws.ecs",
  "detail": {
    "clusterArn": "arn:aws:ecs:us-east-1:123456789012:cluster/example-cluster",
    "taskArn": "arn:aws:ecs:us-east-1:123456789012:task/example-cluster/a1173316d40a45dea9",
    "taskDefinitionArn": "arn:aws:ecs:us-east-1:123456789012:task-definition/webserver:5",
    "group": "family:webserver",
    "lastStatus": "RUNNING",
    "desiredStatus": "RUNNING",
    "containers": [
      { "name": "web", "lastStatus": "RUNNING" }
    ]
  }
}

読み方の要点。

  • lastStatus は今の状態、desiredStatus はあるべき状態。この2つが揃うまで、同じタスクについて何度もイベントが飛ぶ。1タスク=1イベントではない
  • groupfamily:webserver なので、group を指定せずに RunTask で起こされたタスクだと分かる(第3節)
  • タスクが停止したときのイベントには stopCodestoppedReason が乗る
  • detail の中の version はリソースの版数で、重複配信されたイベントの見分けに使える。イベント本体側の version は常に 0 なので混同しないこと
  • タスクのヘルスステータスはこのイベントに含まれない。必要なら DescribeTasks を叩く

stopCode に入る値は6つ。

stopCode 意味
TaskFailedToStart 起動そのものに失敗した
EssentialContainerExited essential なコンテナが終了した
UserInitiated 人が StopTask した
ServiceSchedulerInitiated サービスのスケジューラが停止させた
SpotInterruption Fargate Spot が中断された
TerminationNotice 終了通知を受けた

RunTask が成功したからバッチも成功している — 第2節と第5節の伏線がここで回収される。

往路だけを組んだ構成では、次のどれが起きても何も通知されない。

  • TaskFailedToStart で1秒も動かなかった
  • EssentialContainerExited かつ exitCode1 で異常終了した
  • SpotInterruption で処理の途中で消えた

どれも ECS の中では正しくイベントが飛んでいる。拾うルールが無いだけだ。

👉 拾い方の方針としては、ECS Task State ChangelastStatusSTOPPED のものに絞り、そこからさらに stopCodecontainers[].exitCode で異常だけを取り出して SNS などに流す。これで「定時に動いて正常に終わった」以外を検知できるようになる。


なぜ cron が2つあるのか

EventBridge で時刻起動を設定できる場所は2つある。そして片方は AWS 自身が legacy と宣言している

EventBridge ユーザーガイドのスケジュール式ルールのページは、タイトルからして "Creating a scheduled rule (legacy)" であり、本文に "Scheduled rules are a legacy feature of EventBridge." と書かれている。コンソールのナビゲーションでも Scheduler > Scheduled rule (legacy) の位置に格納されている。そして "We recommend that you use Scheduler to invoke targets on a schedule." と明言されている。

両者を並べるとこうなる。

スケジュール式ルール(legacy) EventBridge Scheduler
位置づけ イベントバスの上に載るルール バスから独立した専用サービス
資源の名前 ルール スケジュール
使えるバス 既定のイベントバスのみ バスを使わない
タイムゾーン UTC 固定 任意のタイムゾーンを指定できる
最小粒度 1分 1分
単発実行 できない(rate / cron の繰り返しのみ) できる
実行時刻のばらし なし フレキシブルタイムウィンドウあり
リトライ・DLQ ターゲットごとに設定 スケジュール自体に設定

👉 リトライと DLQ はどちらにもある。既定値も同じ(最大185回 / 最大24時間)。違うのは設定する場所だけで、ルールでは「ターゲットの追加設定」として、Scheduler では「スケジュールの設定」として書く。Scheduler が優れているのはここではなく、タイムゾーン・単発実行・タイムウィンドウ・スケーラビリティの側だ。

なお Scheduler では ECS の RunTasktemplated target として用意されていて、EcsParameters を取る。第5節で書いた内容がそのまま当てはまる。

新規に定期バッチを組むなら Scheduler を選ぶ、が現時点の素直な答えになる。既にスケジュール式ルールで動いているものが明日壊れるわけではないが、新しく増やす積極的な理由は乏しい。

Scheduler は Rules の上位互換だからルールはもう要らない — legacy なのは Rules のスケジュール式の部分だけだ。

イベントパターンで拾うルールは現役であり、S3 にファイルが置かれたら起動する、といったイベント駆動はルールの仕事。Scheduler は時刻でしか発火しない。そして第7節の復路——ECS が流すイベントを拾う——も、ルールでしかできない。


用語対応表

最後に、混同しやすい言い方を一覧で回収しておく。

よく言われる言い方 正確には
EventBridge のタスク Scheduler の「スケジュール」、または Rules の「ルール+ECS ターゲット」
EventBridge で ECS を実行する EventBridge が RunTask を代理で呼ぶ
ECS のタスクを登録する タスク定義を登録する(新しいリビジョンが増える)
タスクを常時起動する サービスを作ってタスク数を維持させる
バッチ用のサービスを作る サービスは要らない。単発の RunTask で足りる
ロールを設定する 3つある。EventBridge のロール / タスク実行ロール / タスクロール
EventBridge の cron スケジュール式ルール(legacy)と EventBridge Scheduler の2つがある。新規は Scheduler

まとめ

  • EventBridge に「タスク」は無い。時刻で起こすなら Scheduler のスケジュール、イベントで起こすなら Rules のルール
  • ECS の「タスク」は3層。タスク定義(設計図)/ タスク(実体)/ サービス(維持係)
  • 往路は EventBridge が RunTask を代理で呼ぶ仕組み。だから EcsParameters が要るし、iam:PassRole が要る
  • 復路は ECS が勝手に流している。拾うルールを書かなければ、失敗は黙って流れていく
  • 「呼んだ」「起動した」「正常終了した」は別の事実。往路だけでは最初のひとつしか保証されない
  • 定期バッチを新しく組むなら EventBridge Scheduler。ただしイベント駆動と復路は今もルールの仕事
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?