【AWS】CloudWatchを使ってEC2を自動停止し経費削減を狙ってみた。

cloudwatchでec2を自動停止

Zabbixサーバーのテストを行っている最中です。

私はこれまでAWSにけっこう課金をしてきました。

これ、サービスを動かすための必要経費ならいいんですが、テスト使用の場合使っていない時間の課金ってもったいないですよね。

なので、主にAWSを使わないであろう夜間に自動停止をすることで経費を抑えることにしました。

CloudWatch Eventsを使う

いろいろと調べてみるとLambdaも使えるそうなのですが、今回はCloudWatch EventsのみでEC2の自動停止を試みました。

概要はこんな感じです。

  • あらかじめ設定したスケジュール・時間に停止させる(今回は22時)
  • EC2インスタンスを2つ停止させる

起動に関してはテスト時に起動するので、今回はあくまでもうっかり消し忘れ注意みたいな感じでセッティングしてみました。

作業時はこちらの方のブログ記事がめっちゃ参考になったので貼らせていただきます。

やったこと

ポリシーを作成する

まず、CloudWatch EventsがEC2インスタンスに対してアクションを実行するための権限が必要なので、ポリシー及びロールを作成します。

サービスからIAMに入ります。

今回は必要最低限の機能にしたかったのでカスタムポリシーを使いました。

「ポリシー」から「ポリシーの作成」をクリック。

「JSON」のタブをクリック。

デフォルトの表記はこちら。

ここに必要なポリシーを書き込みます。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "lambda:InvokeFunction"
            ],
            "Resource": [
                "arn:aws:lambda:*:*:function:Automation*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "ec2:StartInstances",
                "ec2:StopInstances"
            ],
            "Resource": [
                "*"
            ]
        },
        {
            "Effect": "Allow",
            "Action": [
                "sns:Publish"
            ],
            "Resource": [
                "*"
            ]
        }
    ]
}

今回は、とりあえず停止するための”ec2:StopInstances”、起動させるための”ec2:StartInstances”、SNSでメッセージ通知をさせるための”sns:Publish”を書きました。

ec2:StopInstances以外はまだ使いませんが、後々使いそうなのであらかじめ書いておきます。※停止だけしたい場合はec2:StopInstancesだけでOKです。

ポリシーが書けたら「ポリシーの確認」をクリック。

任意の名前をつけていきます。

今回は「EC2_STOP_2」という名前にしました。

よければ「ポリシーの作成」をクリック。

これでポリシーが作成できました。

ポリシーをロールに割当てる

続いて、ポリシーをロールに割当てます。

IAMの権限のイメージをサッカーに例えると、ポリシーがボールでロールがサッカー選手です。

サッカーでは選手とボールのどちらが欠けてもゴールはできません。

IAMロール(選手)がIAMポリシー(ボール)を運んでゴール(任意のAWSサービスに権限を通す)するイメージです。

ということで、ボールを運ぶ役割であるロールを作成してそこにポリシーを割り当てていきます。

「ロール」から「ロールの作成」をクリック。

こちらではロールを何に使うのか選択できます。

今回はEC2を管理したいので、「EC2」を選択します。

選択したら、次のステップ:アクセス権限をクリック。

今回はすでに作成してあるポリシーを選択します。

「ポリシーのフィルタ」をクリック。

すると、「ユーザーによる管理」という項目がでてきます。

先程作成した、「EC2_STOP_2」が出てくるので、左側にあるチェックボックスにチェックを入れて「次のステップ:タグ」をクリック。

タグが必要な方は入力して、「次のステップ:確認」をクリック。

ロール名とロールの説明を入力します。

今回は「EC2_STOP」という名称にしました。

作成が終わるとロールの項目に「EC2_STOP」が出てきます。

このロール名をクリックし、「信頼関係」のタブを開きます。

こちらに表示されている「信頼されたエンティティ」という項目を編集していきます。

「信頼関係の編集」をクリック。

デフォルト状態がこちら。

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

“Service”に”events.amazonaws.com”の項目を追加していきます。

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

書いたら「信頼ポリシーの更新」をクリック。

「信頼されたエンティティ」が追加されたことを確認します。

ポリシーとロールについてはこれでOKです。

CloudWatch Eventsを作成する

CloudWatchに入り、「ルールの作成」をクリック。

イベントソースを「スケジュール」をチェックし変更。「Cron式」にチェック。

ここで時間等のスケジュールを設定します。

「0 13 * * ? *」と入力。

注意点として、タイムゾーンがGMT(グリニッジ標準時)であるということ。

自分で日本時間をGMTに変換する必要があります。(例. 日本時間22時→グリニッジ標準時13時)

変換には時差計算ツール等使うと便利です。

ターゲットをEC2 StopInstances API 呼び出しに変更し、自動停止したいEC2インスタンスのIDを入力します。

「既存のロールを使用」にチェックを入れ、先程作成した「EC2_STOP」を選択します。

ルールの定義で名前と説明を入力し、ルールの作成をクリック。

今回は2つのEC2インスタンスを自動停止したいので、もう1つのEC2インスタンスも追加してみましょう。

CloudWatchの「ルール」から完成した「EC2_Stop」の左のボックスにチェックを入れ、「アクション」から「編集」をクリックします。

「ターゲットの追加」をクリックします。

先程と同じく、任意のインスタンスIDを入れ、EC2 StopInstance API 呼び出しを選択、「既存のロールを使用」にチェックを入れ、EC2_STOPを選択。

「設定の詳細」をして「ルールの更新」をします。

これで完了です。