AWS SAMのCLIであるaws-sam-cliを使うとローカルでLambda環境を作ってテストし、それをAWS上にデプロイできる。
ここではaws-sam-cliのインストールからローカルでのテスト、AWS上にデプロイするまでの手順を示す。
aws-sam-cliをインストールするOSはUbuntu 18.04とする。
- AWS Serverless Application Model (SAM) コマンドラインインターフェイス。サーバレスアプリケーションをローカルで構築、テスト、デバッグする (Amazon Web Services ブログ)
aws-sam-cliのインストールと動作確認
動作環境
aws-sam-cliを使うにあたりあらかじめ以下をインストールしておく。
⦿ Pytyoh 3.x
⦿pip
⦿Docker
⦿AWS CLI
$ python --version Python 3.6.8 $ pip --version pip 19.3.1 from /usr/local/lib/python3.6/dist-packages/pip (python 3.6) $ docker --version Docker version 18.09.7, build 2d0083d $ aws --version aws-cli/1.16.263 Python/3.6.8 Linux/4.15.0-65-generic botocore/1.12.253
aws-sam-cliインストール
aws-sam-cliはpipで簡単にインストールできる。
$ sudo pip install aws-sam-cli $ sam --version SAM CLI, version 0.22.0
サンプルアプリケーション作成(Python3.6)
aws-sam-cliがインストールできたらサンプルアプリケーションを作成してみる。
Lambdaは様々な言語で記述できるが、ここではPython3.6のサンプルアプリケーションを作成する。
$ sam init --runtime python3.6 --name sam-python [+] Initializing project structure... Project generated: ./sam-python Steps you can take next within the project folder =================================================== [*] Invoke Function: sam local invoke HelloWorldFunction --event event.json [*] Start API Gateway locally: sam local start-api Read sam-python/README.md for further instructions [*] Project initialization is now complete $ tree sam-python sam-python ├── README.md ├── events │ └── event.json ................. Lambdaに渡すイベントの定義 ├── hello_world │ ├── __init__.py │ ├── __pycache__ │ │ ├── __init__.cpython-36.pyc │ │ └── app.cpython-36.pyc │ ├── app.py ..................... Lambda関数本体 │ └── requirements.txt ├── template.yaml .................. SAMテンプレート └── tests └── unit ├── __init__.py ├── __pycache__ │ ├── __init__.cpython-36.pyc │ └── test_handler.cpython-36.pyc └── test_handler.py 6 directories, 12 files
⦿ 単独実行
アプリケーションができたら実行してみる。
$ cd sam-python $ sam local invoke HelloWorldFunction --event events/event.json --log-file lambda.log Invoking app.lambda_handler (python3.6) 2019-10-20 23:13:06 Found credentials in shared credentials file: ~/.aws/credentials Fetching lambci/lambda:python3.6 Docker container image...(略)... Mounting ~/sam-python/hello_world as /var/task:ro,delegated inside runtime container
実行結果はログファイルに出力される。
$ cat lambda.log START RequestId: 6eab94c3-2835-4241-9b97-b94b2bd60f2f Version: $LATEST END RequestId: 6eab94c3-2835-4241-9b97-b94b2bd60f2f REPORT RequestId: 6eab94c3-2835-4241-9b97-b94b2bd60f2f Duration: 0 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 19 MB {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}
--eventで指定したイベントの定義は以下のようにして作成できる。
$ sam local generate-event [OPTIONS] COMMAND [ARGS] > event.json
COMMANDには様々なAWSのサービスが指定でき、それぞれARGSが異なるのでhelpを参照する。
$ sam local generate-event --help : Commands: alexa-skills-kit alexa-smart-home apigateway batch cloudformation cloudfront cloudwatch codecommit codepipeline cognito config connect dynamodb kinesis lex rekognition s3 ses sns sqs stepfunctions
(S3用イベントの場合)
$ sam local generate-event s3 --help : Commands: delete Generates an Amazon S3 Delete Event put Generates an Amazon S3 Put Event $ sam local generate-event s3 put --help : $ sam local generate-event s3 put --help Usage: sam local generate-event s3 put [OPTIONS] Options: --region TEXT Specify the region name you'd like, otherwise the default = us-east-1 --partition TEXT Specify the partition name you'd like, otherwise the default = aws --bucket TEXT Specify the bucket name you'd like, otherwise the default = example-bucket --key TEXT Specify the key name you'd like, otherwise the default = test/key --debug Turn on debug logging to print debug message generated by SAM CLI. --help Show this message and exit.
⦿ API Gateway経由の実行
次にAPI Gateway経由で実行する。まずはAPI Gatewayを作成してリクエストを待ち受ける。
$ sam local start-api --log-file lambda.log Mounting HelloWorldFunction at http://127.0.0.1:3000/hello [GET] You can now browse to the above endpoints to invoke your functions. You do not need to restart/reload SAM CLI while working on your functions, changes will be reflected instantly/automatically. You only need to restart SAM CLI if you update your AWS SAM template 2019-10-20 23:15:33 * Running on http://127.0.0.1:3000/ (Press CTRL+C to quit)
この状態で別ターミナルからcurlでアクセスするとAPI Gateway経由でLambdaが起動する。
$ curl http://127.0.0.1:3000/hello {"message": "hello world"}
元ターミナルには以下のように出力される。
Invoking app.lambda_handler (python3.6) 2019-10-20 23:15:54 Found credentials in shared credentials file: ~/.aws/credentials Fetching lambci/lambda:python3.6 Docker container image...... Mounting /home/xxxxx/sam-python/hello_world as /var/task:ro,delegated inside runtime container No Content-Type given. Defaulting to 'application/json'. 2019-10-20 23:15:59 127.0.0.1 - - [20/Oct/2019 23:15:59] "GET /hello HTTP/1.1" 200 - -> Ctrl + cで中断
ログファイルには以下のように記録される。
$ cat lambda.log START RequestId: 7b951478-46f9-427a-a9fc-5c2ac8b9966f Version: $LATEST END RequestId: 7b951478-46f9-427a-a9fc-5c2ac8b9966f REPORT RequestId: 7b951478-46f9-427a-a9fc-5c2ac8b9966f Duration: 0 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 19 MB
またLambdaはDockerコンテナ上で実行されるのでDockerイメージがダウンロードされている。
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE lambci/lambda python3.6 2659a569a6df 2 weeks ago 866MB
⦿ ローカルエンドポイント経由の実行
ローカルエンドポイントを作成してAWS CLIから実行することもできる。
$ sam local start-lambda --log-file lambda.log Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template through the endpoint. 2019-10-21 00:12:59 * Running on http://127.0.0.1:3001/ (Press CTRL+C to quit)
この状態で別ターミナルからAWS CLIでLambdaを実行させる。
$ aws lambda invoke --function-name HelloWorldFunction --endpoint-url http://127.0.0.1:3001 out.txt { "StatusCode": 200 } $ cat out.txt {"statusCode": 200, "body": "{\"message\": \"hello world\"}"}
元ターミナルには以下のように出力される。
Invoking app.lambda_handler (python3.6) 2019-10-21 00:14:35 Found credentials in shared credentials file: ~/.aws/credentials Fetching lambci/lambda:python3.6 Docker container image...... Mounting /home/xxxxx/sam-python/hello_world as /var/task:ro,delegated inside runtime container 2019-10-21 00:14:40 127.0.0.1 - - [21/Oct/2019 00:14:40] "POST /2015-03-31/functions/HelloWorldFunction/invocations HTTP/1.1" 200 - -> Ctrl + cで中断
ログファイルには以下のように記録される。
$ cat lambda.log START RequestId: c3da9704-d7a4-45bf-b484-a0fd274c8036 Version: $LATEST END RequestId: c3da9704-d7a4-45bf-b484-a0fd274c8036 REPORT RequestId: c3da9704-d7a4-45bf-b484-a0fd274c8036 Duration: 0 ms Billed Duration: 100 ms Memory Size: 128 MB Max Memory Used: 19 MB
⦿ Node.jsのサンプルアプリケーション
他にも例えばNode.jsのサンプルアプリケーションを作成する場合も–runtimeの指定を変えるだけでよい。
$ sam init --runtime nodejs --name sam-nodejs [+] Initializing project structure... Project generated: ./sam-nodejs Steps you can take next within the project folder =================================================== [*] Invoke Function: sam local invoke HelloWorldFunction --event event.json [*] Start API Gateway locally: sam local start-api Read sam-nodejs/README.md for further instructions [*] Project initialization is now complete $ tree sam-nodejs sam-nodejs ├── README.md ├── events │ └── event.json ................. Lambdaに渡すイベントの定義 ├── hello-world │ ├── app.js ..................... Lambda関数本体 │ ├── package.json │ └── tests │ └── unit │ └── test-handler.js └── template.yaml .................. SAMテンプレート 4 directories, 6 files
Lambdaの実行方法は先のPythonの時と同様なので割愛する。
AWS上にデプロイ
AWS上にデプロイ
ローカルで動作確認できたのでCloudFormationでAWS上にデプロイする。
まずテンプレートの正当性を確認する。
$ sam validate 2019-10-21 01:14:36 Found credentials in shared credentials file: ~/.aws/credentials /home/xxxxx/sam-python/template.yaml is a valid SAM Template
問題がなければ上記のように「valid」になるのでS3バケットにアップロードする。ここではバケット名を「l-w-i.lambda」とする。
$ aws s3 mb s3://l-w-i.lambda $ sam package --template-file template.yaml --s3-bucket l-w-i.lambda --output-template-file packaged.yaml Uploading to c0e3fc815ba0ece850ad243e5994a832 1897 / 1897.0 (100.00%) Successfully packaged artifacts and wrote output template to file packaged.yaml. Execute the following command to deploy the packaged template aws cloudformation deploy --template-file /home/<user>/sam-python/packaged.yaml --stack-name <YOUR STACK NAME>
アップロードが終わったらデプロイを行う。
$ sam deploy --template-file packaged.yaml --stack-name sam-python --capabilities CAPABILITY_IAM Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - sam-python
これによりCloudFormationのスタックが作成され、Lambda関数がデプロイされる。
$ aws cloudformation describe-stacks --stack-name sam-python --query 'Stacks[].Outputs[1]' [ { "OutputKey": "HelloWorldApi", "OutputValue": "https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/", "Description": "API Gateway endpoint URL for Prod stage for Hello World function" } ]
API Gatewayのエンドポイントも作成されるのでcurlでアクセスしてみる。
$ curl https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello {"message": "hello world"} <pre class="brush:shell"> Lambdaが実行され、CloudWatch Logsにも実行ログが記録される。
デプロイしたLambda関数を削除する場合はCloudFormationのスタックを削除する。S3バケットとCloudWatch Logsのロググループは削除されないので別途削除する。
$ aws cloudformation delete-stack --stack-name sam-python
参考サイト
- AWS SAM情報 (Qiita)
元記事はこちら
「[Amazon Web Services] aws-sam-cliを使ってローカルでLambdaを動かし、AWS上にデプロイする」