はじめに
EC2の自動起動/停止は、基本的な設定ですがEC2インスタンスを利用する上で
- 日々の起動作業の省略、待ち時間の削減
- 停止忘れによる利用料増加の防止
などメリットは大きいと思います。
今回はそんな設定をCDKで実行してみたのでご紹介させていただきます。
コードでは運用しやすい工夫も行っていますので是非ご覧ください。
ソースコードはこちらのGitHubで公開しております。
事前準備
- AWSアカウントが作成されていること
- CDK開発環境の構築が完了していること
(詳しくはこちらをご参照ください。)
AWS 構成図

EC2の自動起動/停止のアーキテクチャはいくつかあると思いますが、今回はEventBridgeが指定した時間にトリガーを発行し、SSM Automationドキュメントを実行することでEC2の制御を行います。
コードの解説
StackファイルとConfigファイル(パラメータファイル)について抜粋して解説します。
コードの全容はこちらのGitHubからご確認ください。
Stackファイル
/**
* 事前定義
*/
// パラメータファイル読み込み(用途に応じて変更する可能性のあるパラメータは外部ファイルに記述)
const config = require("../config/" + props.nodeEnv);
ここでは、環境ごとのパラメータファイルを読み込んでいます。このCDKコードをデプロイするアカウント、リージョンごとにパラメータファイルを作成し、その設定ごとにスケジュールや対象EC2を簡単に書き換えられるような工夫となっています。
// EC2の起動・停止に関する定義
type Ec2Schedule = {
cron: string;
action: 'start' | 'stop';
instanceIds: string[];
};
// 外部ファイルから読み込み
const schedules: readonly Ec2Schedule[] = config.EC2_SCHEDULES;
ここではEC2の制御内容を型として定義しています。
設定ファイルに記述した複数のスケジュールを配列として取得しています。
これにより、複数のEC2インスタンスを個別スケジュールで制御できます。
/**
* EventBridge用IAMロール
*/
const eventsRole = new iam.Role(this, 'EventsRole', {
roleName: `${config.common.project}-${config.common.env}-events-role`,
assumedBy: new iam.ServicePrincipal('events.amazonaws.com'),
});
// ポリシー追加
eventsRole.addToPolicy(
new iam.PolicyStatement({
actions: [
'ssm:StartAutomationExecution',
'ec2:StartInstances',
'ec2:StopInstances',
],
resources: ['*'],
})
);
このロールは、EventBridgeがSSM Automationを実行するために使用されます。
assumedBy に events.amazonaws.com を指定することで、EventBridgeがこのロールを利用できるようになります。SSM Automationを実行するための権限としてssm:StartAutomationExecutionを、EC2の起動停止をするための権限としてec2:StartInstances, ec2:StopInstances付与しています。
/**
* スケジュール定義をループしてルール生成
*/
schedules.forEach((schedule, index) => {
// 起動 / 停止で使う AWS 管理 Automation を切り替え
const documentName =
schedule.action === 'start'
? 'AWS-StartEC2Instance'
: 'AWS-StopEC2Instance';
const ec2StartStopRule = new events.CfnRule(this, `EC2${schedule.action}Rule${index}`, {
name: `${config.common.project}-${config.common.env}-ec2${schedule.action}${index}-rule`,
scheduleExpression: schedule.cron,
state: 'ENABLED',
targets: [{
id: 'StartSSMAutomation',
arn: `arn:aws:ssm:${this.region}::automation-definition/${documentName}:$DEFAULT`,
roleArn: eventsRole.roleArn,
input: JSON.stringify({
InstanceId: schedule.instanceIds,
})
}],
});
});
パラメータファイルで定義したスケジュールをループし、それぞれに対応するEventBridgeルールを生成します。
actionの値に応じて使用するSSM Automationドキュメントを切り替えています。ドキュメントはAWSが提供している以下を利用しています。
- AWS-StartEC2Instance
- AWS-StopEC2Instance
cron形式のスケジュールをパラメータファイルから取得し、scheduleExpression に引き渡しています。
input では、Automationドキュメントに対象となるEC2インスタンスIDを渡しています。AWS-StartEC2Instance およびAWS-StopEC2Instance は、InstanceId を配列形式で受け取ります。
Configファイル
本コードを利用する場合は、基本的にこのファイルを修正するのみで大丈夫です。
// 共通パラメータセット
export const common = {
project: "ec2startstop",
env: "dev",
accountId: "12345678912",
regionId: "ap-northeast-1",
}
環境ごとにtsファイルを作成します。ファイル名のほか、common内で指定する各種パラメータを環境ごとに書き換えて、Stack作成時にこのパラメータを読み込むことで、それぞれの設定でEC2の自動起動/停止を簡単に設定することができます。
/**
* EC2 の起動・停止スケジュール定義
*
* - cron: EventBridge の cron 式
* - action: start | stop
* - instanceIds: 対象 EC2 の InstanceId 配列
*/
export const EC2_SCHEDULES = [
{
// 平日 朝9時に起動
cron: 'cron(0 0 ? * MON-FRI *)',
action: 'start',
instanceIds: [
'i-xxxxxxxxxx',
'i-yyyyyyyyyy',
],
},
{
// 平日 夜18時に停止
cron: 'cron(0 9 ? * MON-FRI *)',
action: 'stop',
instanceIds: [
'i-xxxxxxxxxx',
'i-yyyyyyyyyy',
],
},
] as const;
例として平日9時と平日18時のcorn形式を示しています。ここをご自身の定義したいスケジュールに書き換えてください。
CfnRuleで指定できる時間はUTCのみとなっているため、日本時間-9時間でcron式を作成する必要があります。
対象となるEC2インスタンスのIDを instanceIds で配列として定義していますので、ここをご自身の起動/停止したいEC2インスタンスのIDに書き換えてください。
本Stackをデプロイ後に、対象となるEC2インスタンスを追加、削除したい場合は、この配列に記載したIDを修正しStackの変更セットをデプロイすることで簡単にメンテナンス可能です。
まとめ
EC2の自動起動/停止のためのCDKコードをご紹介しました。
パラメータファイルを書き換えることで起動/停止のスケジュール、対象のEC2インスタンスをカスタマイズできるような書き方をしてみました。マネジメントコンソールで設定を入れるより運用しやすいのではないでしょうか。
ぜひご活用いただければと思います。