blog.dopana

Back

バックアップ、メール送信、データ処理などの定期的なタスクを自動化する必要がありますか?AWS LambdaとCloudWatch Events/EventBridgeの組み合わせは、従来のcronジョブを置き換えるための完璧なサーバーレスソリューションです。

Lambdaスケジュールジョブの概要#

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

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

[!NOTE] AWSは現在、新しいスケジュールジョブに従来のCloudWatch Eventsの代わりにEventBridge Schedulerの使用を推奨しています。

方法1: EventBridge Scheduler(推奨)#

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

EventBridge Schedulerの利点#

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

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

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

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

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

ポリシー権限:

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

AWSコンソールを使用#

  1. EventBridge Schedulerコンソールに移動
  2. Create scheduleをクリック
  3. Recurring scheduleを選択
  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 functionをターゲットとして選択
  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. Create ruleをクリック
  4. Schedule expressionを選択
  5. cron式を入力:
# 毎日9:00 AM UTC
0 9 * * ? *

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

AWS CLIを使用#

Cron式ガイド#

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

cron(Minutes Hours Day-of-month Month Day-of-week Year)
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. 冪等性#

安全な再試行のためにハンドラーを冪等にします:

def lambda_handler(event, context):
    # ジョブが既に実行されたかチェック
    if is_job_already_processed(event):
        logger.info("Job already processed, skipping")
        return {"status": "skipped"}
    
    # ジョブを処理
    result = process_job(event)
    
    # ジョブを処理済みとしてマーク
    mark_job_as_processed(event)
    
    return result
python

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

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

import boto3
import json

sqs = boto3.client('sqs')

def send_to_dlq(error_message, event):
    """失敗したイベントをDLQに送信"""
    sqs.send_message(
        QueueUrl='YOUR_DLQ_URL',
        MessageBody=json.dumps({
            'error': error_message,
            'event': event,
            'timestamp': str(datetime.utcnow())
        })
    )
python

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. 重複実行を防止

参考文献#