【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

最近の AWS は新しい機能が次々と追加されています。

もはや「人工知能」「ビジネス分析ツール」など AWS の機能だけで、ビジネスに必要なすべての環境が準備できるのではないかと思います。

 

「Lambda」という AWS のサービスがあります。

「Lambda」はプログラムを実行できるサーバーレスの環境なのでサーバーの準備が不要です。

2016年まで「Lambdaの利用手順」は結構ありますが、2017年から設定手順が変わりました。

(AWSは変化のスピードが速いため昔の手順が利用できなくなることがよくあります)

そのため、2017年現在の「Lambda」で、EC2インスタンスを起動・停止するプログラム(Python)を作り、スケジューリングの設定をする手順を説明します。

 

 

Lambdaとは?

Lambdaとは「ラムダ」と読みます。

ギリシア文字の第11字母です。

ギリシア文字では「λ」と書きます。

ギリシア文字の中の1文字なので意味はありません。

 

AWS の「Lambda」のページを確認するとギリシア文字の「λ」のマークのアイコンがあります。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

サーバーレスでプログラムが実行できる

Lambda を利用するとプログラムを実行するためのサーバーが不要になります。

通常プログラムを実行するためにはサーバーが必要です。

例えば Java で開発されたプログラムを実行したい場合は、サーバーに JRE(Java Runtime Environment、Java 実行環境)が必要です。

C言語でプログラムを書いたら GCC でコンパイルをして実行する環境が必要です。

 

私のようなインフラ系エンジニアにとって、この「プログラムを実行する環境」が意外と運用管理をする手間が掛かります。

有名な Java の開発環境である「Eclipse(エクリプス)」なども環境を構築することが大変です。

 

そのため、せっかくプログラムに興味があっても環境がなくて挫折する方が多いと思います。

 

しかし「Lambda」のようなサーバーレス環境では、プログラムの実行環境は AWS が提供してくれるため、プログラムの実行環境の運用・管理・保守は気にせずにガシガシとプログラムを作ることに専念できます。

私は、このサービスはかなりプログラマーにとっては大きなイノベーションになると思っています。

 

プログラマーが開発に専念できる、サーバーのアップデートやパッチの適用や障害対応に時間を割く必要がない、これはビジネスにおいて大きな影響を与えるだろうと思います。

 

たとえば「アイデア」を持っている人がいるとします。

通常、どんなにいい「アイデア」を持っていたとしても、実現できなければ「絵に描いた餅」です。

アイデアを実現するためには「プログラム」の知識も必要ですが、「環境」も必要になるのです。

しかしこの「AWS Lambda」を利用することで、ほぼタダですぐに「アイデア」を実現させる可能性が広がります。

今まではベンチャー系の企業を立ち上げて、人を集めて開発環境を作って、数十台のサーバーを運用管理して・・・といったことをしなくても、AWS でダイレクトにサービスを作って、すぐに全世界にサービスを提供できるようになるかもしれません。

 

 

AWS Lambda の利用料金はほぼタダ(無料)

(ほぼ)「無料」「無償」。これも大きなポイントです。

1ヶ月に100万件が無料といわれてもピンと来ないので、割り算をしてみると、

 

  • 1,000,000÷30日=33,333件/1日
  • 33,333÷24時間=1,388件/1時間
  • 1,388÷60分=23件/1分

 

つまり、1分間に23回以上プログラムを実行すると料金が発生します。

しかし、そうはいっても、その後は100万件につき 0.2 USドル程度なので、ほぼ無料と言ってもいいでしょう。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

トリガーの選択肢が豊富

プログラムを実行するトリガーが豊富です。

※トリガーとはプログラムを起動させる「キッカケ」です。(例えば、時間が来たらプログラムを起動する、URLをクリックすると起動する、などプログラムを起動する切っ掛けです)

  • API Gateway
  • AWS IoT
  • CloudWatch Events(CRON によるスケジューリング)
  • CodeCommit
  • Cognito Sync Trigger
  • DynamoDB
  • Kinesis
  • S3
  • SNS

 

今回は「CRON」によりスケジューリングができる「CloudWatch」を利用してスケジューリングをしてみます。

※CRON 機能を利用することで、例えば毎週日曜日午後8時にプログラムを実行する、月~金の9:00~18:00までプログラムを実行するなど、細かくスケジューリングができます。

 

 

Lambda は AWS の管理画面上より設定して実行する

具体的な Lambda の使い方ですが、AWS の管理画面上より簡単に設定でき、すぐに利用できます。

※AWSのアカウントがない場合は、別途 AWS アカウントを作成してください。(クレジットカードが必要です)

 

 

以下のURLより「コンソールへログイン」ボタンをクリックして「AWS マネジメントコンソール」へログインします。

https://aws.amazon.com/jp/console/

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

ルートユーザーサインインの画面(ログイン画面)が表示されるのでログインします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

ログインしたら左上の「サービス」をクリックします。

下図のように「サービス」一覧が表示されるので「コンピューティング」-「Lambda」をクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

Python で Lambda 用プログラムを作る

ここからプログラム言語の「Python(Python3.6)」で EC2 インスタンスを操作するプログラムを作り、「Lambda(サーバー上ではなく)」より実行します。

作業の流れ

初めに何をどうするのか作業の流れを確認しましょう。

  1. 設計
  2. プログラミング
  3. Lambda登録
  4. スケジューリングをする
  5. 動作確認

 

対象インスタンス

対象インスタンスは、EC2 インスタンス2台です。

以下の2台のインスタンスを利用します。

アベイラビリティゾーン:ap-northeast-1a

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

OSは「Amazon Linux」でも「RedHat」でも「Windows」でも何でも大丈夫です。

今回は対象 EC2 インスタンスの OS は関係なく EC2 インスタンス自体の「起動」・「停止」プログラムです。

 

スケジュール設計

最終的には以下のスケジューリングを考えました。

  • 月曜日~金曜日(盆正月、祝日は考慮せず)
  • 夜21時にインスタンス起動
  • 夜23時にインスタンス停止

将来的にはもっとトリガーの条件を増やしてみたいです。

例えば、HTTPD のセッションがある場合はインスタンス停止を遅らせるとか、特定のプログラムが実行されている場合はそのプログラムが完了するまで待ってから実行する(もしくはプログラムを kill してから実行する)など。

 

 

EC2 インスタンス起動プログラム

以下の「起動プログラム」を利用します。

言語は「Python3.6」「boto3」というライブラリを利用します。

import boto3

 

# Enter the region your instances are in, e.g. 'us-east-1'
region = 'ap-northeast-1' ← アベイラビリティゾーンを入れます。

# Enter your instances here: ex. ['X-XXXXXXXX', 'X-XXXXXXXX']
instances = ['i-068cfXXXXX791268', 'i-086ee3XXXXXcc1ef6'] ← ここにインスタンスIDを入れます。

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

    return 'Finished Start Instance Script..'

 

EC2 インスタンス停止プログラム

以下「停止プログラム」です。

起動している EC2 インスタンスを強制的に停止します。

import boto3

# Enter the region your instances are in, e.g. 'us-east-1'
region = 'ap-northeast-1' ← アベイラビリティゾーンを入れます。

# Enter your instances here: ex. ['X-XXXXXXXX', 'X-XXXXXXXX']
instances =  ['i-068cfXXXXX791268', 'i-086ee3XXXXXcc1ef6'] ← ここにインスタンスIDを入れます。

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

    return 'Finished Stop Instance Script..'

 

 

「boto3」とは

boto3 とは boto の「バージョン3」のことを言います。

boto とは「AWS SDK for Python」というライブラリで、このライブラリを利用することで Python から AWS を操作することができます。

(EC2 インスタンスだけでなく、その他の AWS サービス(S3、RDS 等)も操作できます)

 

 

参考にしたページ

以下のページは英語ですが AWS 公式サイトがプログラム例を記載しています。

 

How do I stop and start Amazon EC2 instances at regular intervals using AWS Lambda?

https://aws.amazon.com/jp/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/?nc1=h_ls

 

※2017年7月にアップデートをしているのですが、プログラムがまだ「Python2.7」のままなのが気になります。(Lambda はすでに Python3.6 がリリースされています)

 

 

 

Lambda に登録する

起動プログラム・停止プログラムが完成したら「Lambda」に登録します。

「Lambda」にプログラムを登録することで「実行」できるようになります。

 

Lambda のページに移動する

AWS マネジメントコンソールにログインして、左上の「サービス」をクリックすると下図のようにサービス一覧が表示されるので「Lambda」をクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

Lambda 関数を作成する

AWS Lambda のページに移動すると下図のように「関数の作成」ボタンがあるのでクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

「設計図の選択」画面が表示されたら「一から作成」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

「トリガーの設定」画面が表示されたらそのまま「次へ」ボタンをクリックします。

トリガー(スケジュール)は後で設定するので、ここは何も設定せずにそのまま「次へ」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

関数の設定画面で以下のように設定します。

名前    : Start_Instances(任意の名前、ただし半角英数字とハイフン、アンダーバーのみしか使えません)

ランタイム : Python 3.6

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

下へスクロールすると「Lambda 関数のコード」「コード」を入力する画面があるので上の「起動プログラム」をコピペします。

※ただし実際の「インスタンスID」は適宜正しいものに設定してください。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

プログラムのコードを入力し、更に下にスクロールすると「Lambda 関数ハンドラおよびロール」を設定する箇所があるので以下のように設定します。

ハンドラ : lambda_function.lambda_handler

ロール  : カスタムロールの作成

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

Lambda ハンドラとは何か?

ハンドラとは「ファイル名.関数名」のセットです。

例えば、ファイル名が「main(実際のファイル名が main.py の場合)」で、関数名が「handler」なら「main.handler」を入力します。

言葉を変えると、Python プログラムのファイル「main.py」を作成して、このプログラムの中に「main」関数を書き、Lambda でこの「main」関数を実行したい場合は「main.handler」を設定します。

 

今回は、デフォルトのままで問題ないため「lambda_function.lambda_handler」で設定します。

 

 

IAM ロールを作成する

設定を続けます。

 

「カスタムロールの作成」を選択すると、下図のように別ページに移動します。

移動したら下図のように設定をします。

IAM ロール : 新しい IAM ロールの作成

ロール名  : lambda_Start_Stop_Instances_Role(このロールを起動プログラム・停止プログラムで利用します)

 

「編集」をクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

 

 

下図のように「ポリシーの編集」画面が表示されるので「OK」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

 

下図のようにポリシーを設定します。

今回は EC2 インスタンスを起動・停止したいため「ec2:Start*」「ec2:Stop*」を設定しています。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

以下、コピペして利用できます。

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
                "ec2:Start*", ← ここで EC2 インスタンスを起動する権限を与えています。
                "ec2:Stop*"   ← ここで EC2 インスタンスを停止する権限を与えています。
      ],
      "Resource": "*" ← AWS のリソースすべてに対する権限を与えています。
    }
  ]
}

 

 

設定したら画面の下の方に「許可」ボタンがあるのでクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

 

元のページに戻り、設定を続けます。

「既存のロール」に先ほど設定したロール(lambda_Start_Stop_Instances_Role)を設定します。

「次へ」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

 

最後に「関数の作成」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

IAM ロールとは?

IAM とは「Identity and Access Management」の略です。

日本語にすると「ID管理とアクセス管理」という意味になりますでしょうか。

 

ロールとは「role(役、役割、任務)」という意味です。

 

IAM ロールはユーザーではありません。

IAM ロールの使い道としては、AWS リソースへのアクセス権を持っていない「ユーザー」「アプリケーション」「サービス」にアクセス権限を委任するという使い方があります。

 

AWS リソースへのアクセス権限(操作権限)は、「IAM ユーザー」「IAM グループ」ではなく「IAM ロール」に割り当てます。

 

ロールのアクセス権限の定義は「ポリシー」で行います。

ポリシーは JSON 形式で記述します。

 

【ポリシーの例】

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Action": [
                "ec2:Start*", ← ここで EC2 インスタンスを起動する権限を与えています。
                "ec2:Stop*"   ← ここで EC2 インスタンスを停止する権限を与えています。
      ],
      "Resource": "*" ← AWS のリソースすべてに対する権限を与えています。
    }
  ]
}

 

 

 

プログラムの動作テストをする

設定が完了すると下図のように「テスト」ボタンが表示されるので、クリックしてプログラムの動作テストをします。

※実際にプログラムを実行します。(単なる構文チェックではなく実際にプログラムが動くことに注意)

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

下図のように「テストイベントの入力」画面が表示されるので「保存してテスト」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

設定や構文に問題がなければ以下のように「実行結果:成功(ログ)」が表示されます。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

以上で Lambda 関数の新規作成は完了です。

 

停止プログラムの設定をする

今まで「起動プログラム」の設定をしてきましたが、「起動プログラム」を参考に「停止プログラム」の設定もします。

 

続けて「スケジューリング」の設定をします。

 

スケジューリングをする

設計のところでも書きましたが、今回以下のスケジューリングを試します。

 

【設定するスケジュール】

  • 月曜日~金曜日(盆正月、祝日は考慮せず)
  • 夜21時にインスタンス起動
  • 夜23時にインスタンス停止

 

スケジュールを設定する

「AWS Lambda」に移動して「関数」をクリックします。 

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

先ほど作成した起動プログラムの「Start_Instances」をクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

「トリガー」タブをクリックして「トリガーを追加」をクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

「トリガーを追加」画面が表示されるので赤い枠をクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

プルダウンメニューより「CloundWatch Events」を選択します。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

下図のようにルールの作成画面が表示されるので「ルール」「新規ルールの作成」を選択します。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

スケジュールを設定する

以下スケジュールの設定をします。

ルール名    : Start_Instances_Schedule(任意の名前を設定します)

ルールタイプ  : スケジュール式

スケジュール式 : CRON の構文は以下説明します。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

CRON の構文

「スケジュール式」に CRON の構文を入れますが、構文規則から説明します。

cron(Minutes  Hours  Day-of-month  Month  Day-of-week Year)

   分    時    日        月    曜日      年

 

※タイムゾーンはUTCのみになるので注意です。

 

「UTC」と「JST」対応表

簡単ですが、一瞬で分かるように「UTC」と「JST」の対応票です。

例えば、日本時間の21時に設定したい場合は、「12」を設定します。

 

UTC(GMT)   JST

0       9

1      10

2      11

3      12

4      13

5      14

6      15

7      16

8      17

9      18

10      19

11      20

12      21

13      22

14      23

15      0(翌日)

16      1(翌日)

17      2(翌日)

18      3(翌日)

19      4(翌日)

20      5(翌日)

21      6(翌日)

22      7(翌日)

23      8(翌日)

UTC と GMT の違い

「UTC」と「GMT」は同義と考えてよいです。

  • UTC(協定世界時:Coordinated universal time)英国のグリニッジ(経度0度)の地方平均時
  • GMT(グリニッジ平均時:Greenwich mean time)

 

スケジュール設定例

今回は月曜日から金曜日まで21時~23時までなので以下のようになります。

 

■構文
cron(Minutes  Hours  Day-of-month  Month  Day-of-week Year)

   分    時    日        月    曜日      年

 

  • 起動時間 cron(0 12 ? * MON-FRI *)
  • 停止時間 cron(0 14 ? * MON-FRI *)

 

月曜から金曜の UTC 12時00分 (JST 21時00分) からスタートします。

「?」のはてなマークは「Day-of-month」の項目ですが、これはいつでも構わないという意味です。

例えば月・火・水・木・金曜日のどれかならば、1日でも11日でも13日でも構わないという意味です。

次に「*」のアスタリスクは、全部という意味です。(どれでもいいという意味ではないことに注意です)

全部の月を指定するということで「*」を設定しています。

次は分かりやすく「MON-FRI」を指定します。

月曜日から金曜日までという意味です。

 

 

参考

以下、CRON でスケジュールを設定する際に構文で参考にさせていただいたサイトです。

ありがとうございます。

 

http://qiita.com/pyr_revs/items/abd29d9472f4cba9032c

 

AWS公式サイト

https://docs.aws.amazon.com/ja_jp/AmazonCloudWatch/latest/events/ScheduledEvents.html

 

 

下図のようにスケジュールの設定を入力したら「送信」ボタンをクリックします。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

設定に問題がなければ下図のように登録されます。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

動作確認をする

設定をしたら、動作確認をします。

時間が来たら実際に EC2 インスタンスが起動していることを確認します。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

 

AWS Lambda でのエラー集

AWS Lambda のエラーについてまとめました。

 

You are not authorized to perform this operation. のエラーが出た場合

Lambda 関数(プログラム)を実行した際に以下のエラーが出た場合です。

{
"errorMessage": "An error occurred (UnauthorizedOperation) when calling the StartInstances operation: You are not authorized to perform this operation. Encoded authorization failure message: l7MY0PYC56eqaEawpuQVHMM7t_GrItkkwYy0tMJMRzxDOGIFDh1YydM5MXLbSa-

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

もう一度正しいポリシーが設定されているか確認します。

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": [
                "ec2:Start*",
                "ec2:Stop*"
            ],
            "Resource": "*"
        }
    ]
}

 

AWS Lambda のここが分かりにくい

「AWS Lambda」のページで、まだ「関数」を1つも作っていない状態で、下図のように「AWS Lambda」-「関数」をクリックすると次の画面が表示されません。

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

 

「エラー」にもならずに延々と「お待ちください」のアイコンが回り続けます。(数分経ってもタイムアウトしません)

【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】

 

まとめ

AWS Lambda は非常に便利ですが、まだまだできることがたくさんありすぎて全貌をつかめていません。

これからも AWS Lambda & Python で何ができるのかアイデアを出していろいろとプログラムを試します。

 

 

Posted by 100%レンタルサーバーを使いこなすサイト管理人

コメントを残す

メールアドレスが公開されることはありません。