シンプルな、EC2インスタンスの自動起動・停止について

     

    この記事は公開してから1年以上経過しており、情報が古い可能性がありますのでご了承ください。

    こんにちは、SIOS AppKeeper開発チームの黒田です。

    今回は、AWS Lambdaのスケジュール機能を利用した、
    シンプルなEC2インスタンスの自動起動・停止方法を紹介したいと思います。

    開発や検証などを目的とした環境では、不要なEC2インスタンスの停止や削除は、
    システムのランニングコスト削減に対して少なからず効果があります。
    特に前月からはEC2の課金単位が、時間単位から秒単位へ変更となっておりますので、
    停止・削除によるコスト削減がより効果的なものとなっています。

    このような停止・削除といった操作は、EC2インスタンスの数が少ないうちは手動で
    行われても良いかも知れませんが、実は地味に面倒な作業でもあります。
    うっかり止め忘れたために想定以上の費用がかかってしまうケースも…?

    基本動作としては、全てのリージョンで、以下の特定タグが設定されているEC2インスタンスを
    スケジュールされた時間に自動起動・停止します。

    EC2インスタンスタグの動作一覧

    keyvalue動作
    Ec2StartStopAuto起動・停止を実行
    Ec2StartStopStart起動のみ実行
    Ec2StartStopStop停止のみ実行

    ※タグのkeyやvalue名は、環境にあわせて設定してください。

    設定するAWSサービス

    • Lambda
    • IAM Role
    • CloudWatch Event

    設定方法

    Lambda

    1.AWS マネージドコンソールへログインしてからAWS Lamdbaサービスを選択し、関数の作成を選択します。

     

    2.トリガーの設定をスキップし、次へを選択します。

     

    3.Lamdba関数の「名前」を入力し、ランタイムは「Python3.6」を選択します。

     

    4.コードをインラインで編集します。

    コードのサンプルは、以下になります。

    import boto3
     
    def lambda_handler(event, context):
        awsRegions = boto3.client('ec2').describe_regions()['Regions']
     
        for region in awsRegions:
            awsregion = region['RegionName']
            ec2 = boto3.resource('ec2', region_name=awsregion)
     
            instances = ec2.instances.all()
     
            start_list = []
            stop_list = []
            action = event['Action']
     
            for i in instances:
                if i.tags != None:
                    for t in i.tags:
                        if t['Key'] == 'Ec2StartStop':
     
                            if t['Value'] == 'Auto' or t['Value'] == action:
                                if action == 'Start' and i.state['Name'] == 'stopped':
                                        start_list.append(i.instance_id)
                                elif action == 'Stop' and i.state['Name'] == 'running':
                                        stop_list.append(i.instance_id)
     
            if start_list:
                print('Starting', len(start_list), 'instances', start_list)
                ec2.instances.filter(InstanceIds=start_list).start()
     
            elif stop_list:
                print('Stopping', len(stop_list), 'instances', stop_list)
                ec2.instances.filter(InstanceIds=stop_list).stop()

    ※必要に応じてコードを変更してください。

    IAM Role

    5.「Lambda 関数ハンドラおよびロール」の「ロール」で、「カスタムロールの作成」を選択します。

     

    6.「ロール名」と「ポリシードキュメント」を入力してください。

    ポリシードキュメントは、以下になります。

    {
      "Version": "2012-10-17",
      "Statement": [
        {
          "Effect": "Allow",
          "Action": [
            "logs:CreateLogGroup",
            "logs:CreateLogStream",
            "logs:PutLogEvents"
          ],
          "Resource": "arn:aws:logs:*:*:*"
        },
        {
          "Effect": "Allow",
          "Action": [
            "ec2:Describe*",
            "ec2:Start*",
            "ec2:Stop*"
          ],
          "Resource": "*"
        }
      ]
    }

    7.「詳細設定」の「タイムアウト」値の変更

    デフォルト3秒から30秒へ
    ※タイムアウト値は、環境にあわせて変更してください。

     

    CloudWatch Event

    8.まずは、起動のスケジュール設定をします。AWS CloudWatchサービス画面に移動し、「イベント」->「ルール作成」を選択してください。

     

    9.「イベントソース」のスケジュールを選択し、「Cron式」を選択して、起動時間のcron式を入力してください。

    cron式(UTC)

    30 23 ? * MON-FRI *

    ※環境にあわせて起動時間を変更してください。

     

    10.「ターゲットの追加」を選択し、作成したLambda関数(Ec2StartStop)を選択します。「入力の設定」の「定数(JSONテキスト)」を選択し、以下を入力してください。

    定数(JSONテキスト)

    {"Action": "Start"}

    11.「名前」を入力と「状態」の「有効」をチェックし、「ルールの作成」を選択します。

     

    12.停止スケジュールの設定をします。以下のようにcron式と定数(JSONテキスト)を入れ替え、8~11の手順を繰り返してください。

    cron式(UTC)

    00 13 ? * MON-FRI *

    ※環境にあわせて停止時間を変更してください。

    定数(JSONテキスト)

    {"Action": "Stop"}

    13.動作確認を行います。EC2インスタンスにタグを設定し、スケジュールされた時間にEC2インスタンスが起動・停止されているかを確認してください。

     

     

    以上、AWS Lambdaのスケジュール機能を利用したシンプルなEC2インスタンスの自動起動・停止方法の紹介でした。

     

    Amazon EC2上で運用しているアプリケーションの自動監視、自動復旧サービスもやってます。
    たくさんのEC2インスタンスをご利用の方簡単に導入できるEC2インスタンスの障害対策をお探しの方など、ご興味あればぜひサービス紹介ページをご覧ください。

    SNSでもご購読できます。