前回までの環境構築では、Ubuntu18.04上にLocalStack、aws-cliのインストールを行いました。今回は実際にブラウザからAPI Gatewayを通してLambda関数を起動する方法を記載します。
API Gatewayとは
API Gatewayとは、Webサービスの一部を外部からアクセス可能とするための機能です。外部へアクセス方法としてREST APIに準拠したインターフェースを公開します。これにより、APIGatewayに対してブラウザからアクセスが可能となります。外部から制御を行いたい機能の数だけAPI Gatewayのインターフェースを公開することでWebサービスの保守・管理、モニタリング等を柔軟に行うことができます。
Lambda関数とは
API Gatewayは外部とのゲートウェイ(インターフェース)であり、プログラムを実行することはできません。そこで、API Gatewayから呼び出し可能なプログラムとしてLambda関数を利用します。
Lambda関数とはサーバーレスのプログラムであり、APIGatwayから呼び出されるまでは処理を行うサーバーを持ちません。言い換えると、API Gatewayからアクセスされた場合のみサーバーが与えられ、プログラムが終了すると再びサーバが未割当の状態となります。
この仕組みにより、サーバーへのアクセスが無い状態ではサーバーの利用料を抑えることがでるというメリットがあります。一方で、実行の度にサーバーを割り当てる必要があるため、プログラムの起動に時間がかかるというデメリットが存在します。
※Lambda起動時間はVPC内外で大きく異なりますがここでは省略します。
Lambda関数の作成
Lambda関数作成手順
おおまかな手順はAWS公式から確認することができます。ここではLocalStack用にいくつか変更し記載しています。
下記のようなLambda関数を作成します。
import json
def handler(event, context):
return {
'statusCode' : 200,
'headers' : {
'content-type' : 'text/html'
},
'body' : event['queryStringParameters']['a']
}
上記のファイルを”lambda_environment.py”というファイル名で保存します。
作業用ディレクトリ”lambda_func”を作成し、その中へコピーします。
mkdir lambda_func
cp lambda_environment.py lambda_func
cd lambda_func
ディレクトリの中は下記のようになります。
ls
lambda_environment.py
続いて、プログラムをzipファイルへ圧縮(アーカイブ)します。
zip lambda_environment.zip *
下記が表示されると成功です。
adding: lambda_environment.py (deflated 39%)
下記のようにzipコマンドが無いと怒られた場合はインストールしましょう。
“Command ‘zip’ not found, but can be installed with:”
sudo apt-get install zip
次に、awsコマンドを用いてLambda関数を作成していきます。
LocalStack内のLambdaサービスに対して処理を行うため、エンドポイントのポート番号として”4574″を指定します。
aws lambda create-function --function-name lambda_function_handler --runtime python3.7 --handler lambda_environment.handler --memory-size 128 --zip-file fileb://lambda_environment.zip --role arn:aws:iam::123456:role/role-name --endpoint-url=http://localhost:4574 --region us-east-1 --profile localstack
成功すると下記のように表示されます。
{
"FunctionName": "lambda_function_handler",
"FunctionArn": "arn:aws:lambda:us-east-1:000000000000:function:lambda_function_handler",
"Runtime": "python3.7",
"Role": "arn:aws:iam::123456:role/role-name",
"Handler": "lambda_environment.handler",
"CodeSize": 374,
"Description": "",
"Timeout": 3,
"MemorySize": 128,
"LastModified": "2020-04-30T09:07:20.672+0000",
"CodeSha256": "2VkNhokaMQ2S6bIxUfF3HIypCC4HY7jxAzd0707p0E4=",
"Version": "$LATEST",
"TracingConfig": {
"Mode": "PassThrough"
},
"RevisionId": "ff84ec72-4612-44ab-9051-b603dcc38bd6",
"State": "Active",
"LastUpdateStatus": "Successful"
}
後に、Lambda関数ハンドラのURIを利用するため環境変数に格納します。
このとき、”FunctionArn”の”arn:aws:lambda:us-east-1:000000000000:function:lambda_function_handler lambda_function_handler”は登録するLambda関数名により変化しますのでご自身の環境に合わせて設定して下さい。
export URI=arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:lambda_function_handler/invocations
よく発生するエラー
よく発生するエラーをまとめます。
- 同じLambda関数名を複数登録した場合のエラー
An error occurred (ResourceConflictException) when calling the CreateFunction operation: Function already exist: lambda_function_handler
登録済みのLambda関数が存在するかどうかを確認することができます。
aws lambda list-functions --endpoint-url=http://localhost:4574 --region us-east-1 --profile localstack
登録済みのLambda関数を削除することができます。
aws lambda delete-function --function-name lambda_function_handler --endpoint-url=http://localhost:4574 --region us-east-1 --profile localstack
- –handlerへ指定するpythonファイル名が間違っている場合のエラー
An error occurred (ValidationError) when calling the CreateFunction operation: Unable to find handler script (/tmp/localstack/zipfile.4dfbb6b8/lambda_enviro
nment_.py) in Lambda archive. Config for local mount, docker, remote: "False", "True", "True"
- –zip_fileが存在しない場合のエラー
Error parsing parameter '--zip-file': Unable to load paramfile fileb://lambda_function_.zip: [Errno 2] No such file or directory: 'lambda_function_.zip'
API Gatewayの作成
API Gateway作成手順
はじめに、外部からアクセスを可能とするためのREST APIを作成します。LocalStack内のAPI Gatewayサービスに対して処理を行うため、エンドポイントのポート番号として”4567″を指定します。
aws apigateway create-rest-api --name 'My First API' --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
実行後、生成したREST API IDが表示されます。
{
"id": "abdy85e05g",
"name": "My First API",
"createdDate": 1588237751,
"apiKeySource": "HEADER",
"endpointConfiguration": {
"types": [
"EDGE"
]
},
"tags": {}
}
以降の処理でこのREST API IDを利用しますので、環境変数へ登録します。
export REST_API_ID=abdy85e05g
次にルートリソースIDを取得します。
aws apigateway get-resources --rest-api-id $REST_API_ID --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
下記のようにルートリソースIDが表示されます。
{
"items": [
{
"id": "u2gvz3prq5",
"path": "/"
}
]
}
ルートリソースIDも以降の処理で利用しますので、環境変数へ登録します。
export ROOT_RESOURCE_ID=u2gvz3prq5
次に、”env_test”というパスでAPI Gatewayリソースを作成します。
aws apigateway create-resource --rest-api-id $REST_API_ID --parent-id $ROOT_RESOURCE_ID --path-part env_test --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
下記のように表示されます。
{
"id": "xuckh8op49",
"parentId": "u2gvz3prq5",
"pathPart": "env_test",
"path": "/env_test"
}
リソースIDも以降で使用するため保持します
export RESOURCE_ID=xuckh8op49
次に、httpに対するGET用のAPIリクエストメソッドを作成します。
aws apigateway put-method --rest-api-id $REST_API_ID --resource-id $RESOURCE_ID --http-method GET --authorization-type "NONE" --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
{
"httpMethod": "GET",
"authorizationType": "NONE",
"apiKeyRequired": false
}
Lambda関数とAPI Gatewayを統合セットアップします。
aws apigateway put-integration --rest-api-id $REST_API_ID --resource-id $RESOURCE_ID --http-method GET --type AWS_PROXY --integration-http-method POST --uri $URI --passthrough-behavior WHEN_NO_MATCH --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
下記が表示されると成功です。
{
"type": "AWS_PROXY",
"httpMethod": "POST",
"uri": "arn:aws:apigateway:us-east-1:lambda:path/2015-03-31/functions/arn:aws:lambda:us-east-1:000000000000:function:lambda_function_handler/invocations",
"integrationResponses": {
"200": {
"statusCode": 200,
"responseTemplates": {
"application/json": null
}
}
}
}
APIをtestステージにデプロイします。
aws apigateway create-deployment --rest-api-id $REST_API_ID --stage-name test --endpoint-url=http://localhost:4567 --region us-east-1 --profile localstack
{
"id": "3wf5f7zcd3",
"description": "",
"createdDate": 1588238159
}
動作確認
curlコマンドを用い、APIGatewayからLambda関数が呼び出されることを確認します。
curl http://localhost:4567/restapis/$REST_API_ID/test/_user_request_/env_test?a=333
上記は引数aに333を指定するという意味になりますので、下記のように333が表示されると成功です。
333
ブラウザからも確認できます。
ブラウザへ設定する際は$REST_API_IDを実際に値に変換してURLを設定する必要があります。
http://localhost:4567/restapis/abdy85e05g/test/user_request/env_test?a=333

- Lambda関数作成
- API Gatewayに対するREST API作成
- curl、ブラウザによる表示確認
コメント