はじめに
2015/10のAmazon re:Invent 2015で、Lambdaに関して幾つかの機能追加が発表されました。
個人的に大きいのは以下の3つです。
- Lambda functionをPythonで記述できる
- Lambda functionをSchedule実行させる事ができる
- Lambda functionの最大実行時間が5分に拡張された (従来は1分)
AWS LambdaをData Pipelineを使ってSchedule Drivenで起動させる記事を以前書いたのですが、Schedule実行の機能はLambdaの標準機能としてサポートされました。この記事ではLambda functionをPythonを使って記述し、Schedule実行させる手順をチラ裏しておきます。
制限事項
今回発表/追加されたLambda + Python + Scheduleの実行環境ですが、気を付けて置くべき制限があります。大きいのは以下の項目です。
- Lambda functionの処理は5分以内に終了させないとErrorになる(なので時間がかかる処理には使えない)
- Schedule実行の最短周期は5分 (なので1分に1回Lambda functionを実行する、とかはできない)
- PythonはVer 2.7のみ対応 (3.xは現時点で対応されていない)
- PythonでPython2.7の標準library以外をimportして使用するには、library毎zip圧縮してUploadする必要がある(手順は後述)
Case1:5分毎にPythonのPrintで出力をしてみる
一番最初のCase studyとして、単にPrintするだけのPython Scriptを、5分毎のSchedule実行させる、という一番ベタなケースです。Schedule実行の結果が正しく出力されているかLogを見てみます。
AWS ConsoleのLambdaから、Create a Lambda function
を選択します。
Step1 雛形(blueprint=青写真)の選択
Lambda functionの雛形が沢山ありますがlambda-canary
を検索して選びます。Lambda function上で、Python scriptをSchedule実行させる雛形です。
Step2 Event sourceの設定
今回はSchedule実行なので、Event sourceにはScheduled Event
を選択します(defaultで選ばれていると思います)。
Name
とDescription
は適当な説明文を入れればOKです。
Schedule expression
はdefaultでrate(5 minutes)
になっているはずなのでそのままで良いです。
Step3 Python scriptの設定
Python scriptと、IAM roleの設定を行います。
Pythonのcodeは以下を使います。ひたすらprintするだけのCodeです。
import json, datetime, commands
def lambda_handler(event, context):
print commands.getoutput('cat /proc/cpuinfo | grep -e "processor" -e "model name"')
print commands.getoutput('cat /proc/meminfo | grep MemTotal')
print commands.getoutput('cat /proc/meminfo | grep MemFree')
print datetime.datetime.now().strftime('%Y/%m/%d %H:%M')
print '-------------------------------'
print event
print event['account']
print context.__dict__
print context.memory_limit_in_mb
Python script以外は、以下の設定が必要です。他はDefaultのママで良いです。
-
Name
はLambda functionの名前です。(他のLambda functionと被らなければ)適当な文字列で良いです。 -
Role
はLambda functionに付与するIAM roleです。今回は他のAWS Resourceにアクセスしないので、lambda_basic_execution
を選択すれば良いです(lambda_basic_execution
と言うIAM roleが無い場合には、この名前のroleを作成する事になります)。
Step4 設定確認
最終確認です。Enable now
を選択すると、この設定でSchedule実行がEnableされます。Enable now
を選択しCreate function
を押せば完成です。
Step5 Print出力された結果を確認
Lambda functionの出力結果は、CloudWatch logsに保存されます。
AWS ConsoleのCloudWatchのLogsから、Lambda_Test
を選択します。すると、5分毎に実行Logが追加され、printした内容がLogに残っていると思います。
Python scriptの補足
- Python2.7に標準で入って居るLibraryは、
import json, datetime, commands
の様に書けばOKです -
main
というmethodは無く、lambda_handler
というMethodがEntry pointとして(event
,context
という引数で)呼ばれます。
Entry pointの関数はConfiguration
のHandler
で指定を変える事が可能です
- Entry pointの引数である
event
,context
の中身は、何をEvent sourceとするかで違ってきています。printでevent
,context
の中身を吐き出しているので、チェックしてみてください。
Case2:Schedule実行の周期を5分毎から10分毎に変えてみる
Step1 古いSchedule実行設定の削除
AWS ConsoleのLambdaから、先ほど作ったLambda_Test
のfunctionのEvent sources
のタブに行きます。
rate(5 minutes)
で設定したSchedule実行をx
で一旦削除し、Add event source
を選択します
Step2 10分毎のSchedule実行の設定
Add event source
のDialogで、Event sources type
にScheduled Event
を選択し、以下の様にDialogを埋めます。
-
Name
とDescription
は適当な説明文を入れる -
schedule expression
でcron
を選択し、cron(0/10 * * * ? *)
と書く
ここで注意なのは、Lambdaのcronの文法が、いわゆるLinux一般のcronの文法と微妙に違う点です。
この記事を参考にcron(0/10 * * * ? *)
と書いてください。
Enable now
を選択すると、この設定でSchedule実行がされます。10分毎に実行LogがCloudWatch logsにあるか確認して見て下さい。
Case3:標準ではないLibraryを入れてみる
numpy
やpandas
やrequests
と言った、Python2.7標準では無いlibraryをLambda + Pythonで使いたい場合は、Script fileそのものと合わせてLibraryも一緒にzipしてuploadして上げる必要があります。詳細は、AWS公式サイトのCreating a Deployment Package (Python)を参照して下さい。
Step1 Python scriptをfileとして保存
以下のPython scriptをLocalに保存します (ここではLambdaTest.py
と言うfile名で保存する想定で進めます)。
Python Scriptの中身は、requests
libraryを使ってgoogle.co.jp
をHTTP GETして、Status CodeとResponse BodyをPrintするものです。
import requests, datetime
def lambda_handler(event, context):
target_URL = 'https://www.google.co.jp'
r = requests.get(target_URL)
print datetime.datetime.now().strftime('%Y/%m/%d %H:%M')
print '-------------------------------'
print r.status_code
print '-------------------------------'
print r.text
requests
と言う、Python2.7標準に無いlibraryが必要なので、このCodeをこのままLambdaに登録するとErrorになります。そのため、requests
のlibrary fileを同じフォルダに置き、zip圧縮して、zipをLambdaに登録します。
Step2 Libraryを含んだzip fileを作成
pip install
を-t /PathTo/LambdaTest.py
optionで実行すると、指定したフォルダにlibrary fileを配置してくれます。例えば、LambdaTest.pyが/home/hoge
に有るとしたら、pip install -t /home/hoge
と実行すればOKです。
以下みたいなファイル構成になるはずです。これら(フォルダが2個、ファイルが1個)をzip圧縮して、適当な名前を付けます(LambdaLibraryZip.zip
としたとします)
Step3 Entry Pointの関数名を変更
Lambda functionのCodeをzipでUploadする場合、Entry Pointの関数名(Pythonのmain関数)が*.pyのファイル名
+ .
+ Scriptの中のEntry Pointの関数
となります。今回の例で言うと、LambdaTest.lambda_handler
と設定する必要があります。Configuration
タブのHandler
をLambdaTest.lambda_handler
と設定します
Step4 zip fileをUploadして実行
Code
タブから、Upload a .ZIP file
で、先ほど作成したLambdaLibraryZip.zip
をUploadして、Save and test
をクリックして、Python Scriptが正しく実行されているか確認してみてください。
最後に
LambdaのPython対応、Schedule実行対応は、Python Loveな私的にはとても良いNewsです。Amazonの掲げる2 tier Architecture、もしくはサーバレスアーキテクチャへの大きな布石になると思います(そしてAmazonにどんどんLockinされていく...)。
ただ、まだLambda + Python + Schedule実行でも置き換えられない領域が幾つかあると思います。
短い周期での実行が必要なケース
Lambdaの最短実行周期は5分です。これで多くのニーズはカバーされると思いますが、『1分毎にStatus Checkや死活監視したい』などの要件もやはりあります。Server-lessで短い周期のSchedule実行を行うAWS serviceを自分は知らないです(知っていたら教えてください)。
Amazonが出してきた提案は、EC2 t2.nano Instanceなのでは、と思っています。現行のt2.microよりも更に安いInstanceを用意してヤッから、これ使ってチラシの裏にでも書いてな、って事です。
処理に時間かかかるケース
Lambdaの最大処理時間は今回5分に拡張されました(従来は1分でした)。1分だった時は、S3のLogをLocalに持って来て、中身をParseして、Errorが見つかったらAlarmを発動しつつ結果をRDSに書き込んでおく
と言った処理をLambda functionでする時に、Log sizeが数100MBを超えるとTimeoutするようなケースがありましたが、今回の5分への拡張で多くのニーズはカバーされると思います。が、『大量のDataのDailyのETL Batch処理』などの処理の時間が必要な要件もやはりあります。
自分の知る限り、この手の演算やData転送で処理に時間が掛かる要件には、
- 演算能力が必要無い場合は、Data Pipeline + Pythonを使う
- 演算能力が必要な場合は、Lambda Schedule実行で必要なSpecを持つEC2 (Spot) Instanceを立てる
が良いんじゃないかなぁ、と思っています。