blog.dopana

Back

バックアップ、メール送信、データ処理などの定期的なタスクを自動化する必要がありますか?AWS LambdaとCloudWatch Events/EventBridgeの組み合わせは、従来のcronジョブを置き換えるのに最適なサーバーレスソリューションです。このガイドでは、本番環境向けの定期ジョブをTypeScript/Node.jsで実装する方法に焦点を当てます。

Lambda定期ジョブの概要#

AWS Lambdaは、サーバーを管理せずにコードを実行できるサーバーレスコンピューティングサービスです。スケジューリングサービスと組み合わせることで、以下のことが可能になります:

  • タスクの自動化: バックアップ、レポート生成、データクリーンアップ
  • コスト削減: コード実行時のみ支払う
  • 自動スケーリング: 設定なしで負荷増加に対応
  • 高可用性: AWSが可用性を保証

[!NOTE] AWSは現在、新しい定期ジョブには従来のCloudWatch EventsではなくEventBridge Schedulerの使用を推奨しています。

flowchart LR
    subgraph Scheduler["トリガーサービス"]
        direction TB
        EBS["EventBridge Scheduler<br/>(タイムゾーン / 再試行 / 柔軟なウィンドウ)"]
        CWE["CloudWatch Events<br/>(従来のCron)"]
    end

    subgraph Serverless["サーバーレス実行基盤"]
        Lambda["AWS Lambda Function<br/>(Node.js / TypeScript)"]
        DLQ["Dead Letter Queue (SQS)<br/>(失敗時のイベント退避)"]
    end

    subgraph Targets["対象リソースと監視"]
        DB[(データベース / S3)]
        Log["CloudWatch Logs / アラーム"]
    end

    EBS -->|定期実行呼び出し| Lambda
    CWE -.->|標準呼び出し| Lambda
    Lambda -.->|実行失敗 / 再試行上限| DLQ
    Lambda -->|データ読み書き| DB
    Lambda -->|ログ・メトリクス送信| Log

EventBridge Schedulerは、CloudWatch Eventsと比較して機能が強化された最新のスケジューリングサービスです。

EventBridge Schedulerの利点#

  • タイムゾーンサポート: UTCのみに制限されない
  • 柔軟な時間ウィンドウ: 柔軟な時間範囲内で実行可能
  • 組み込み再試行: 失敗時の自動再試行
  • ワンタイムスケジュール: 単一実行のサポート
  • デッドレターキュー: より良いエラーハンドリング

ステップ1: TypeScript Lambda関数の作成#

ステップ2: IAMロールの作成#

Lambdaはジョブ実行とログ書き込みの権限が必要です:

trust-policy.json
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "lambda.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
json

ポリシー権限:

ステップ3: EventBridge Schedulerでスケジュール作成#

AWSコンソールを使用#

  1. EventBridge Schedulerコンソールに移動
  2. スケジュールの作成をクリック
  3. 定期スケジュールを選択
  4. スケジュール式を設定:
# 毎日9:00 AM UTCで実行
cron(0 9 * * ? *)

# 15分ごとに実行
rate(15 minutes)

# 毎週月曜日9:00 AMで実行
cron(0 9 ? * MON *)

# 毎月1日に実行
cron(0 0 1 * ? *)
bash
  1. Lambda関数をターゲットとして選択
  2. タイムゾーンを設定(必要な場合):
# 9:00 AM Eastern Time
cron(0 9 ? * MON *)
timezone: America/New_York
bash
  1. 柔軟な時間ウィンドウを設定(オプション):
# スケジュール時刻から15分以内に実行
mode: FLEXIBLE
maximum_window_in_minutes: 15
bash
  1. 再試行ポリシーを設定:
maximum_retry_attempts: 3
maximum_event_age_in_seconds: 3600
bash

AWS CLIを使用#

aws scheduler create-schedule \
  --name daily-job \
  --schedule-expression 'cron(0 9 * * ? *)' \
  --schedule-expression-timezone 'UTC' \
  --target '{
    "Arn": "arn:aws:lambda:us-east-1:123456789012:function:my-function",
    "RoleArn": "arn:aws:iam::123456789012:role/scheduler-role"
  }' \
  --flexible-time-window '{
    "Mode": "FLEXIBLE",
    "MaximumWindowInMinutes": 15
  }'
bash

Terraformを使用#

方法2: CloudWatch Events(従来)#

CloudWatch Eventsは従来の方法で、まだサポートされていますが機能は少ないです。

ステップ1: Lambda関数の作成#

Schedulerメソッドと同じ。

ステップ2: CloudWatchルールの作成#

AWSコンソールを使用#

  1. CloudWatchコンソールに移動
  2. Events → Rulesを選択
  3. ルールの作成をクリック
  4. スケジュール式を選択
  5. cron式を入力:
# 毎日9:00 AM UTC
0 9 * * ? *

# 5分ごと
rate(5 minutes)
bash
  1. Lambda関数をターゲットとして選択
  2. 権限を設定(AWSが自動作成)

AWS CLIを使用#

Cron式ガイド#

EventBridgeは6フィールドのcron式を使用します:

cron(分 時 日-月 月 曜-日 年)
text

Cron式の例#

フィールド値#

フィールド特殊文字
0-59, - * /
0-23, - * /
日-月1-31, L, W, - * / ? L W
1-12, JAN-DEC, - * /
曜-日1-7, SUN-SAT, ?, L, #, - * / ? L #
1970-2199, - * /

[!WARNING] 日-月または曜-日が制限されている場合は?を使用し、両方のフィールドを同時に使用しないでください。

ベストプラクティス#

1. 冪等性#

安全な再試行のためにハンドラーが冪等であることを確認:

2. デッドレターキュー(DLQ)#

失敗した呼び出しを処理するためにDLQを設定:

3. 重複実行の防止#

DynamoDBロックで重複実行を防止:

4. モニタリングとログ#

CloudWatch LogsとMetricsを使用:

5. エラーハンドリング#

エラーを適切に処理:

比較: EventBridge Scheduler vs CloudWatch Events#

機能EventBridge SchedulerCloudWatch Events
スケジュールタイプcron + rate + one-timecron + rate
タイムゾーンサポート✅ 任意のタイムゾーン❌ UTCのみ
柔軟なウィンドウ✅ あり❌ なし
組み込み再試行✅ あり❌ なし(DLQが必要)
コスト$1.00/M呼び出し無料(最初の5M/月)
ユースケース本番ジョブ単純な定期ジョブ

実践例: 毎日のデータベースクリーンアップ#

EventBridge Schedulerでスケジュール:

# 毎日2:00 AM UTCで実行
cron(0 2 * * ? *)
bash

トラブルシューティング#

ジョブが実行されない#

  1. スケジュール式を確認: cron構文が正しいか確認
  2. IAM権限を確認: Lambdaに必要な権限があるか確認
  3. CloudWatch Logsを確認: エラーメッセージを探す
  4. ターゲットARNを確認: Lambda関数ARNが正しいか確認

ジョブは実行されるが失敗する#

  1. CloudWatch Logsを確認: エラーメッセージを探す
  2. タイムアウトを確認: Lambdaがタイムアウトしている可能性
  3. リソース権限を確認: データベース、S3等のアクセス権
  4. ローカルでテスト: Lambdaをローカルで実行してデバッグ

重複実行#

  1. ロックメカニズムを実装: DynamoDBまたはRedisを使用
  2. 予約同時実行数を使用: 同時実行数を制限
  3. 冪等性を追加: ハンドラーが冪等であることを確認

リソースのクリーンアップ#

不要になったらリソースをクリーンアップ:

# スケジュール削除
aws scheduler delete-schedule --name daily-job

# CloudWatchルール削除
aws events delete-rule --name daily-lambda-rule

# Lambda関数削除
aws lambda delete-function --function-name my-function

# IAMロール削除
aws iam delete-role --role-name scheduler-role
bash

結論#

AWS LambdaとEventBridge Scheduler/CloudWatch Eventsの組み合わせは、定期ジョブの強力なソリューションを提供します:

  • EventBridge Scheduler: タイムゾーンサポート、再試行、柔軟なウィンドウを持つ本番ジョブ向け
  • CloudWatch Events: コスト効率の良い単純な定期ジョブ向け

主要なポイント:

  1. 本番にはEventBridge Schedulerを使用
  2. 冪等性とエラーハンドリングを実装
  3. CloudWatchでモニタリングを設定
  4. 失敗した呼び出しにはDLQを使用
  5. 重複実行を防止

参考文献#