この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
AWS SAM(Serverless Application Model)を利用してAPI Gateway + Lambdaなどのリソース一式をデプロイすることはよくあるかと思います。理由あって他のリソースに一切紐付かない単体のLambda関数をデプロイする機会がありましたのでテンプレートの例を紹介します。
Lambda単体が必要ならマネージメントコンソールから作成した方が早いのでは?というのは至極当然のご意見なのですが、検証の都合SAMから生み出す必要がありました。
実行環境
$ sam --version
SAM CLI, version 1.36.0
本検証で利用したコード一式は以下に置いてあります。
初期設定
sam init
コマンドでHello World Example
のサンプルテンプレートで初期化しました。
$ sam init
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
What package type would you like to use?
1 - Zip (artifact is a zip uploaded to S3)
2 - Image (artifact is an image uploaded to an ECR image repository)
Package type: 1
Which runtime would you like to use?
1 - nodejs14.x
2 - python3.9
3 - ruby2.7
4 - go1.x
5 - java11
6 - dotnetcore3.1
7 - nodejs12.x
8 - nodejs10.x
9 - python3.8
10 - python3.7
11 - python3.6
12 - python2.7
13 - ruby2.5
14 - java8.al2
15 - java8
16 - dotnetcore2.1
Runtime: 2
Project name [sam-app]: lambda-alone
Cloning from https://github.com/aws/aws-sam-cli-app-templates
AWS quick start application templates:
1 - Hello World Example
2 - EventBridge Hello World
3 - EventBridge App from scratch (100+ Event Schemas)
4 - Step Functions Sample App (Stock Trader)
5 - Elastic File System Sample App
Template selection: 1
-----------------------
Generating application:
-----------------------
Name: lambda-alone
Runtime: python3.9
Architectures: x86_64
Dependency Manager: pip
Application Template: hello-world
Output Directory: .
Next application steps can be found in the README file at ./lambda-alone/README.md
Commands you can use next
=========================
[*] Create pipeline: cd lambda-alone && sam pipeline init --bootstrap
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
Lambda単体をデプロイするまで
サンプルのテンプレートをベースにテンプレートの修正と、関数を編集してAWSへデプロイしてみます。
テンプレート修正
Events:
のType: API
でAPI Gatewayと連携する設定が入っています。何も紐付けたくないLambdaの場合はEvetns:
以下を削除すればOKです。あとはEvents
に関連したOutput
があるので忘れずに削除。
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
hellow-sample
Sample SAM Template for hellow-sample
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 3
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # More info about API Event Source: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#api
Properties:
Path: /hello
Method: get
Outputs:
# ServerlessRestApi is an implicit API created out of Events key under Serverless::Function
# Find out more about other implicit resources you can reference within SAM
# https://github.com/awslabs/serverless-application-model/blob/master/docs/internals/generated_resources.rst#api
HelloWorldApi:
Description: "API Gateway endpoint URL for Prod stage for Hello World function"
Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
HelloWorldFunction:
Description: "Hello World Lambda Function ARN"
Value: !GetAtt HelloWorldFunction.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for Hello World function"
Value: !GetAtt HelloWorldFunctionRole.Arn
変更箇所
少し手直してシンプルなテンプレートにしました。
FunctionName:
を追加しLambda関数名を任意の名前に設定arm64
Graviton2を採用Events:
の丸ごと削除CodeUri
のディレクトリ名を変更Outputs
でEvents
内のAPI Gatewayに関する出力内容があっため削除
template.yaml
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
lambda-alone
Sample SAM Template for lambda-alone
Globals:
Function:
Timeout: 5
Resources:
Function:
Type: AWS::Serverless::Function
Properties:
FunctionName: "lambda-alone"
CodeUri: ./lambda-alone
Handler: app.lambda_handler
Runtime: python3.9
Architectures:
- arm64
Outputs:
HelloWorldFunction:
Description: "Lambda Function ARN"
Value: !GetAtt Function.Arn
HelloWorldFunctionIamRole:
Description: "Implicit IAM Role created for function"
Value: !GetAtt FunctionRole.Arn
Memo
最小限のテンプレートを目指してOutputs:
の内容は欲していなかったので全削除しました。sam deploy
すると以下のエラーのメッセージが表示されました。SAMのテンプレートはOutput
がnull
になることを許さないことを知りました。
Error: Failed to create changeset for the stack: lambda-test, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state: For expression "Status" we matched expected path: "FAILED" Status: FAILED. Reason: [/Outputs] 'null' values are not allowed in templates
sam local start-lambda
コマンドでローカルのエンドポイントから呼び出せるのか試してみました。
$ sam local start-lambda
Starting the Local Lambda Service. You can now invoke your Lambda Functions defined in your template through the endpoint.
2021-12-04 11:55:45 * Running on http://127.0.0.1:3001/ (Press CTRL+C to quit)
2021-12-04 11:55:57 127.0.0.1 - - [04/Dec/2021 11:55:57] "GET / HTTP/1.1" 404 -
API Gatewayも何もないのでLambdaを呼び出しようがないですよね。
$ curl http://127.0.0.1:3001/
{"Type": "LocalService", "Message": "PathNotFoundException"}⏎
sam local invoke
コマンドでLambdaを呼べるか試してみます。こちらはLambdaを実行して意図したレスポンスが返ってきました。
$ sam local invoke
...snip...
REPORT RequestId: 090ff64d-7513-43b5-8594-a4150280d2af Init Duration: 3.18 ms Duration: 1342.88 ms Billed Duration: 1343 msMemory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"Welcome to ABASHIRI city.\"}"}⏎
...snip...
Build & Deploy
ビルドしてデプロイします。
$ sam build
Building codeuri: /Users/ohmura.yasutaka/aws/ohmura.yasutaka/work/sam/targetgroup-lambda/lambda-alone/lambda-alone runtime: python3.9 metadata: {} architecture: arm64 functions: ['Function']
requirements.txt file not found. Continuing the build without dependencies.
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam/build
Built Template : .aws-sam/build/template.yaml
Commands you can use next
=========================
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided
初回のデプロイなのでガイドに従い設定してデプロイします。
$ sam deploy --guided
...snip...
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: lambda-alone
AWS Region [ap-northeast-1]:
#Shows you resources changes to be deployed and require a 'Y' to initiate deploy
Confirm changes before deploy [y/N]: y
#SAM needs permission to be able to create roles to connect to the resources in your template
Allow SAM CLI IAM role creation [Y/n]: y
#Preserves the state of previously provisioned resources when an operation fails
Disable rollback [y/N]: n
Save arguments to configuration file [Y/n]: y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
...snip...
マネージメントコンソールから確認
リソースベースポリシーも何もありません。これだとテスト実行しか呼び出しようがないです。
テスト実行は成功しました。SAMから単体のLambdaをデプロイできることを確認できました。
おわりに
Lambda単体をSAMから生み出したかったのですが情報がなく「もしやそんな使い方しないからできなかったりする?」と不安になりました。普通はやらなさそうなので「できました」という結果を書き留めておきます。どなたかの不安解消につながれば幸いです。