AWS Serverless Application Model(SAM)で、AWS Lambda関数とAmazon API Gatawayをデプロイしてみた
AWS LambdaをIaCで管理したい
おのやんです。
みなさん、AWS Lambda(以下、Lambda)をコードで管理したいと思ったことはありませんか?私はあります。
AWSインフラをコードで管理することは、一般的にInfrastructure as Code(以下、IaC)と呼ばれる運用管理手法のひとつです。AWSをIaCで管理する際は、AWS CloudFormationやAWS CDK、Terraformなどの選択肢があります。
そんなIaCですが、Lambdaなどインフラリソースとプログラムのコードが密接に関連しているリソースの場合、インフラリソースだけでなくコードも一緒に管理したい場面があります。そんな場合は、 AWS Serverless Application Model(以下、SAM) が候補に上がっていきます。
このSAMを用いて、今回Lambdaを実装する機会がありましたので、今回はそちらを紹介していきます。
SAMとは
SAMは、サーバーレスアプリケーションをIaCで管理できるフレームワークです。SAMのテンプレートはCloudFormation テンプレートの拡張版になっていて、LambdaやAPI Gatewayなどのインフラリソースに加えて、アプリケーションコードなども一緒にデプロイできます。
準備
前提として、AWS CLIのインストール・認証設定が済んでいる必要があります。こちらの設定を済ませておきます。
上記が設定されている状態で、SAMを用いてリソースをデプロイする時に必要になるAWS SAM CLI(以下、SAM CLI)をインストールします。詳細はこちらの公式ドキュメントに掲載されているので、参考にしてください。
私は今回MacでSAM CLIをインストールする必要があったため、公式ドキュメントにならってPKGファイルをダウンロードして展開しています(執筆時点で、Homebrewによるインストールは公式ドキュメントに書かれていないため注意してください)。
ローカル環境での動作確認
それでは、実際に構築していきます。今回のディレクトリ構成は以下のようになります。
aws-test-sam-sample/
│── template.yaml
└── hello_world/
└── app.py
template.yaml
の内容は以下の通りです。AWS::Serverless::Function
の設定でLambda関数が作成され、そのコードとしてhello_world
内のapp.py
が参照されます。またEvents
の項目で設定しているType: Api
により、Amazon API Gateway(以下、API Gateway)が自動で作成されます。
AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: Hello World API
#---------------------------------------------#
# Lambda function
#---------------------------------------------#
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: hello_world/
Handler: app.lambda_handler
Runtime: python3.9
#---------------------------------------------#
# API gateway
#---------------------------------------------#
Events:
HelloWorld:
Type: Api
Properties:
Path: /hello
Method: get
この状態でsam local start-api
コマンドを実行することで、ローカルでAPIをテストできます。
% sam local start-api
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. If you used sam build before running local commands, you
will need to re-run sam build for the changes to be picked up. You only need to restart SAM CLI if you update your AWS SAM
template
2024-08-13 11:26:54 WARNING: This is a development server. Do not use it in a production deployment. Use a production WSGI server instead.
* Running on http://127.0.0.1:3000
2024-08-13 11:26:54 Press CTRL+C to quit
ローカルでサーバーが起動できたら、上記のアドレスにテンプレートで指定したPathを繋げたhttp://127.0.0.1:3000/hello
や、http://localhost:3000/hello
にブラウザからアクセスすることで、リクエストを送信できます。
AWS環境へのデプロイ
この動作確認ができたら、AWS環境へ実際にデプロイしてみましょう。
SAM経由でAWSにデプロイするには、まずビルドを行います。
% sam build
Building codeuri: /Users/xxx/aws-test-sam-sample/hello_world runtime: python3.9 metadata: {} architecture:
x86_64 functions: HelloWorldFunction
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
=========================
[*] 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
ビルドが正常に終了すると、ルートディレクトリに.aws-sam
ディレクトリが作成されます。この中に、デプロイの際に必要なアプリケーションのビルドアーティファクト(ソースコードやテンプレートファイル、デプロイ設定ファイルなど)が作成されています。
ビルドが完了したら、デブロイを実行します。アプリケーションを初めてデプロイする場合は、sam deploy --guided
を使用してデプロイ設定を構成します。2回目以降のデプロイ時は、sam deploy
でOKです。
デプロイログが結構な量表示されるので、トグル下に入れています。
デプロイログ
% sam deploy --guided
Configuring SAM deploy
======================
Looking for config file [samconfig.toml] : Not found
Setting default arguments for 'sam deploy'
=========================================
Stack Name [sam-app]: aws-test-sam-sample
AWS Region [ap-northeast-1]: 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]: y
HelloWorldFunction has no authentication. Is this okay? [y/N]: y
Save arguments to configuration file [Y/n]: Y
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
Looking for resources needed for deployment:
Creating the required resources...
Successfully created!
Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxx
A different default S3 bucket can be set in samconfig.toml and auto resolution of buckets turned off by setting resolve_s3=False
Saved arguments to config file
Running 'sam deploy' for future deployments will use the parameters saved above.
The above parameters can be changed by modifying samconfig.toml
Learn more about samconfig.toml syntax at
https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html
Uploading to aws-test-sam-sample/xxxx 237 / 237 (100.00%)
Deploying with following values
===============================
Stack name : aws-test-sam-sample
Region : ap-northeast-1
Confirm changeset : True
Disable rollback : True
Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxx
Capabilities : ["CAPABILITY_IAM"]
Parameter overrides : {}
Signing Profiles : {}
Initiating deployment
=====================
Uploading to aws-test-sam-sample/xxxx.template 562 / 562 (100.00%)
Waiting for changeset to be created..
CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------
Operation LogicalResourceId ResourceType Replacement
-------------------------------------------------------------------------------------------------------------------------
+ Add HelloWorldFunctionHelloWorld AWS::Lambda::Permission N/A
PermissionProd
+ Add HelloWorldFunctionRole AWS::IAM::Role N/A
+ Add HelloWorldFunction AWS::Lambda::Function N/A
+ Add ServerlessRestApiDeployment4 AWS::ApiGateway::Deployment N/A
xxxx
+ Add ServerlessRestApiProdStage AWS::ApiGateway::Stage N/A
+ Add ServerlessRestApi AWS::ApiGateway::RestApi N/A
-------------------------------------------------------------------------------------------------------------------------
Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:123456:changeSet/samcli-deploy123459/xxx-xxx-xxx
Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y
2024-08-13 12:20:25 - Waiting for stack create/update to complete
CloudFormation events from stack operations (refresh every 5.0 seconds)
-------------------------------------------------------------------------------------------------------------------------
ResourceStatus ResourceType LogicalResourceId ResourceStatusReason
-------------------------------------------------------------------------------------------------------------------------
CREATE_IN_PROGRESS AWS::CloudFormation::Stack aws-test-sam-sample 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_IN_PROGRESS AWS::Lambda::Function HelloWorldFunction Eventual consistency check
initiated
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 ServerlessRestApiDeployment4 -
xxxxxx
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorld -
xxxxxx
CREATE_IN_PROGRESS AWS::Lambda::Permission HelloWorldFunctionHelloWorld Resource creation Initiated
PermissionProd
CREATE_COMPLETE AWS::Lambda::Function HelloWorldFunction -
CREATE_COMPLETE AWS::Lambda::Permission HelloWorldFunctionHelloWorld -
PermissionProd
CREATE_IN_PROGRESS AWS::ApiGateway::Deployment ServerlessRestApiDeployment4 Resource creation Initiated
xxxxxx
CREATE_COMPLETE AWS::ApiGateway::Deployment ServerlessRestApiDeployment4 -
xxxxxx
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::CloudFormation::Stack aws-test-sam-sample -
-------------------------------------------------------------------------------------------------------------------------
Successfully created/updated stack - aws-test-sam-sample in ap-northeast-1
正常にデプロイされると、こちらのようにLambda関数が作成されます。
API Gatewayも作成されます。
裏ではAWS CloudFormationのスタックが作成されています。
LambdaのコンソールからURLを確認し、<エンドポイント>/Prod/hello
でブラウザからアクセスすると、ローカルで検証した時と同じレスポンスを返す動作を確認できます。
SAMは、サーバーレスアプリケーションもデプロイできる拡張版CFn
テンプレートの基本的な書き方はCFnとほぼ同じですので、普段からCFnを使用しているユーザーなら、その延長線上で簡単にデプロイできる印象です。
SAMでlambdaなどをデプロイする時は、SAM CLIによるビルドからデプロイまでの一連の流れなどを把握しておきましょう。では!