EC2でのプログラム定期実行の方法 ~EventBridgeとsystemdを活用する2つのアプローチ~
AWS EC2は非常に柔軟な仮想サーバーですが、「特定のプログラムを定期実行したい」という場面も少なくありません。たとえば、毎日深夜にデータを収集したり、ログをバックアップしたりといった用途です。
この記事では、EC2インスタンス上でプログラムを定期的に実行する2つの方法を紹介します。いずれもsystemdを活用したアプローチですが、「EC2インスタンスを起動するタイミングで実行する方法」と「常時稼働中のインスタンス上で定期実行する方法」に分けて解説します。
この記事の目次
方法1: EventBridge + systemdでEC2を定期起動し、起動時にプログラムを実行
この方法では、EC2インスタンスはふだん停止しておき、実行したいタイミングだけ起動し、起動時にプログラムを実行します。以下のような流れになります。
全体の流れ
- EventBridge(旧CloudWatch Events)でCronルールを設定し、特定の時間にEC2を起動
- EC2が起動した際、systemdのec2-userなどに紐づいたサービスが起動し、プログラムを実行
- プログラムの実行が終わった後にインスタンスを自動停止
メリット
-
- コスト効率が良い:使う時間だけインスタンスを起動するため、長時間稼働させる必要がないジョブに最適
- セキュリティ:定期実行以外はインスタンスが停止しているため、セキュリティ面でも安心
構成手順
EventBridge用のIAMロールを作成
ポリシー作成
- AWSコンソールで「IAM」と検索し、「ポリシーの作成」をクリック
- 「ポリシー作成」に遷移したら、JSONを選択し、以下のJSONに置き換える
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "ec2:StartInstances" ], "Resource": "arn:aws:ec2:<region>:<account id>:instance/<instance id>" } ] }
- 任意の名前、説明を入力してポリシーの作成は完了
IAMロール作成
- 「IAMロールを作成」をクリック
- 「カスタム信頼ポリシー」を選択し、以下のJSONに置き換える
{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "scheduler.amazonaws.com" }, "Action": "sts:AssumeRole" } ] }
- 次へをクリック後、「許可ポリシー」でさきほど作成したポリシーを選択
- 任意の名前と説明を入力してIAMロールの作成は完了
EventBridgeでスケジュール作成
- AWSコンソールで「event bridge」と検索し、「ルールを作成」をクリック
- 「ルール名」「説明」を入力し、ルールタイプは「スケジュール」を選択
- 「スケジュール詳細の指定」に遷移するので、スケジュールのパターンで「定期的なスケジュール」を選択
- 「cronベースのスケジュール」を選択し、cron式を設定する(今回は毎日午前7時に実行するよう指定)
- フレックスタイムウィンドウは「オフ」としておく(設定日時から〜分以内でランダムな時間帯に実行したい場合は任意で設定)
- 「次へ」をクリックすると、ターゲット選択画面に遷移するので、「全てのAPI」を選択肢、検索欄で「EC2」を検索し、さらに検索結果から「start」で検索し、「Amazon EC2 StartInstances」を選択
- クリックすると、JSONオブジェクトのフィールドが出てくるので、”MyData”の部分をターゲットインスタンスのidに置き換える
- 次へをクリックして、設定画面の下部、「アクセス許可」にて「既存のロールを使用」を選択し、先ほど作成したIAMロールを付与する
- 確認画面がでたら、「スケジュールを作成」をクリックして完了
systemdサービスを作成
-
- EC2内で、以下のような/etc/systemd/system/my-job.serviceを作成
[Unit] Description=My Scheduled Job After=network.target [Service] Type=oneshot ExecStart=/home/ec2-user/my-script.sh -> 実行プログラムshを指定
- EC2の起動時にこのサービスが実行されるよう、タイマーではなく起動トリガーで有効化
sudo systemctl enable my-job.service
- EC2内で、以下のような/etc/systemd/system/my-job.serviceを作成
インスタンス停止
- スクリプトの最後で、AWS CLIなどを用いてインスタンス自身を停止させる
aws ec2 stop-instances --instance-ids $(curl -s http://169.254.169.254/latest/meta-data/instance-id)
注意点
- インスタンスの起動後、systemdが正常に起動するまでに数秒かかる場合がある
- IAMロールにEC2停止権限が必要
方法2:インスタンスを常時起動し、systemdで定期実行
この方法では、インスタンスを常に起動したままにしておき、systemdのタイマー機能やcronを使ってプログラムを定期実行します。
メリット
- 実行頻度が高いジョブに向いている
- より柔軟なスケジューリングが可能
- インスタンスの起動待ちが不要なため、実行が速い
systemd-timerを使った定期実行例
- 以下のようなサービスファイルを作成
/etc/systemd/system/my-job.service[Unit] Description=My Periodic Job [Service] Type=oneshot ExecStart=/home/ec2-user/my-script.sh
- タイマーを定義
/etc/systemd/system/my-job.timer[Unit] Description=Runs my job every 6 hours [Timer] OnBootSec=5min OnUnitActiveSec=6h Unit=my-job.service # インスタンスが起動した5分後から開始し、その後6時間ごとにジョブを実行 [Install] WantedBy=timers.target
- タイマーを有効化・起動
sudo systemctl enable my-job.timer sudo systemctl start my-job.timer
どちらの方法を選ぶべきか?
条件 | おすすめの方法 |
コスト重視 | 方法1(EventBridge + systemd) |
実行頻度が高い | 方法2(常時起動 + systemd) |
複雑なスケジューリングが必要 | 方法2(常時起動 + systemd) |
セキュリティやリソース節約を優先 | 方法1(EventBridge + systemd) |
まとめ
EC2インスタンス上での定期的なプログラム実行について今回は2つの方法を紹介しました。
- EventBridgeを使って必要なときだけEC2を起動し、systemdでジョブを実行する
- 常時稼働しているEC2上でsystemdタイマーで実行する
AWSの柔軟性とsystemdの安定性を組み合わせることで、効率的で堅牢なスケジューリングを実現できます。目的や予算に応じて、最適な方法を選んでみてください。
この情報は役に立ちましたか?
フィードバックをいただき、ありがとうございました!
カテゴリー: