AWS SAMで始めるサーバーレス開発: AWS SAMのチュートリアルを試してみた

AWS

2024.3.15

Topics

はじめに

こんにちは、Shunです。

皆さん、AWS SAM(AWS Serverless Application Model 以降、SAM)を利用されたことはありますか?

SAMは、サーバーレスアプリケーションの構築と管理を簡単にするためのフレームワークです。

これはCloudFormationをベースにしており、サーバーレス開発に特化した拡張を提供しています。

AWS SAM は、AWS SAM テンプレートと AWS SAM コマンドラインインターフェイス (AWS SAM CLI) の 2 つの部分で構成されています。AWS SAM テンプレートは、サーバーレスアプリケーション用の Infrastructure as Code (IaC) の定義に最適化された簡潔な構文を提供します。AWS CloudFormation の拡張機能として、AWS SAM テンプレートを AWS CloudFormation に直接デプロイできます。これにより、AWS での広範な IaC サポートの恩恵を受けることができます。AWS SAM CLI は、AWS SAM の機能をすぐに使えるようにするデベロッパーツールです。これを使用すると、サーバーレスアプリケーションをすばやく作成、開発、デプロイできます。AWS SAM の多くの機能には、ローカル開発とクラウドテストをスピードアップする SAM Accelerate や、AWS SAM を AWS CDK や Terraform などの他のツールに拡張する SAM CLI 統合などがあります。
引用: AWS Serverless Application Model

SAMを使用すると、必要なリソース、その関係性、および設定を1つのテンプレートファイルで定義できます。SAM CLIを利用することで、これらのアプリケーションをローカルでテストしたり、AWSにデプロイしたり、管理することが可能になります。

最近、SAMを使用する機会があったので、AWSが提供するチュートリアルをもとに実際の検証を行いました。

*チュートリアル: Hello World アプリケーションのデプロイ

この記事では、チュートリアルの内容を共有します。

前提

前提条件は以下です。

  • AWS CLIがセットアップ済みであること
  • AWS SAM CLIがセットアップ済みであること
  • Dockerがセットアップ済みであること

これらのセットアップがまだの方は、CloudShellを使用すると簡単です。

(DockerもCloudShell上で使えるようになりました。)

構成図

実施するアプリケーションの構成図は以下の通りです。

この構成を使用して、API GatewayとLambdaを構築し、hello worldメッセージをレスポンスとして受け取ります。

料金

本記事で紹介するチュートリアルでは料金は発生しません。

チュートリアル内容

以下の内容に沿って、実施します。

チュートリアル: Hello World アプリケーションのデプロイ

1. サンプルの Hello World アプリケーションを初期化する

SAMを開始するには、以下のコマンドを実行します。

$ sam init

実行すると、対話形式でセットアップ方法を選択していきます。

You can preselect a particular runtime or package type when using the `sam init` experience.
Call `sam init --help` to learn more.

# AWSのテンプレートを使用するか、自前のテンプレートを使用するかを聞かれます。AWSのテンプレート(1)を選択します。
Which template source would you like to use?
        1 - AWS Quick Start Templates
        2 - Custom Template Location
Choice: 1

# AWS のどのテンプレートを使用するかを聞かれます。今回は、Hello Worldのテンプレート(1)を選択します。
Choose an AWS Quick Start application template
        1 - Hello World Example
        2 - Data processing
        3 - Hello World Example with Powertools for AWS Lambda
        4 - Multi-step workflow
        5 - Scheduled task
        6 - Standalone function
        7 - Serverless API
        8 - Infrastructure event management
        9 - Lambda Response Streaming
        10 - Serverless Connector Hello World Example
        11 - Multi-step workflow with Connectors
        12 - GraphQLApi Hello World Example
        13 - Full Stack
        14 - Lambda EFS example
        15 - Hello World Example With Powertools for AWS Lambda
        16 - DynamoDB Example
        17 - Machine Learning
Template: 1

# ランタイムとパッケージのタイプを聞かれます。yを選択します。
Use the most popular runtime and package type? (Python and zip) [y/N]: y

# 今回は、簡単な検証のため、X-Rayは必要ありません。
Would you like to enable X-Ray tracing on the function(s) in your application?  [y/N]: N


# CloudWatch Application Insightsも同様に必要ありません。
Would you like to enable monitoring using CloudWatch Application Insights?
For more info, please view https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/cloudwatch-application-insights.html [y/N]: N

# ログも取得しません。
Would you like to set Structured Logging in JSON format on your Lambda functions?  [y/N]: N

# プロジェクト名を入力します。本記事では、デフォルトのsam-appをプロジェクト名としています。
Project name [sam-app]:[プロジェクト名を入力]

上記の入力が終わると、GitHubから以下のようにクローンされます。

Cloning from https://github.com/aws/aws-sam-cli-app-templates (process may take a moment)                                                                                                                                                                                                  

    -----------------------
    Generating application:
    -----------------------
    Name: sam-app
    Runtime: python3.9
    Architectures: x86_64
    Dependency Manager: pip
    Application Template: hello-world
    Output Directory: .
    Configuration file: sam-app/samconfig.toml
    
    Next steps can be found in the README file at sam-app/README.md
        

Commands you can use next
=========================
[*] Create pipeline: cd sam-app && sam pipeline init --bootstrap
[*] Validate SAM template: cd sam-app && sam validate
[*] Test Function in the Cloud: cd sam-app && sam sync --stack-name {stack-name} --watch

sam init以降は、作成したプロジェクトのディレクトリへ移動し、作業を行います。

2. アプリケーションを構築する

次に、アプリケーションを構築します。

以下のコマンドで、関数の依存関係、プロジェクトコードやプロジェクトファイルが整理されます。

$ sam build

実行結果は以下です。

Starting Build use cache                                                                                                                                                                                                                                                                   
Building codeuri: /home/cloudshell-user/eto-test/hello_world runtime: python3.9 metadata: {} architecture: x86_64 functions: HelloWorldFunction                                                                                                                                            
requirements.txt file not found. Continuing the build without dependencies.                                                                                                                                                                                                                
 Running PythonPipBuilder:CopySource                                                                                                                                                                                                                                                       
Skipping copy operation since source /home/cloudshell-user/eto-test/hello_world does not exist                                                                                                                                                                                             

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
# 次の章では、以下のコマンドを用いてAWSへデプロイを行います。 
[*] Deploy: sam deploy --guided

.aws-sam/build/template.yamlの中身は以下です。

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: 'sam-app

  Sample SAM Template for sam-app

  '
Globals:
  Function:
    Timeout: 3
    MemorySize: 128
    LoggingConfig:
      LogFormat: JSON
Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: HelloWorldFunction
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
      - x86_64
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get
    Metadata:
      SamResourceId: HelloWorldFunction
Outputs:
  HelloWorldApi:
    Description: API Gateway endpoint URL for Prod stage for Hello World function
    Value:
      Fn::Sub: https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/
  HelloWorldFunction:
    Description: Hello World Lambda Function ARN
    Value:
      Fn::GetAtt:
      - HelloWorldFunction
      - Arn
  HelloWorldFunctionIamRole:
    Description: Implicit IAM Role created for Hello World function
    Value:
      Fn::GetAtt:
      - HelloWorldFunctionRole
      - Arn

ハイライト箇所のAWS::Serverless::FunctionでLambdaに関連するリソースを定義しています。

CloudFormaitonであれば、IAMリソースを定義する必要がありますが、SAMではLambdaを実行するために必要なIAMロールを自動的に生成し、適切な権限を割り当てることができます。

それにより、テンプレートの記述量を減らし、Lambdaの実行に必要な権限管理を簡単に行うことができます。

3. アプリケーションをAWSへデプロイする

以下のコマンドを使用して、AWS環境へデプロイを行います。

$ sam deploy --guided

実行すると、対話形式で諸々聞かれます。

Configuring SAM deploy
======================

        Looking for config file [samconfig.toml] :  Found
        Reading default arguments  :  Success

        Setting default arguments for 'sam deploy'
        =========================================
# CloudFormaitonのスタックネームを入力します。
        Stack Name [sam-app]: 
# デプロイするリージョンを入力します。
        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
# IAMを作成するか問題ないかを問われます。必要なため、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
# ロールバックは行いたいため、Nとします。
        #Preserves the state of previously provisioned resources when an operation fails
        Disable rollback [y/N]: N
# Lambdaに権限はないが問題ないかを聞かれます。問題ないため、yとします。
        HelloWorldFunction has no authentication. Is this okay? [y/N]: y
# デプロイオプションの定義ファイルを作成するかを問われます。不要なため、nとします。
        Save arguments to configuration file [Y/n]: n

作成するリソースの確認画面になります。問題なければ、yとします。

        Looking for resources needed for deployment:

        Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-prvgzz2w4a1n
        A different default S3 bucket can be set in samconfig.toml and auto resolution of buckets turned off by setting resolve_s3=False
        Uploading to sam-app/e3c7ec584c3e043c5b3ac0b1d166480c  551464 / 551464  (100.00%)

        Deploying with following values
        ===============================
        Stack name                   : sam-app
        Region                       : ap-northeast-1
        Confirm changeset            : True
        Disable rollback             : False
        Deployment s3 bucket         : aws-sam-cli-managed-default-samclisourcebucket-prvgzz2w4a1n
        Capabilities                 : ["CAPABILITY_IAM"]
        Parameter overrides          : {}
        Signing Profiles             : {}

Initiating deployment
=====================

        Uploading to sam-app/2fc3f85cfbebff18a688b21b01b463b9.template  1199 / 1199  (100.00%)


Waiting for changeset to be created..

CloudFormation stack changeset
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Operation                                                             LogicalResourceId                                                     ResourceType                                                          Replacement                                                         
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
+ Add                                                                 HelloWorldFunctionHelloWorldPermissionProd                            AWS::Lambda::Permission                                               N/A                                                                 
+ Add                                                                 HelloWorldFunctionRole                                                AWS::IAM::Role                                                        N/A                                                                 
+ Add                                                                 HelloWorldFunction                                                    AWS::Lambda::Function                                                 N/A                                                                 
+ Add                                                                 ServerlessRestApiDeployment47fc2d5f9d                                 AWS::ApiGateway::Deployment                                           N/A                                                                 
+ Add                                                                 ServerlessRestApiProdStage                                            AWS::ApiGateway::Stage                                                N/A                                                                 
+ Add                                                                 ServerlessRestApi                                                     AWS::ApiGateway::RestApi                                              N/A                                                                 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:xxxxx:changeSet/samcli-deploy1710207813/786ffbee-9714-42eb-abee-b8d39a690789


Previewing CloudFormation changeset before deployment
======================================================
Deploy this changeset? [y/N]: y

これで作成完了です。ハイライト箇所は次章で使用します。

2024-03-12 01:49:12 - 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                                            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_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::Lambda::Permission                                               HelloWorldFunctionHelloWorldPermissionProd                            -                                                                   
CREATE_IN_PROGRESS                                                    AWS::ApiGateway::Deployment                                           ServerlessRestApiDeployment47fc2d5f9d                                 -                                                                   
CREATE_COMPLETE                                                       AWS::Lambda::Function                                                 HelloWorldFunction                                                    -                                                                   
CREATE_IN_PROGRESS                                                    AWS::Lambda::Permission                                               HelloWorldFunctionHelloWorldPermissionProd                            Resource creation Initiated                                         
CREATE_COMPLETE                                                       AWS::Lambda::Permission                                               HelloWorldFunctionHelloWorldPermissionProd                            -                                                                   
CREATE_IN_PROGRESS                                                    AWS::ApiGateway::Deployment                                           ServerlessRestApiDeployment47fc2d5f9d                                 Resource creation Initiated                                         
CREATE_COMPLETE                                                       AWS::ApiGateway::Deployment                                           ServerlessRestApiDeployment47fc2d5f9d                                 -                                                                   
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                                            sam-app                                                               -                                                                   
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

CloudFormation outputs from deployed stack
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Outputs                                                                                                                                                                                                                                                                                
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Key                 HelloWorldFunctionIamRole                                                                                                                                                                                                                                          
Description         Implicit IAM Role created for Hello World function                                                                                                                                                                                                                 
Value               arn:aws:iam::xxxxx:role/sam-app-HelloWorldFunctionRole-PkHjHeJFycab                                                                                                                                                                                         

Key                 HelloWorldApi                                                                                                                                                                                                                                                      
Description         API Gateway endpoint URL for Prod stage for Hello World function                                                                                                                                                                                                   
Value               https://7qt9u1y1jc.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/                                                                                                                                                                                            

Key                 HelloWorldFunction                                                                                                                                                                                                                                                 
Description         Hello World Lambda Function ARN                                                                                                                                                                                                                                    
Value               arn:aws:lambda:ap-northeast-1:xxxxx:function:sam-app-HelloWorldFunction-2AEAK6AzH6PM                                                                                                                                                                        
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------


Successfully created/updated stack - sam-app in ap-northeast-1

4. アプリケーションを実行する

デプロイしたアプリケーションの出力を確認します。

デプロイ時にOutputsHelloWorldApiが出力されています。

HelloWorldApiへGETリクエストを送ると、以下のようにhello worldが出力されます。

$ curl https://7qt9u1y1jc.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello world"}

5. 直接Lambdaを呼び出す

ここではAPIではなく、Lambdaを直接呼び出します。

以下のコマンドを打つことで、Lambdaを実行することができます。

$ sam remote invoke HelloWorldFunction --stack-name sam-app
Invoking Lambda Function HelloWorldFunction                                                                                                                                                                                                                                                
START RequestId: 14f3870f-aeb0-4393-b578-c82b20cd7e61 Version: $LATEST
END RequestId: 14f3870f-aeb0-4393-b578-c82b20cd7e61
REPORT RequestId: 14f3870f-aeb0-4393-b578-c82b20cd7e61  Duration: 1.07 ms       Billed Duration: 2 ms   Memory Size: 128 MB     Max Memory Used: 30 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

6. アプリケーションを変更してAWSに同期する

以下のコマンドを打つことでローカルとAWSを同期させることができます。

$ sam sync --watch

これでローカルで変更した内容がリアルタイムでAWSへ同期されます。そのため、開発環境以外での使用は推奨されていません。

挙動を検証するために、sam-app/hello_world/app.pyを変更します。

Hello WorldHello everyone!とします。

すると、ローカルの変更がすぐにAWS環境のLambdaへ反映されます。

$ curl https://7qt9u1y1jc.execute-api.ap-northeast-1.amazonaws.com/Prod/hello/
{"message": "hello everyone!"}

7. アプリケーションをローカルでテストする

ローカル環境へDockerがセットアップされていれば、ローカルでアプリケーションのテストを実施することができます。

まず、Lambdaのローカル環境を作成し、呼び出します。

$ sam local invoke
Invoking app.lambda_handler (python3.9)                                                                                                                                                                                                                                                    
Local image was not found.                                                                                                                                                                                                                                                                 
Removing rapid images for repo public.ecr.aws/sam/emulation-python3.9                                                                                                                                                                                                                      
Building image............................................................................................................................................................................................................................
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                           
Mounting /home/cloudshell-user/sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside runtime container                                                                                                                                                               
START RequestId: ce9f5304-4915-481e-a9e1-8fd57fa734f7 Version: $LATEST
END RequestId: bc8f3fd8-1663-40de-9594-ea829efc047a
REPORT RequestId: bc8f3fd8-1663-40de-9594-ea829efc047a  Init Duration: 0.16 ms  Duration: 81.85 ms      Billed Duration: 82 ms  Memory Size: 128 MB     Max Memory Used: 128 MB
{"statusCode": 200, "body": "{\"message\": \"hello world\"}"}

続いて、HTTP API エンドポイントをローカルでホストし、Lambdaを呼び出します。

$ sam local start-api
Initializing the lambda functions containers.                                                                                                                                                                                                                                              
Local image is up-to-date                                                                                                                                                                                                                                                                  
Using local image: public.ecr.aws/lambda/python:3.9-rapid-x86_64.                                                                                                                                                                                                                          
                                                                                                                                                                                                                                                                                           
Mounting /home/cloudshell-user/sam-app/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated, inside runtime container                                                                                                                                                               
Containers Initialization is done.                                                                                                                                                                                                                                                         
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-03-12 02:32:34 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-03-12 02:32:34 Press CTRL+C to quit

ローカルのAPIエンドポイントからもhello worldのレスポンスを確認することができました。

$ curl http://127.0.0.1:3000/hello
{"message": "hello world"}

8. AWSアプリケーションを削除する

最後に、作成したリソースを削除します。

以下のコマンドを実行することでリソースを削除します。

$ sam delete
# 対話形式でリソースを削除してよいか確認されます。
        Are you sure you want to delete the stack sam-app in the region ap-northeast-1 ? [y/N]: y
        Do you want to delete the template file 20ea9ca62b8332cc08fa5c96ebf5e715.template in S3? [y/N]: y
        - Deleting S3 object with key c6ce8fa8b5a97dd022ecd006536eb5a4                                                                                                                                                                                                                     
        - Deleting S3 object with key 5b3336c1cabd0374ab90521d9acb1965.template                                                                                                                                                                                                            
        - Deleting S3 object with key 20ea9ca62b8332cc08fa5c96ebf5e715.template                                                                                                                                                                                                            
        - Deleting Cloudformation stack sam-app

Deleted successfully

さいごに

今回は、SAMのチュートリアルを一通り実施してみました。

正直、SAMのサービス概要のみではどのようなサービスかイメージができなかったのですが、実際に手を動かすことでサービスイメージを掴むことができました。

本来は、開発環境を構築する必要がありますが、CloudShellを使えば、開発環境のセットアップ無しにSAMを体験することが可能です。

是非、SAMを試してみてください。

最後まで読んでいただきありがとうございます!

Shun

好きな言葉は生ビール199円です。日本ビール協会認定1冠、AWS12冠、Google Cloud11冠

Recommends

こちらもおすすめ

Special Topics

注目記事はこちら