はじめに
この記事は アイレット株式会社 22新卒 Advent Calendar 2022 2日目の記事になります。
AWS SAMとは
AWS SAMとは、AWS サーバーレスアプリケーションモデル (Serverless Application Model)の略で、サーバーレスアプリケーションを構築するためのオープンソースフレームワークです。
AWS SAMでHello World!
今回は、AWS Lambda上でHello Worldする関数を作成します。
自宅のPCはWindowsなのでWindows用のドキュメントに従ってやっていきます。
Macの方はこちら→Mac用のドキュメント
AWS SAM CLIのインストール
Windowsの人はここからダウンロードできます。
msiファイルを実行して、インストールが完了したら
>> sam --version
正常にインストールされていたら
SAM CLI, version 1.59.0
みたいな出力が表示されると思います。
アプリケーションのデプロイ
sam init
>> sam init
今回はHello Worldがしたいので AWS Quick Start Templates で Hello World Example を選択します。
出力
You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Multi-step workflow
3 - Serverless API
4 - Scheduled task
5 - Standalone function
6 - Data processing
7 - Infrastructure event management
8 - Lambda EFS example
9 - Machine Learning
Template: 1
Use the most popular runtime and package type? (Python and zip) [y/N]: y
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: N
Project name [sam-app]: hello-world
Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)
-----------------------
Generating application:
-----------------------
Name: hello-world
Runtime: python3.9
Architectures: x86_64
Dependency Manager: pip
Application Template: hello-world
Output Directory: .
Next steps can be found in the README file at ./hello-world/README.md
Commands you can use next
=========================
[*] Create pipeline: cd hello-world && sam pipeline init --bootstrap
[*] Validate SAM template: cd hello-world && sam validate
[*] Test Function in the Cloud: cd hello-world && sam sync --stack-name {stack-name} --watch
実行が終わると大体以下のようなファイルが生成されていると思います。
hello-world/
├── README.md
├── events/
│ └── event.json
├── hello_world/
│ ├── __init__.py
│ ├── app.py
│ └── requirements.txt
├── template.yaml
└── tests/
└── unit/
├── __init__.py
└── test_handler.py
以下の3つのファイルが特に重要な役割のものです。
template.yaml: AWSリソースの定義をするファイル
hello_world/app.py: 実際のLambdaハンドラーのロジックを記述するファイル
hello_world/requirements.txt:アプリケーションが必要とするPython依存関係を記述するファイル
各ファイルの中身
テンプレートファイル
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
hello-world
Sample SAM Template for hello-world
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 60
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
上記コードは大きくGlobals,Resources,Outputsに分けられます。
Globals:アプリケーションに複数のFunctionが含まれる場合,そのすべてに共通する設定を記述する部分
Resources:各Functionごとの設定を記述する部分
Outputs:AWS SAMから出てくるものの定義。 エンドポイントなど。
関数本体
import json
def lambda_handler(event, context):
return {
"statusCode": 200,
"body": json.dumps({
"message": "hello world",
}),
}
requirements.txtは今回必要ないため割愛。
外部ライブラリが必要な場合は以下のように記述します。
#version指定がないと最新版をダウンロードしてくる
requests
#バージョン指定がある場合はその条件に従ってダウンロードしてくれる。
pytest >= 5.3.5
pandas == 1.2.4
ビルド
先ほど、sam initで作成したhello-worldディレクトリに移動して以下のコマンドを実行します。
>> sam build
Your template contains a resource with logical ID "ServerlessRestApi", which is a reserved logical ID in AWS SAM. It could result in unexpected behaviors and is not recommended.
Building codeuri: F:\AWS\hello-world\hello_world runtime: python3.8 metadata: {} architecture: x86_64 functions: HelloWorldFunction
Running PythonPipBuilder:ResolveDependencies
Running PythonPipBuilder:CopySource
Build Succeeded
Built Artifacts : .aws-sam\build
Built Template : .aws-sam\build\template.yaml
Commands you can use next
=========================
[*] Validate SAM template: sam validate
[*] Invoke Function: sam local invoke
[*] Test Function in the Cloud: sam sync --stack-name {stack-name} --watch
[*] Deploy: sam deploy --guided
ビルドに成功すると、次に実行できるコマンドのリストが出てくるのでいったんローカルで実行をテストしてみます。
ローカルテスト
※ローカルで関数を実行するためにはDockerが必要です。
導入方法
https://docs.docker.com/docker-for-windows/install/
Dockerでコンテナを立ち上げてから以下のコマンドを実行します。
>> sam local invoke
出力
START RequestId: bfd5e63c-6a78-4970-9445-d363c1a6ceed Version: $LATEST
END RequestId: bfd5e63c-6a78-4970-9445-d363c1a6ceed
REPORT RequestId: bfd5e63c-6a78-4970-9445-d363c1a6ceed Init Duration: 0.14 ms Duration: 133.35 ms Billed Duration: 134 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}
このようにデプロイを行う前にローカルでテストすることができます。
デプロイ
テストもできたので最後にデプロイします。
>> sam deploy --guided
出力
CloudFormation stack changeset
---------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
---------------------------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHelloWorl AWS::Lambda::Permission N/A
dPermissionProd
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeployment AWS::ApiGateway::Deployment N/A
47fc2d5f9d
+ Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A
+ Add ServerlessRestApi AWS::ApiGateway::RestApi N/A
---------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:222074562886:changeSet/samcli-deploy1669567629/e78e49c6-7c15-464b-b4fd-cd3dd97cfa3f
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2022-11-28 01:47:20 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 0.5 seconds)
---------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
---------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::CloudFormation::Stack sam-app User Initiated
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::IAM::Role HelloWorldFunctionRole Resource creation Initiated
CREATE_COMPLETE AWS::IAM::Role HelloWorldFunctionRole -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Resource creation Initiated
CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi -
CREATE_IN_PROGRESS AWS::ApiGateway::RestApi ServerlessRestApi Resource creation Initiated
CREATE_COMPLETE AWS::ApiGateway::RestApi ServerlessRestApi -
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment -
47fc2d5f9d
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorl -
dPermissionProd
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorl Resource creation Initiated
dPermissionProd
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment Resource creation Initiated
47fc2d5f9d
CREATE_COMPLETE AWS::ApiGateway::Deployment ServerlessRestApiDeployment -
47fc2d5f9d
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage -
CREATE_IN_PROGRESS AWS::ApiGateway::Stage ServerlessRestApiProdStage Resource creation Initiated
CREATE_COMPLETE AWS::ApiGateway::Stage ServerlessRestApiProdStage -
CREATE_COMPLETE AWS::Lambda::Permission HelloWorldFunctionHelloWorl -
dPermissionProd
CREATE_COMPLETE AWS::CloudFormation::Stack sam-app -
---------------------------------------------------------------------------------------------------------------------
CloudFormation outputs from deployed stack
---------------------------------------------------------------------------------------------------------------------
Outputs
---------------------------------------------------------------------------------------------------------------------
Key HelloWorldFunctionIamRole
Description Implicit IAM Role created for Hello World function
Value #######################################
Key HelloWorldApi
Description API Gateway endpoint URL for Prod stage for Hello World function
Value #######################################
Key HelloWorldFunction
Description Hello World Lambda Function ARN
Value #######################################
---------------------------------------------------------------------------------------------------------------------
30秒ほどでAWS上にデプロイができました。
簡単に出来過ぎて本当にできてるのか心配なので試しに叩いてみます。
>> curl https://c28gdrpdtb.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}
APIを叩いて値を持ってくることができました🙌
さいごに
今回はHello World関数だけの簡単な構成でしたが、もっと複雑になった際にこんな感じでIac化しておくと管理が楽になるなぁと感じました。
個人的にAWS Lambdaはお気に入りサービスなので、これからSAMをバリバリ活用して開発していこうと思います。
アイレット株式会社 22新卒 Advent Calendar 2022 3日目はMiuraくんが担当です! お楽しみに!
おまけ
先日、社内Slackでサム君(リス)かわいいってつぶやいていたら、上司の方からAWS SAMのステッカーをいただきました🥰
この世にはサム君のTシャツも存在しているみたいなのでいつか手に入れたい・・・
https://twitter.com/awscloud/status/857670730464370688!