EC2でのプログラム定期実行の方法 ~EventBridgeとsystemdを活用する2つのアプローチ~

AWS EC2は非常に柔軟な仮想サーバーですが、「特定のプログラムを定期実行したい」という場面も少なくありません。たとえば、毎日深夜にデータを収集したり、ログをバックアップしたりといった用途です。
この記事では、EC2インスタンス上でプログラムを定期的に実行する2つの方法を紹介します。いずれもsystemdを活用したアプローチですが、「EC2インスタンスを起動するタイミングで実行する方法」と「常時稼働中のインスタンス上で定期実行する方法」に分けて解説します。

方法1: EventBridge + systemdでEC2を定期起動し、起動時にプログラムを実行

この方法では、EC2インスタンスはふだん停止しておき、実行したいタイミングだけ起動し、起動時にプログラムを実行します。以下のような流れになります。

全体の流れ

  1. EventBridge(旧CloudWatch Events)でCronルールを設定し、特定の時間にEC2を起動
  2. EC2が起動した際、systemdec2-userなどに紐づいたサービスが起動し、プログラムを実行
  3. プログラムの実行が終わった後にインスタンスを自動停止

メリット

    • コスト効率が良い使う時間だけインスタンスを起動するため、長時間稼働させる必要がないジョブに最適
  • セキュリティ:定期実行以外はインスタンスが停止しているため、セキュリティ面でも安心

構成手順

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

インスタンス停止

  • スクリプトの最後で、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の安定性を組み合わせることで、効率的で堅牢なスケジューリングを実現できます。目的や予算に応じて、最適な方法を選んでみてください。

この情報は役に立ちましたか?


フィードバックをいただき、ありがとうございました!

関連記事

カテゴリー:

ブログ

情シス求人

  1. システム開発におけるテスト工程の重要性と各テストの役割

  2. チームメンバーで作字やってみた#1

ページ上部へ戻る