Djangoroidの奮闘記

python,django,angularJS1~三十路過ぎたプログラマーの奮闘記

AWS lambda をpythonコードで使ってみる〜テスト編

概要

AWS lambda から、pythonコードで使ってみる

参考サイト

docs.aws.amazon.com

docs.aws.amazon.com

やってみた

AWS Lambda を Amazon S3 に使用する

バケットにアップロードされる各画像(.jpg および .png オブジェクト)のサムネイルを作成するlambda関数を作る。

ステップ 1: 準備

  • AWS アカウントにサインアップし、アカウントで管理者ユーザー(adminuser)を作成する

http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/setting-up.html

  • AWS CLI をインストールしてセットアップする。

http://docs.aws.amazon.com/ja_jp/lambda/latest/dg/setup-awscli.html

$ pip install awscli
$ aws configure
# IDなどを、さっき作ったadminuserで設定する。

#コマンドを実行して、AWS CLI がコンピュータにインストールされたことを確認します。
$ aws help

# Lambda コマンドを実行して、ユーザーが AWS Lambda にアクセスできることを確認します。
$ aws lambda list-functions --profile default
  • ここで、もし別のuserをawscliに追加したいときは、$ cat ~/.aws/credentialsに情報を追記する。
[profile adminuser]
aws_access_key_id = adminuser access key ID
aws_secret_access_key = adminuser secret access key
region = aws-region

ステップ 1.2: バケットを作成しサンプルオブジェクトをアップロードする

ポイント * ソースバケットと Lambda 関数の両方が同じ AWS リージョンに存在する必要があります。 * さらに、Lambda 関数に使用されるコード例でも、同じリージョンに両方のバケットがあるとします。 * このチュートリアルでは、 ap-northeast-1 リージョンを使用します。

mybucket と mybucketresized を作る

mybucketに、bull.jpg(サンプル) オブジェクトをアップする。

ステップ 2: Lambda 関数を作成し、手動で呼び出す (サンプルイベントデータを使用)

  • 提供されたサンプルの コードを使用して Lambda 関数のデプロイパッケージを作成します。
  • IAM ロール (実行ロール) を作成します。デプロイパッケージのアップロード時には、ユーザーに代わって関数を実行するために Lambda が引き受けることができる IAM ロール (実行ロール) を指定する必要があります。
  • デプロイパッケージをアップロードすることで Lambda 関数を作成したら、サンプル Amazon S3 イベントデータを使用してその関数を手動で呼び出すことでテストします

ステップ 2.1: デプロイパッケージを作成する

以下のコードを、CreateThumbnail.py という名前でファイルを保存します。

from __future__ import print_function
import boto3
import os
import sys
import uuid
from PIL import Image
import PIL.Image
     
s3_client = boto3.client('s3')
     
def resize_image(image_path, resized_path):
    with Image.open(image_path) as image:
        image.thumbnail(tuple(x / 2 for x in image.size))
        image.save(resized_path)
     
def handler(event, context):
    for record in event['Records']:
        bucket = record['s3']['bucket']['name']
        key = record['s3']['object']['key'] 
        download_path = '/tmp/{}{}'.format(uuid.uuid4(), key)
        upload_path = '/tmp/resized-{}'.format(key)
        
        s3_client.download_file(bucket, key, download_path)
        resize_image(download_path, upload_path)
        s3_client.upload_file(upload_path, '{}resized'.format(bucket), key)

ソースコードがローカルホストにある場合は、それをEC2インスタンス(amazon linux)にSSHで接続して、コピーします。

  • これは、多分、lambdaの動作環境と合わせるために、amazon linux上でわざわざ行う必要があるのかもしんない。別の方法ないかなぁ。

  • EC2を作った時に、設定するkeyペアは超重要。これはダウンロードしてローカルのPCに保存しておく。

ec2 に接続する方法は、「接続」というボタンをクリックすると出てくる。以下はしょってコピペ。

インスタンスにアクセスするには:
* SSH クライアントを開きます。
* プライベートキーファイル(lambda_key.pem)を見つけます。ウィザードが、インスタンスを作成するために使用するキーを自動的に検出します。
SSH が機能するには、キーが公開されていないことが必要です。必要な場合は次のコマンドを使用します。
chmod 400 key.pem
インスタンスに接続するには、パブリック DNS を使用します。
***************.ap-northeast-1.compute.amazonaws.com
例: 
ssh -i "key.pem" ec2-user@************.ap-northeast-1.compute.amazonaws.com
ほとんどの場合、上のユーザー名は正確ですが、AMI の使用方法を読んで AMI 所有者がデフォルト AMI ユーザー名を変更していないことを確認してください。
ここのec2-userというのはデフォルトで設定されているのか。

とりあえず、接続できた!

# CreateThumbnail.pyをEC2にコピペする。
$ scp -i key.pem /Users/user/Document/lambda/CreateThumbnail.py ec2-user@*********.ap-northeast-1.compute.amazonaws.com:~/CreateThumbnail.py

# SSHで、ec2に接続する。
ssh -i "key.pem" ec2-user@************.ap-northeast-1.compute.amazonaws.com

# 必要な要件をinstallする
$ sudo yum install python27-devel python27-pip gcc

# pillowに必要なpackageをinstallする
$ sudo yum install libjpeg-devel zlib-devel

# 仮想環境を作成してアクティブ化します。
$ virtualenv ~/shrink_venv
$ source ~/shrink_venv/bin/activate

# 必要なモジュールをinstallする
$ pip install Pillow
$ pip install boto3

# .zip ファイルを作成します。
zip -9 ~/CreateThumbnail.zip

ここでerror発生!zip error: Nothing to do!とのこと。。。 以下のサイトを参考にしてみた。たぶん、引数が足りないとのこと。

「zip error: Nothing to do!」というエラーが出るときの対処法

なので、以下の通りコマンドを変更してみる。

zip -9 ~/CreateThumbnail.zip *

できた!とりあえず、これでいいんちゃうかなぁ。

$ cd $VIRTUAL_ENV/lib/python2.7/site-packages
$ zip -r9 ~/CreateThumbnail.zip *
$ cd $VIRTUAL_ENV/lib64/python2.7/site-packages
$ zip -r9 ~/CreateThumbnail.zip *
$ zip -g CreateThumbnail.zip CreateThumbnail.py

チュートリアルはここまでだけど、zipファイルのアップが必要ぽいので、一応ダウンロードしておく。

EC2にファイルアップロード/ダウンロード - Qiita

$ exit(ec2からサインアウト)
$ scp -i "pemのパス" ec2-user@host:ダウンロード対象ファイルパス .
$ scp -i "key.pem" ec2-user@*****************.ap-northeast-1.compute.amazonaws.com:/home/ec2-user/CreateThumbnail.zip .

ステップ 2.2: 実行ロール (IAM ロール) を作成する

  • 「Role Name」では、AWS アカウント内で一意の名前(lambda-s3-execution-role など)を使用します。
  • [Select Role Type] で、[AWS Service Roles] を選択して [AWS Lambda] を選択します。これにより、ロールを引き受けるアクセス権限を AWS Lambda サービスに付与します。
  • [Attach Policy] で、[AWSLambdaExecute] を選択します。

  • 作成したロールの ARN をメモします。これは、次のステップで Lambda 関数を作成するときに必要になります。

ステップ 2.3: Lambda 関数を作成し、手動でテストする

  • デプロイパッケージをアップロードして、Lambda 関数を作成します。
  • Lambda 関数を手動で呼び出し、パラメータとしてサンプル Amazon S3 イベントデータを渡すことで、この関数をテストします。

ステップ 2.3.1: Lambda 関数を作成する(デプロイパッケージをアップロードする)

コマンドプロンプトで、--profile として adminuser を使用して、以下の Lambda AWS CLI create-function コマンドを実行します。

$ aws lambda create-function \
--region ap-northeast-1 \
--function-name CreateThumbnail \
--zip-file fileb://Users/*****/Desktop/lambda/CreateThumbnail.py \
--role arn:aws:iam::*********:role/********\
--handler CreateThumbnail.handler \
--runtime python2.7 \
--timeout 10 \
--memory-size 1024

error発生!zip-fileのpathが間違えていた!fileb://でワンセットのため、絶対pathの場合は、///が三つ続くことになる。

aws lambda create-function \
--region ap-northeast-1 \
--function-name CreateThumbnail \
--zip-file fileb:///Users/****/Desktop/lambda/CreateThumbnail.zip \
--role arn:aws:iam::*********:role/********\ \
--handler CreateThumbnail.handler \
--runtime python2.7 \
--timeout 10 \
--memory-size 1024

一応アップ完了!!

オプションとして、同じ AWS リージョンの Amazon S3 バケットに .zip ファイルをアップロードし、前述のコマンドでそのバケットとオブジェクト名を指定することもできます。以下に示すように、--zip-file パラメータを --code パラメータで置き換える必要があります。

--code S3Bucket=bucket-name,S3Key=zip-file-object-key
  • 関数の ARN を書き留めます。通知設定を Amazon S3 バケットに追加するときは、以下のセクションでこれが必要になります。

"FunctionArn": "arn:aws:lambda:ap-northeast-1:**************:function:CreateThumbnail"

ステップ 2.3.2: Lambda 関数をテストする (手動で呼び出す)

  • このステップでは、サンプル Amazon S3 イベントデータを使用して、手動で Lambda 関数を呼び出します。AWS マネジメントコンソール または AWS CLI を使用して関数をテストできます。

「開始方法」の手順に従って、Lambda 関数を作成して呼び出す(コンソール)

[AWS lambda]-> [Test]->[Sample event template] -> [S3 Put]を選択。

テストの内容を以下のような感じで該当箇所を修正する。

{  
   "Records":[  
      {  
         "eventVersion":"2.0",
         "eventSource":"aws:s3",
         "awsRegion":"us-west-2",
         "eventTime":"1970-01-01T00:00:00.000Z",
         "eventName":"ObjectCreated:Put",
         "userIdentity":{  
            "principalId":"AIDAJDPLRKLG7UEXAMPLE"
         },
         "requestParameters":{  
            "sourceIPAddress":"127.0.0.1"
         },
         "responseElements":{  
            "x-amz-request-id":"C3D13FE58DE4C810",
            "x-amz-id-2":"FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
         },
         "s3":{  
            "s3SchemaVersion":"1.0",
            "configurationId":"testConfigRule",
            "bucket":{  
               "name":"sourcebucket",
               "ownerIdentity":{  
                  "principalId":"A3NL1KOZZKExample"
               },
               "arn":"arn:aws:s3:::sourcebucket"
            },
            "object":{  
               "key":"HappyFace.jpg",
               "size":1024,
               "eTag":"d41d8cd98f00b204e9800998ecf8427e",
               "versionId":"096fKKXTRTtl3on89fVO.nfljtsv6qko"
            }
         }
      }
   ]
}

Lambda 関数をテストする (AWS CLI)

  • Configure test event の内容をそのままコピペして、input.txtというファイルに保存する。

  • 次の Lambda CLI invoke コマンドを実行して関数を呼び出します。コマンドは非同期実行をリクエストします。オプションで、invocation-type パラメータ値として RequestResponse を指定することで、このコマンドを同期的に呼び出すこともできます。

$ aws lambda invoke \
--invocation-type Event \
--function-name CreateThumbnail \
--region us-west-2 \
--payload file://file-path/inputfile.txt \
--profile adminuser \
outputfile.txt

とりあえず、こちらも無事完了。

ここでは、awsのadminuserとして全ての処理を実行したが、実際は、S3バケットそのものに、lambda実行の権限を付与することになる。

この関数を呼び出すことができるのは、関数を呼び出すために独自の認証情報を使用しているためです。次のセクションでは、ユーザーに代わってこの関数を呼び出すように Amazon S3 を設定します。そのためには、関数を呼び出すための Amazon S3 アクセス権限を付与する Lambda 関数に関連付けられたアクセスポリシーに、アクセス権限を追加する必要があります。

  • サムネイルがターゲットバケットに作成されたことを確認し、以下のように AWS Lambda コンソールで Lambda 関数のアクティビティをモニタリングします。

これでとりあえず、テストまでは完了!意外と大変だなぁ(^ ^:)