ちょっと話題の記事

AWS再入門2022 AWS Serverless Application Model (AWS SAM)編

弊社コンサルティング部による『AWS 再入門ブログリレー 2022』の4日目のエントリでテーマはAWS Serverless Application Model (AWS SAM)です。
2022.02.04

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

こんにちは、リサリサです。

当エントリは弊社コンサルティング部による『AWS 再入門ブログリレー 2022』の 4日目のエントリです。

このブログリレーの企画は、普段 AWS サービスについて最新のネタ・深い/細かいテーマを主に書き連ねてきたメンバーの手によって、 今一度初心に返って、基本的な部分を見つめ直してみよう、解説してみようというコンセプトが含まれています。

AWSをこれから学ぼう!という方にとっては文字通りの入門記事として、またすでにAWSを活用されている方にとってもAWSサービスの再発見や2022年のサービスアップデートのキャッチアップの場となればと考えておりますので、ぜひ最後までお付合い頂ければ幸いです。

では、さっそくいってみましょう。4日目のテーマはAWS Serverless Application Model (AWS SAM)です。

今回のブログでは実際にチュートリアルもを実施しますのでぜひ一度やってみてください!

AWS Serverless Application Model (AWS SAM)とは?

AWS Serverless Application Model (以下AWS SAM) は、AWS で以下のようなサーバーレスアプリケーションを簡単に構築するために使用できるオープンソースのフレームワークです。

AWS CloudFormation の拡張機能になりますので、AWS CloudFormation が分からない方は、下記記事から、先にAWS CloudFormation を理解頂いておくといいと思います。

AWS SAM を使用する利点

AWS SAM でのサーバーレスアプリケーションの作成には以下のような利点があります。

単一のデプロイ構成

AWS SAM を使用すると、関連するコンポーネントやリソースの整理が容易になり、単一のスタック上で操作できるようになります。AWS SAM を使用すると、メモリやタイムアウトなどの設定をリソース間で共有し、単一のバージョン管理されたエンティティとしてすべての関連リソースを一緒にデプロイできます。

AWS CloudFormationの拡張

AWS SAM は AWS CloudFormation の拡張であるため、AWS CloudFormation の信頼性の高いデプロイ機能を利用できます。AWS CloudFormation テンプレートで AWS SAM を使用してリソースを定義できます。また、AWS CloudFormation で利用できるすべてのリソース、組み込み関数、およびその他のテンプレート機能も使用できます。

組み込みのベストプラクティス

AWS SAM を使用して、インフラストラクチャを設定として定義し、デプロイできます。これにより、コードレビューなどのベストプラクティスを使用し、実行できるようになります。

ローカルのデバッグとテスト

Docer をインストールすれば、AWS SAM テンプレートで定義されたサーバーレスアプリケーションのローカルでの構築、テスト、およびデバッグを実行できます。

開発ツールとの緊密な統合

AWS SAM は、サーバーレスアプリケーションを構築するための一連の AWS ツールと併用できます。サーバーレスアプリケーションのデプロイパイプラインを構築するには、CodeBuild、CodeDeploy、および CodePipeline を使用できます。AWS CodeStar を使用して、プロジェクト構造、コードリポジトリ、および自動的に設定される CI/CD パイプラインの使用を開始することもできます。サーバーレスアプリケーションをデプロイするには、Jenkins プラグインを使用できます。Stackery.io ツールキットを使用して、本番用のアプリケーションを構築できます。

AWS SAM の開始方法

IAM 許可と AWS 認証情報を設定する

AWS SAM は CLI で操作するものになるので、ローカル環境に AWS 認証情報の設定が必要になります。認証情報の設定が済んでいる(AWS CLI が使える状態)の方はスキップしてください。

設定がまだの方はAWS 認証情報のセットアップに従って、セットアップを行います。

Docker をインストールする (オプション)

Docker をインストールすると、ローカルでLambdaのテストが出来るようになります。今回はしませんが必要に応じて AWS SAM CLI のインストール の「ステップ 3: Docker をインストールする (オプション)」を参照して、インストールしてください。

AWS SAM CLI をインストールする

今回はUbuntu Server 18.04にインストールしました。他の環境の場合は、 AWS SAM CLI のインストール を参照してください。

$pip install aws-sam-cli
$sam --version
$SAM CLI, version 1.23.0

チュートリアルをやってみた

チュートリアル: Hello World アプリケーションのデプロイ をやってみました。以下のアプリケーションを作成します。get を叩くと「hello world」が返ってくる API です。

サンプル AWS SAM アプリケーションをダウンロードする

sam init コマンドではサーバーレスアプリケーションを初期化できます。今回は hello-world API のテンプレートをクローンしていきます。

対話式で選択肢が出るので、数字で選んでいきます。

$ 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.8
        3 - ruby2.7
        4 - go1.x
        5 - java11
        6 - dotnetcore3.1
        7 - nodejs12.x
        8 - nodejs10.x
        9 - python3.7
        10 - python3.6
        11 - python2.7
        12 - ruby2.5
        13 - java8.al2
        14 - java8
        15 - dotnetcore2.1
Runtime: 2

Project name [sam-app]: 

Cloning app templates 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: Template selection: Template selection: 1

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

SAM CLI update available (1.37.0); (1.23.0 installed)
To download: https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html

これで、hello-world API のテンプレートがクローンされました。

こんなファイルが自動で作られています。

$ tree
.
├── README.md
├── __init__.py
├── events
│   └── event.json
├── hello_world
│   ├── __init__.py
│   ├── app.py
│   └── requirements.txt
├── template.yaml
└── tests
    ├── __init__.py
    ├── integration
    │   ├── __init__.py
    │   └── test_api_gateway.py
    ├── requirements.txt
    └── unit
        ├── __init__.py
        └── test_handler.py

5 directories, 13 files

hello_world/app.py に Lambda のコードが入っています。

requirements.txt には、依存ライブラリが入っており、sam build すると解決できます。

template.yaml が AWS CloudFormation の構文を拡張した SAM 構文のテンプレートで、これを元にリソースを構築するようになります。以下のテンプレートで、Lambda と API Gateway が作成されます。

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

  Sample SAM Template for sam-app

# 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.8
      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

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

sam build コマンドは、アプリケーションが持つあらゆる依存関係を .aws-sam/build 下に構築します。

今回はランタイムをPythonにしているので、requirements.txt を解決してくれます。

$ sam build
Building codeuri: /mnt/c/vscode/sam-app/hello_world runtime: python3.8 metadata: {} 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
=========================
[*] Invoke Function: sam local invoke
[*] Deploy: sam deploy --guided

.aws-sam には以下のファイルが作成されました。

$ tree .aws-sam
.aws-sam
├── build
│   ├── HelloWorldFunction
│   │   ├── __init__.py
│   │   ├── app.py
│   │   ├── certifi
│   │   │   ├── __init__.py
│   │   │   ├── __main__.py
│   │   │   ├── cacert.pem
~略~
│   └── template.yaml
└── build.toml

アプリケーションを AWS クラウドにデプロイする

sam deploy コマンドでデプロイしていきます。初回は、--guided オプションを付けることで、対話式で、デプロイの設定を作りつつ、デプロイする事が出来ます。設定の samconfig.toml ファイルが作られるので、次回以降は、--guided オプションなしで deploy ができます。

$ 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 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
        HelloWorldFunction may not have authorization defined, Is this okay? [y/N]: y
        Save arguments to configuration file [Y/n]: y
        SAM configuration file [samconfig.toml]: 
        SAM configuration environment [default]: 
Enter MFA code for arn:aws:iam::123456789012:mfa/cm-kimura.risa: 

        Looking for resources needed for deployment: Found!

                Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-ikc487ot1fs7
                A different default S3 bucket can be set in samconfig.toml

        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 sam-app/f28f4bb6f24c12a2984f985b9f45998c  452537 / 452537  (100.00%)

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

Initiating deployment
=====================
Uploading to sam-app/e59ab6ef4171daa5f13a107fb80d0b4f.template  1089 / 1089  (100.00%)

Waiting for changeset to be created..

CloudFormation stack changeset
-----------------------------------------------------------------------------------------------------
Operation                 LogicalResourceId         ResourceType              Replacement             
-----------------------------------------------------------------------------------------------------
+ Add                     HelloWorldFunctionHello   AWS::Lambda::Permission   N/A                     
                          WorldPermissionProd                                                         
+ Add                     HelloWorldFunctionRole    AWS::IAM::Role            N/A                     
+ Add                     HelloWorldFunction        AWS::Lambda::Function     N/A                     
+ Add                     ServerlessRestApiDeploy   AWS::ApiGateway::Deploy   N/A                     
                          ment47fc2d5f9d            ment                                              
+ Add                     ServerlessRestApiProdSt   AWS::ApiGateway::Stage    N/A                     
                          age                                                                         
+ Add                     ServerlessRestApi         AWS::ApiGateway::RestAp   N/A                     
                                                    i                                                 
-----------------------------------------------------------------------------------------------------

Changeset created successfully. arn:aws:cloudformation:ap-northeast-1:12345678912:changeSet/samcli-deploy1643977195/cc05f8af-2d23-46b1-b97f-16d383d0bfb0


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

2022-02-04 21:21:36 - Waiting for stack create/update to complete

CloudFormation events from changeset
-----------------------------------------------------------------------------------------------------
ResourceStatus            ResourceType              LogicalResourceId         ResourceStatusReason    
-----------------------------------------------------------------------------------------------------
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::RestAp   ServerlessRestApi         -                       
                          i                                                                           
CREATE_IN_PROGRESS        AWS::ApiGateway::RestAp   ServerlessRestApi         Resource creation       
                          i                                                   Initiated               
CREATE_COMPLETE           AWS::ApiGateway::RestAp   ServerlessRestApi         -                       
                          i                                                                           
CREATE_IN_PROGRESS        AWS::Lambda::Permission   HelloWorldFunctionHello   -                       
                                                    WorldPermissionProd                               
CREATE_IN_PROGRESS        AWS::Lambda::Permission   HelloWorldFunctionHello   Resource creation       
                                                    WorldPermissionProd       Initiated               
CREATE_IN_PROGRESS        AWS::ApiGateway::Deploy   ServerlessRestApiDeploy   -                       
                          ment                      ment47fc2d5f9d                                    
CREATE_IN_PROGRESS        AWS::ApiGateway::Deploy   ServerlessRestApiDeploy   Resource creation       
                          ment                      ment47fc2d5f9d            Initiated               
CREATE_COMPLETE           AWS::ApiGateway::Deploy   ServerlessRestApiDeploy   -                       
                          ment                      ment47fc2d5f9d                                    
CREATE_IN_PROGRESS        AWS::ApiGateway::Stage    ServerlessRestApiProdSt   -                       
                                                    age                                               
CREATE_IN_PROGRESS        AWS::ApiGateway::Stage    ServerlessRestApiProdSt   Resource creation       
                                                    age                       Initiated               
CREATE_COMPLETE           AWS::ApiGateway::Stage    ServerlessRestApiProdSt   -                       
                                                    age                                               
CREATE_COMPLETE           AWS::Lambda::Permission   HelloWorldFunctionHello   -                       
                                                    WorldPermissionProd                               
CREATE_COMPLETE           AWS::CloudFormation::St   sam-app                   -                       
                          ack                                                                         
-----------------------------------------------------------------------------------------------------

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

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

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

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

↑出力の HelloWorldApi の Value が API の URL になるので、試しに叩いてみます。

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

正常にデプロイされました。

CloudFormtion スタックが作成されています。

中身はこんな感じです。

上記の通り、作成されたのは CloudFormaiton スタックなので、削除の際は、↑の「削除」から削除するか、以下の CloudFormation のコマンドで削除できます。

aws cloudformation delete-stack --stack-name sam-app

最後に

以上、『AWS 再入門ブログリレー 2022』の 4日目のエントリ『AWS SAM』編でした。

来週月曜日 (2/7) はたかくにさんの 「Terraform Public Modules」の予定です。お楽しみに!!