LoginSignup
1
0

More than 1 year has passed since last update.

EC2インスタンスの自動停止起動

Posted at

経緯

EC2インスタンスを、使用しない時間帯のみ止めてコスト削減をしたい。
Lambdaのみでの実装と、Instance Schedulerでの実装を行い、それぞれの複数インスタンス・複数スケジュール設定の場合やコスト、注意などをまとめる。

【参考】

Lambda のみで実装する

〇手動方式〇

1. IAM ポリシーと IAMロール作成

  • ポリシーの作成。CloudWatch Logの書き込み、EC2書き込み権限保有(以下JSON)
{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
        "logs:CreateLogGroup",
        "logs:CreateLogStream",
        "logs:PutLogEvents"
      ],
      "Resource": "arn:aws:logs:*:*:*"
    },
    {
      "Effect": "Allow",
      "Action": [
        "ec2:Start*",
        "ec2:Stop*"
      ],
      "Resource": "*"
    }
  ]
}
  • 上記ポリシーをアタッチしたロールを作成

2. EC2 インスタンスを停止および起動する Lambda 関数の作成

  • AWS Lambda コンソールで、「関数の作成」 クリック
  • 「一から作成」クリック
  • [基本的な情報] に次の事項を追加
  • [関数名] に EC2 インスタンスを開始/停止させる関数の名前を入力

[ランタイム] : [python 3.8] を選択
[アクセス権限] : [デフォルトの実行ロールの変更] を展開
[実行ロール] : [既存のロールを使用する] を選択
1で作成したロールを登録

  • 「関数の作成」
  • 「コード」でlambda_functionに以下貼り付け

上の手順で開始させる関数と停止させる関数をそれぞれ作成し、以下を記述する

インスタンスの開始

import boto3
region = 'ap-northeast-1'
instances = ['InstanceID']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
    ec2.start_instances(InstanceIds=instances)
    print('started your instances: ' + str(instances))

インスタンスの停止

import boto3
region = 'ap-northeast-1'
instances = ['InstanceID']
ec2 = boto3.client('ec2', region_name=region)

def lambda_handler(event, context):
ec2.stop_instances(InstanceIds=instances)
    print('stopped your instances: ' + str(instances))

3. CloudWatch Events(Eventblidge) のルールを作成

  • Amazon CloudWatch (Eventblidge)コンソールを開く
  • 左ナビゲーションペインの [イベント] の下にある [ルール] をクリック
  • [ルールの作成] を選択
  • [イベントソース] の [スケジュール] をクリック
  • [Cron expression] に、Lambda にインスタンスを起動/停止させる時刻を表すスケジュール式を入力(UTC)
  • [ターゲットの追加] をクリック
  • [Lambda関数] でEC2 インスタンスを停止させる関数(Start,Stop)を選択
  • [詳細の設定] を選択、名前など設定
  • 「ルールの作成」 ※StartとStopそれぞれ作成

設定した時間になり、スケジュール通り起動・停止していることを確認

〇テンプレートを使用〇

  • AWS CloudFormation テンプレート を YAML ファイルとして保存
  • AWS CloudFormationより、スタックを作成して上記のテンプレートを使用
  • 名前や対象インスタンスID、スケジュールをパラメータに設定し、「作成」
  • 以下のLambda関数とCloudwatchルールが作成

Lambda関数
・TestEC2Scheduler-StartEC2Instances-*
・TestEC2Scheduler-StopEC2Instances-*

CloudWatchルール
・TestEC2Scheduler-StartScheduledRule-*
・TestEC2Scheduler-StopScheduledRule- *

設定した時間になり、スケジュール通り起動・停止していることを確認

複数インスタンス・複数スケジュールでの設定

1 >Lambda、Eventblidgeを手動でスケジュールの数×2(StartとStop)作成

※自動起動停止したいインスタンスの指定は、Lambdaに直接書くか、対象を一覧CSVにしてLambdaで指定する。

2>CloudFormation テンプレートを使用してスケジュールの数だけスタックを作成(LambdaとEventblidgeはStartとStopが自動作成)

※インスタンスの指定は、スタックのパラメータ(Lambdaの環境変数)に登録するか、対象を一覧CSVにしてLambdaで指定する。

コスト

Amazon EventBridge の料金
カスタムイベント :百万件の公開済みカスタムイベントごとに 1.00USD
サードパーティー (SaaS) のイベント :百万件の公開済みイベントごとに 1.00USD
イベントからもう一つのバスへ :百万件の送信済みイベントごとに 1.00USD

AWS Lambda 料金
リクエスト:リクエスト100万件あたり0.20USD
実行時間:GB-秒あたり0.0000166667USD

注意

  • Amazon EventBridgeでのスケジュール設定は、UTCで行われるためマイナス9時間で設定する。

Instance Schedulerで実装する

1. スタックの作成

2. スケジュール定義、ピリオド定義

  • 「DynamoDB」<「テーブル」にて「InstanceScheduler-ConfigTable-*」クリック
  • 「項目を表示」
  • ピリオド定義 (type 属性が period) の office-hours のチェックボックスを選択し、「アクション」から「コピー」をクリック
  • 下記設定し、「項目の作成」をクリック(例:月曜日の9:00~18:00のみ起動する設定)
フィールド名
name mon-start-9am
begintime 9:00
endtime 18:00
description Office hours on Monday
weekdays[0] mon
  • seattle-office-hours のチェックボックスを選択し、アクションから「コピー」をクリック
  • 下記設定し、「項目の作成」をクリック
フィールド名
name mon-9am-18pm
timezone Asia/Tokyo
description Monday 9am to 18pm in Japan (JST)
periods[0] mon-start-9am

3. インスタンスへのタグ付け

  • マネジメントコンソールのインスタンス一覧画面 から対象のインスタンスを選択し、タグのタブから「タグを管理」をクリック
  • 「タグを追加」をクリックし、キーに CloudFormationのInstance Scheduler tag name で指定した値 (初期値は Schedule)、値に適用するスケジュール定義の name の値 (今回は mon-9am-18pm) を入力
  • 「保存」

4. リモートスタックの作成

  • リモートスタックの作成 」>サインイン(入り直す必要あり)、リージョンを東京へ変更
  • InstanceSchedulerAccount、Namespace(1のNamespaceと同じになるように設定)などパラメータを設定
  • 設定した時間になり、スケジュール通り起動・停止していることを確認

複数インスタンス・複数スケジュールでの設定

起動・停止したいスケジュールをDynamoDBのpiriodとscheduleで設定し、対象インスタンスにschedule名をタグ付けする。
問題なく起動・停止した場合はタグにScheduleMessageが作成され、実行時間が確認できる。
→スタック2つ、Lambda1つ、Eventblidge1つ、DynamoDBのScheduleとpiriodはスケジュールの数分作成すればよい。
 ただ、どの対象インスタンスがどのスケジュールで設定されているか一覧で分からないため、別途管理する必要があるかも。

コスト

例:月額約 33.24 ドル Instance Schedulerの費用
※5 つのアカウント * 2 リージョン * 3 サービス (Amazon EC2/Amazon RDS/Aurora クラスター) * 2 つのスケジュール数 * 1 日あたりのスケジューラーあたりのアクションの最小数 2 * 各 Runbook の 4 つのステップの場合
→コストは起動停止対象のインスタンス数は関係せず、実行数の合計によって決まる。

注意

  • 「2. スケジュール定義、ピリオド定義」の際、 configschedule のTimeZoneを「Asia/Tokyo」にする。
  • 3までの手順で実行するとオートメーションのステップ1でエラーとなる。「4. リモートスタックの作成」で別途スタックを立てることで、1つめのスタックのAutomationExecutionRoleのロールが作成され、正常に動作する。
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0