指定時間に1度だけ実行する Amzon EventBridge Scheduler スケジュールを AWS CDK で作成してみた

2024.02.27

こんにちは、CX 事業本部製造ビジネステクノロジー部の若槻です。

Amazon EventBridge のスケジュール実行に特化した機能である Amazon EventBridge Scheduler では、指定した時間に 1 回だけイベントを発行するスケジュール(One-time schedules)を作成することができます。

今回は、指定時間に 1 度だけ実行する Amzon EventBridge Scheduler スケジュールを AWS CDK で作成してみました。

やってみた

パッケージのインストール

EventBridge Scheduler を CDK で構成するための Alpha バージョンのパッケージをインストールします。

npm i -D @aws-cdk/aws-scheduler-alpha
npm i -D @aws-cdk/aws-scheduler-targets-alpha

CDK コード

AWS CDK(TypeScript)のコードです。ここでは EventBridge Scheduler を指定時間(日本時間 2024/02/27 01:55:00)に 1 回だけ発行して Lambda 関数を実行する構成を作成しています。

lib/cdk-sample-stack.ts

import {
  aws_lambda_nodejs,
  aws_lambda,
  aws_logs,
  Stack,
  TimeZone,
  RemovalPolicy,
  CfnOutput,
} from 'aws-cdk-lib';
import * as aws_scheduler_alpha from '@aws-cdk/aws-scheduler-alpha';
import * as aws_scheduler_targets_alpha from '@aws-cdk/aws-scheduler-targets-alpha';
import { Construct } from 'constructs';

export class CdkSampleStack extends Stack {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    // Lambda 関数
    const helloFunc = new aws_lambda_nodejs.NodejsFunction(this, 'SampleFunc', {
      runtime: aws_lambda.Runtime.NODEJS_20_X,
      architecture: aws_lambda.Architecture.ARM_64,
      logGroup: new aws_logs.LogGroup(this, 'SampleFuncLogGroup', {
        removalPolicy: RemovalPolicy.DESTROY,
      }),
    });

    // Lambda 実行ターゲット
    const target = new aws_scheduler_targets_alpha.LambdaInvoke(helloFunc, {});

    // Lambda 実行をターゲットとした EventBridge Scheduler を作成
    const sampleSchedule = new aws_scheduler_alpha.Schedule(
      this,
      'SampleSchedule',
      {
        target,
        schedule: aws_scheduler_alpha.ScheduleExpression.at(
          new Date('2024-02-27T01:55:00'),
          TimeZone.ASIA_TOKYO
        ),
      }
    );

    // SampleSchedule の名前を出力
    new CfnOutput(this, 'SampleScheduleName', {
      value: sampleSchedule.scheduleName,
    });
  }
}

動作確認

CDK スタックをデプロイします。

npx cdk deploy --require-approval never --method=direct

指定時間後に Lambda 関数のログを見ると、おおよそ指定時間に実行されていることが確認できます。

「おおよそ」としたのは、イベントログのタイムスタンプが指定時間より 1 分 30 秒ほど早いからです。スケジュール作成後から実行までの時間が短か過ぎたからでしょうか?数時間後に実行されるスケジュールを作成した場合はどうなるか再度検証してみたいと思います。

after schedule completion は設定できない

ここで、EventBridge Scheduler では、スケジュール完了後にスケジュールを削除する機能(Deletion after schedule completion)があります。これにより繰り返しのスケジュールの場合は最後の呼び出し後、1 回限りのスケジュールの場合は呼び出し後にスケジュールを自動で削除させることができます。

AWS SDK の CreateSchedule API の場合は ActionAfterCompletion パラメーターで DELETE を指定することにより設定できます。既定値は NONE です。

一方 AWS CDK の @aws-cdk/aws-scheduler-alpha パッケージでは、Schedule クラスの ActionAfterCompletion プロパティが存在しないため、スケジュール完了後の削除は設定できません。

node_modules/@aws-cdk/aws-scheduler-alpha/lib/schedule.d.ts

/**
 * Construction properties for `Schedule`.
 */
export interface ScheduleProps {
    /**
     * The expression that defines when the schedule runs. Can be either a `at`, `rate`
     * or `cron` expression.
     */
    readonly schedule: ScheduleExpression;
    /**
     * The schedule's target details.
     */
    readonly target: IScheduleTarget;
    /**
     * Allows to override target properties when creating a new schedule.
     */
    readonly targetOverrides?: ScheduleTargetProps;
    /**
     * The name of the schedule.
     *
     * Up to 64 letters (uppercase and lowercase), numbers, hyphens, underscores and dots are allowed.
     *
     * @default - A unique name will be generated
     */
    readonly scheduleName?: string;
    /**
     * The description you specify for the schedule.
     *
     * @default - no value
     */
    readonly description?: string;
    /**
     * The schedule's group.
     *
     * @default - By default a schedule will be associated with the `default` group.
     */
    readonly group?: IGroup;
    /**
     * Indicates whether the schedule is enabled.
     *
     * @default true
     */
    readonly enabled?: boolean;
    /**
     * The customer managed KMS key that EventBridge Scheduler will use to encrypt and decrypt your data.
     *
     * @default - All events in Scheduler are encrypted with a key that AWS owns and manages.
     */
    readonly key?: kms.IKey;
    /**
     * A time window during which EventBridge Scheduler invokes the schedule.
     *
     * @see https://docs.aws.amazon.com/scheduler/latest/UserGuide/managing-schedule-flexible-time-windows.html
     *
     * @default TimeWindow.off()
     */
    readonly timeWindow?: TimeWindow;
    /**
     * The date, in UTC, after which the schedule can begin invoking its target.
     * EventBridge Scheduler ignores start for one-time schedules.
     *
     * @default - no value
     */
    readonly start?: Date;
    /**
     * The date, in UTC, before which the schedule can invoke its target.
     * EventBridge Scheduler ignores end for one-time schedules.
     *
     * @default - no value
     */
    readonly end?: Date;
}

ActionAfterCompletion プロパティが無いのはそもそも CloudFormation の仕様でもあります。

作成されたスケジュールを取得してみると、ActionAfterCompletion プロパティが NONE になっていることが確認できます。

$ aws scheduler get-schedule --name ${sampleScheduleName}
{
    "ActionAfterCompletion": "NONE",
    "Arn": "arn:aws:scheduler:ap-northeast-1:XXXXXXXXXXXX:schedule/default/CdkSampleStack-SampleSchedule5A069A0C-189IJ4IX0S8FB",
    "CreationDate": "2024-02-27T01:16:36.688000+09:00",
    "FlexibleTimeWindow": {
        "Mode": "OFF"
    },
    "GroupName": "default",
    "LastModificationDate": "2024-02-27T01:52:52.674000+09:00",
    "Name": "CdkSampleStack-SampleSchedule5A069A0C-189IJ4IX0S8FB",
    "ScheduleExpression": "at(2024-02-26T16:55:00)",
    "ScheduleExpressionTimezone": "Asia/Tokyo",
    "State": "ENABLED",
    "Target": {
        "Arn": "arn:aws:lambda:ap-northeast-1:XXXXXXXXXXXX:function:CdkSampleStack-SampleFunc1AE55385-wjFmAAroDKb4",
        "RetryPolicy": {
            "MaximumEventAgeInSeconds": 86400,
            "MaximumRetryAttempts": 185
        },
        "RoleArn": "arn:aws:iam::XXXXXXXXXXXX:role/CdkSampleStack-SchedulerRoleForTarget1441a743A31888-0ruxomWNaHsM"
    }
}

これに関しては、CloudFormation や CDK などの IaC で管理しているリソースが勝手に削除されるのは困るので、納得のいく仕様ではあります。

おわりに

指定時間に 1 度だけ実行する Amzon EventBridge Scheduler スケジュールを AWS CDK で作成してみました。

EC2 インスタンスをある期日以降に無期限で停止したい場合や、キャンペーンのような一回だけのイベントを実行したい場合などに有用な機能だと思います。どなたかのお役に立てれば幸いです。

参考

以上