2017年に【最新版】として Lambda で EC2 インスタンスをスケジュール通りに起動・停止するプログラムを作成手順を作りました。
【AWS】【Python】Lambda で EC2 インスタンスを起動・停止するプログラム&スケジュール化手順【2017年最新版】
しかし2018年になり、更に AWS の設定手順や設定画面が変わっていたので、再度手順を作り直しました。
それにしても AWS はどんどん進化して付いていくのも大変ですよね。
Lambda(ラムダ)とは?
Lambdaとは「ラムダ」と読みます。
ギリシア文字の第11字母です。
ギリシア文字では「λ」と書きます。ラムダと入力してスペースキーを押下して変換候補を出力すると「λ」の文字があるかと思います。
ギリシア文字の中の1文字なので「λ」そのものに意味はありません。
AWS には「Lambda」というサービスがあります。
「Lambda」はプログラムを実行できるサーバーレスの環境なのでサーバーの準備が不要です。
2016年まで「Lambdaの利用手順」は結構ありますが、2017年から設定手順が変わりました。更に2018年から設定手順が変わりました。
(AWSは変化のスピードが速いため昔の手順が利用できなくなることがよくあります)
そのため、2018年現在の「Lambda」で、EC2インスタンスを起動・停止するプログラム(Python)を作り、スケジューリングの設定をする手順を説明します。
【Lambda のメリット】サーバーレスでプログラムが実行できる
Lambda を利用するとプログラムを実行するためのサーバーが不要になります。
通常プログラムを実行するためにはサーバーが必要です。
例えば Java で開発されたプログラムを実行したい場合は、サーバーに JRE(Java Runtime Environment、Java 実行環境)が必要です。
C言語でプログラムを書いたら GCC でコンパイルをして実行する環境が必要です。
私のようなインフラ系エンジニアにとって、この「プログラムを実行する環境」が意外と運用管理をする手間が掛かります。
有名な Java の開発環境である「Eclipse(エクリプス)」なども環境を構築することが大変です。
そのため、せっかくプログラムに興味があっても環境がなくて挫折する方が多いと思います。
しかし「Lambda」のようなサーバーレス環境では、プログラムの実行環境は AWS が提供してくれるため、プログラムの実行環境の運用・管理・保守は気にせずにガシガシとプログラムを作ることに専念できます。
私は、このサービスはかなりプログラマーにとっては大きなイノベーションになると思っています。
プログラマーが開発に専念できる、サーバーのアップデートやパッチの適用や障害対応に時間を割く必要がない、これはビジネスにおいて大きな影響を与えるだろうと思います。
たとえば「アイデア」を持っている人がいるとします。
通常、どんなにいい「アイデア」を持っていたとしても、実現できなければ「絵に描いた餅」です。
アイデアを実現するためには「プログラム」の知識も必要ですが、「環境」も必要になるのです。
しかしこの「AWS Lambda」を利用することで、ほぼタダですぐに「アイデア」を実現させる可能性が広がります。
今まではベンチャー系の企業を立ち上げて、人を集めて開発環境を作って、数十台のサーバーを運用管理して・・・といったことをしなくても、AWS でダイレクトにサービスを作って、すぐに全世界にサービスを提供できるようになるかもしれません。
【Lambda のメリット】AWS Lambda の利用料金はほぼタダ(無料)
AWS Lambda の利用料金は(ほぼ)「無料」「無償」。これも大きなメリットです。
1ヶ月に100万件(1,000,000件)のリクエストが無料といわれてもピンと来ないので、割り算をしてみると、
- 1,000,000÷30日=33,333件/1日
- 33,333÷24時間=1,388件/1時間
- 1,388÷60分=23件/1分
つまり、1分間に23回以上プログラムを実行すると料金が発生します。
しかし、そうはいっても、その後は100万件(1,000,000件)につき 0.2 USドル程度なので、ほぼ無料と言ってもいいでしょう。
【Lambda のメリット】トリガーの選択肢が豊富
プログラムを実行するトリガーが豊富です。
※トリガーとはプログラムを起動させる「キッカケ」です。(例えば、時間が来たらプログラムを起動する、URLをクリックすると起動する、などプログラムを起動する切っ掛けです)
2018年現在のトリガー一覧
- API Gateway
- AWS IoT
- Alexa Skills Kit
- Alexa Smart Home
- CloudWatch Events ← CRON によるスケジューリング【今回はこれを選択】
- CodeCommit
- Cognito Sync Trigger
- DynamoDB
- Kinesis
- S3
- SNS
- [CloudWatch Logs]
無くなったトリガー
- なし
新しく「Alexa Skills Kit」と「Alexa Smart Home」が追加されました。
Alexa(アレクサ)とは?
Alexa(アレクサ)とは Amazon が開発した音声サービスシステムです。
AI(人工知能)が搭載されています。
Amazon Echo (Newモデル)、チャコール (ファブリック)
Alexaは以下のような情報提供ができます。
- 音声交流(簡単な挨拶や定型文など)
- 音楽再生
- 予定リストの作成
- アラームの設定
- ポッドキャストのストリーミング
- オーディオブックの再生
- 天気予報の提供
- 交通情報の提供
- リアルタイム情報などの提供
Alexa に対してトリガーを設定するだけで様々なプログラムを実行することができるようになります。
今回は CRON でスケジューリングをする
今回は「CRON」によりスケジューリングができる「CloudWatch」を利用してスケジューリングをしてみます。
※CRON 機能を利用することで、例えば毎週日曜日午後8時にプログラムを実行する、月~金の9:00~18:00までプログラムを実行するなど、細かくスケジューリングができます。
Lambda は AWS の管理画面上より設定して実行する
具体的な Lambda の使い方ですが、AWS の管理画面上より簡単に設定でき、すぐに利用できます。
※AWSのアカウントがない場合は、別途 AWS アカウントを作成してください。(クレジットカードが必要です)
以下のURLより「コンソールへログイン」ボタンをクリックして「AWS マネジメントコンソール」へログインします。
https://aws.amazon.com/jp/console/
ルートユーザーサインインの画面(ログイン画面)が表示されるのでログインします。
ログインしたら左上の「サービス」をクリックします。
下図のように「サービス」一覧が表示されるので「コンピューティング」–「Lambda」をクリックします。
【設計】Python で Lambda 用プログラムを作る
ここからプログラム言語の「Python(Python3.6)」で EC2 インスタンスを操作するプログラムを作り、「Lambda(サーバー上ではなく)」より実行します。
作業の流れ
初めに何をどうするのか作業の流れを確認しましょう。
- 設計
- プログラミング
- Lambda登録
- スケジューリングをする
- 動作確認
対象インスタンス
対象インスタンスは、EC2 インスタンス2台です。
以下の2台のインスタンスを利用します。
アベイラビリティゾーン:ap-northeast-1a
OSは「Amazon Linux」でも「RedHat」でも「Windows」でも何でも大丈夫です。
今回の対象 EC2 インスタンスは「Ubuntu」です。
今回作成するプログラムは、EC2 インスタンスの OS は関係なく EC2 インスタンス自体の「起動」・「停止」プログラムです。
スケジュール設計
最終的には以下のスケジューリングを考えました。
- 毎日実行
- 夜21時にインスタンス起動
- 深夜1時(翌日1時)にインスタンス停止
EC2 インスタンスを利用するのは勉強のためで仕事が終わってからです。
24時間起動しっぱなしでもいいのですが、従量課金制なので使ってなくても少しずつ課金されます。
しかも機械学習用にスペックの良いマシン(と言ってもせいぜいt2.mediumですが)を使っているので料金が嵩んでいきます。
そのために上記のようなスケジュールを設定することにしました。
ちなみに、将来的にはもっとトリガーの条件を増やしてみたいです。
例えば、HTTPD のセッションがある場合はインスタンス停止を遅らせるとか、特定のプログラムが実行されている場合はそのプログラムが完了するまで待ってから実行する(もしくはプログラムを kill してから実行する)など。
EC2 インスタンス起動プログラム
以下の「起動プログラム」を利用します。
言語は「Python3.6」で「boto3」というライブラリを利用します。
import boto3
# ここにインスタンスを設定します。【例】[‘X-XXXXXXXX’, ‘X-XXXXXXXX’] return ‘Start_Instances スクリプトを終了します。’ |
EC2 インスタンス停止プログラム
以下「停止プログラム」です。
起動している EC2 インスタンスを強制的に停止します。
import boto3 # ここにインスタンスを設定します。【例】[‘X-XXXXXXXX’, ‘X-XXXXXXXX’] return ‘Stop_Instances スクリプトを終了します。’ |
要点:インスタンスタイプを変更してもインスタンスIDは変わらない
使用状況によってインスタンスタイプを変更したくなることがあります。
AWS EC2 インスタンスの場合は「インスタンスタイプ」を変更しても「インスタンスID」は変更されません。
ただしインスタンスを停止した場合は「パブリック DNS(IPv4)」と「IPv4 パブリックIP」は変更されます。(再起動は別)
※そもそも Amazon のパブリック IPv4 アドレスは再利用できません。
「boto3」とは
boto3 とは boto の「バージョン3」のことを言います。
boto とは「AWS SDK for Python」というライブラリで、このライブラリを利用することで Python から AWS を操作することができます。
(EC2 インスタンスだけでなく、その他の AWS サービス(S3、RDS 等)も操作できます)
boto3 のインストールは簡単で pip コマンドでインストールが可能です。
# pip install boto3 |
※Lambda 上ではすでに boto3 はインストールされています。
参考にしたページ
以下のページは英語ですが 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」をクリックします。
Lambda 関数を作成する
AWS Lambda のページに移動すると下図のように「関数の作成」ボタンがあるのでクリックします。
「関数の作成」画面が表示されたらデフォルトでは「一から作成」が選択されています。
今回は「一から作成」でプログラムを設定します。
IAM ロールを作成する
下へスクロールすると「一から作成」画面があるので下図のように設定します。
- 名前 : Start_Instances(分かりやすい名前を付ける)
- ランタイム : Python 3.6
- ロール : カスタムロールの作成
「カスタムロールの作成」を選択すると別ページに移動し「ロール」の設定画面が表示されます。
以下のように設定します。
- IAM ロール : lambda_basic_execution(デフォルト)
- ポリシー名 : 新しいロールポリシーの作成
「ポリシードキュメントを表示」をクリックします。
以下のポリシー画面が表示されるので「編集」をクリックします。
「ポリシーの編集」確認画面が表示されるので「OK」ボタンをクリックします。
【デフォルトの状態】
{ |
↓
【編集後】
以下のように編集します。
※コピペして利用できます。
変更部分ですが、EC2 インスタンスの起動・停止権限(「ec2:Start*」と「ec2:Stop*」)を与えています。
更に AWS のリソースすべてに対する権限を与えています。
※多人数で共有している場合は、セキュリティを考えて更に細かく設定した方がいいでしょう。
{ |
下図のようにポリシーを設定したら「許可」ボタンをクリックします。
元のページに戻るので設定を続けます。
「既存のロール」は先ほど設定した「lambda_basic_execution」を選択します。
下図のように設定をしたら「関数の作成」ボタンをクリックします。
下図のように Lambda 関数が正常に作成されたメッセージが表示されることを確認します。
この状態になり、初めてプログラムのコードを設定できるようになります。
トリガーの追加
次にトリガーを追加します。
下にスクロールすると「トリガー」の追加設定画面が表示されるので「CloudWatch Events」をクリックします。
「CloudWatch Events」をクリックすると下図のように「Start_Instances」に紐付く形で「CloudWatch Events」が追加されます。
下の方にスクロールすると「ルール」の設定画面があるので「ルール」のプルダウンメニューより「新規ルールの作成」を選択します。
「新規ルールの作成」を選択すると下図のように設定画面が表示されるので設定します。
- ルール名 : Start_Instances_Schedule(任意の名前)
- ルールの説明 : インスタンスを起動します。(任意の説明文)
- ルールタイプ : スケジュール式
- スケジュール式 : cron(0 12 ? * * *) など CRON のルールに則ったスケジュールを設定します。(時間は UTC で設定する必要があるので注意)
設定が完了したら「追加」ボタンをクリックします。
あらためて CRON 設定するスケジュールを確認すると以下のように設計しました。
- 毎日実行
- 夜21時にインスタンス起動
- 深夜1時(翌日1時)にインスタンス停止
cron式について
「スケジュール式」に CRON の構文を入れますが、構文規則は以下のような順番になっています。
cron(Minutes Hours Day-of-month Month Day-of-week Year)
分 時 日 月 曜日 年
※タイムゾーンはUTCのみになるので注意です。
- *(アスタリスク) ← 全部対象という意味です。毎日、毎時、全曜日、毎年などという意味になります。
- ?(はてなマーク) ← 値を特定しないという意味です。例えば、日に「?」を指定していますが、何日でも(1日でも31日でも)構いませんという意味です。
- 例えば、15分、20分、35分に実行したい場合は cron(15,20,35 * ? * * *) になります。
「UTC」と「JST」対応表
簡単ですが、一瞬で分かるように「UTC」と「JST」の対応表です。
例えば、日本時間の21時に設定したい場合は、「12」を設定します。
簡単に計算する方法ですが、UTCで表示された数字を見たら「+9」すればOKです。
- 0を見た ← 9を足して日本時間で9時
- 22を見た ← 9を足して31 ← 24を引くと7 ← 日本時間で7時
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(翌日)
下図のように「新しいトリガー」が追加されたことを確認します。
プログラムを設定する
次に作成したプログラムを設定します。
下図のように「Lambda 関数(数では Start_Instances)」を選択します。
下図のように作成したプログラムをコピペします。
プログラムをコピペしたら右上にある「保存」ボタンをクリックします。
「保存されました」のメッセージを確認します。
プログラムの動作テストをする
設定が完了すると下図のように「テスト」ボタンが表示されるので、クリックしてプログラムの動作テストをします。
※実際にプログラムが実行されます。(単なる構文チェックではなく実際にプログラムが動くことに注意)
設定や構文に問題がなければ以下のように「実行結果:成功(ログ)」が表示されます。
以上で Lambda 関数の新規作成は完了です。
停止プログラムの設定をする
続けて「起動プログラム」を参考に「停止プログラム」の設定もします。
AWS コンソール画面より「サービス」–「Lambda」をクリックします。
関数一覧画面が表示されたら右上の「関数の作成」ボタンをクリックします。
「一から作成」画面で以下のように設定情報を入力します。
- 名前 : Stop_Instances
- ランタイム : Python 3.6
- ロール : 既存のロール
- 既存のロール : lambda_basic_execution ← 起動プログラム作成時に作成したロールを流用します。
設定をしたら「関数の作成」ボタンをクリックします。
以下の設定画面が表示されたら「CloudWatch Events」を選択し下図のように「Stop_Instances」と紐付けます。
下の方へスクロールすると「トリガーの設定」があるので下図のように「新規ルールの作成」を選択します。
最終的に以下を例にスケジュールを設定します。
- ルール名 : Stop_Instances_Schedule
- ルールタイプ : スケジュール式
- スケジュール式 : cron(0 10 ? * * *) など設定します。
設定が完了したら「追加」ボタンをクリックします。
インスタンス停止プログラムの設定
次にインスタンス停止プログラムを設定します。
「Stop_Instances」をクリックします。
下図のように「Lambda function」に停止プログラムをコピペします。
コピペしたら「保存」ボタンをクリックします。
エラーが出力されず、下図のように「保存されました」のメッセージが表示されることを確認します。
停止プログラムの動作確認
停止プログラムを設定したら動作確認をします。
画面上にある「テスト」ボタンをクリックします。
※「テスト」ボタンをクリックするとプログラムが実行されるので本番環境の場合は注意(構文チェックではなく実際に動作します)
以下のように「実行結果:成功(ログ)」が表示されることを確認します。
EC2 インスタンスの状態も「stopped」になっています。
AWS Lambda でのログを表示して確認する
AWS Lambda 関数(Start_Instances、Stop_Instances)を実行すると以下のように「ログ」確認のリンクが表示されます。
しかし「ログ」のリンクをクリックすると以下のように「ログストリームのロード中にエラーが発生しました。このページを更新して、再試行してください。」と表示されます。
さらにログストリームの欄には「表示するログストリームがありません」のメッセージも表示されています。
理由はログへの「アクセス権限」がないから
今回の設定では「実行ロール」は「lambda_basic_execution」を設定しました。
もう一度「ロール」の内容を確認します。
AWS の上のメニューより「サービス」–「セキュリティ、アイデンティティ、コンプライアンス」–「IAM」をクリックします。
左側ペインより「ロール」をクリックします。
「lambda_basic_execution」を選択します。
「ポリシーのアタッチ」ボタンをクリックします。
検索欄に「log」を入力して検索します。
検索結果より「CloudWatchLogsFullAccess」を選択します。
下図のように「CloudWatchLogsFullAccess」にチェックを入れて「ポリシーのアタッチ」ボタンをクリックします。
ポリシーがアタッチされていることを確認します。
ログの動作確認
ログが表示されるか動作確認をします。
まずは関数を表示して「テスト」ボタンをクリックして関数を実行します。
「ログ」のリンクをクリックします。
ログが出力されていることを確認します。
ログの中身を確認します。
AWS Lambda でのエラー集
AWS Lambda のエラーについてまとめました。
You are not authorized to perform this operation. のエラーが出た場合
Lambda 関数(プログラム)を実行した際に以下のエラーが出た場合です。
{ |
もう一度正しいポリシーが設定されているか確認します。
{ |
参考サイト
https://aws.amazon.com/jp/premiumsupport/knowledge-center/start-stop-lambda-cloudwatch/?nc1=h_ls
http://qiita.com/pyr_revs/items/abd29d9472f4cba9032c
まとめ
2017年版からインタフェースや手順などが変更されていたので、改めて2018年版の手順を作成しました。
このように AWS は日々進化していくので気が付くと新しいサービスが始まっています。(しかも大体が初期無料で)
AWS Lambda は非常に便利でできることがたくさんありすぎて全貌をつかめていません。
これからも AWS Lambda & Python で何ができるのかアイデアを出していろいろとプログラムを試します。
現在はインプレス社から出版された Lambda の解説書を読んで勉強しています。
AWS Lambda実践ガイド (impress top gear)
コメント