AWSサーバーレスアプリケーションモデルの紹介

1概要

前の記事 では、RESTエンドポイント用のAPI Gateway、ビジネスロジック用のAWS Lambdaを使用して、既にフルスタックサーバーレスアプリケーションをAWSに実装しましたデータベースとしてDynamoDBとして。

ただし、展開は多くの手動の手順で構成されているため、複雑さが増したり環境の数が増えたりすると、不便になる可能性があります。

このチュートリアルでは、テンプレートベースの説明とAWS上でのサーバーレスアプリケーションの自動デプロイを可能にする** AWSサーバーレスアプリケーションモデル(SAM)の使用方法について説明します。

詳しくは、次のトピックを見ていきます。

  • サーバーレスアプリケーションモデル(SAM)の基本、および

基礎となるCloudFormation SAMテンプレート構文を使用した、サーバレスアプリケーションの定義

  • CloudFormation CLIを使用したアプリケーションの自動デプロイメント

2基本

以前 で説明したように、AWSでは、API Gateway、Lambda関数、およびDynamoDBを使用して、サーバーレスアプリケーションを完全に実装できます。間違いなく、これはパフォーマンス、コスト、およびスケーラビリティの面ですでに多くの利点をもたらします。

ただし、各機能の作成、コードのアップロード、DynamoDBテーブルの作成、IAMロールの作成、APIとAPI構造の作成など、現時点ではAWSコンソールで多くの手動手順が必要になることが欠点です。

複雑なアプリケーションやテスト、ステージング、プロダクションのような複数の環境では、その作業はすぐに倍増します。

これが、AWS全般のアプリケーション用のCloudFormation、および特にサーバーレスアプリケーション用のServerless Application Model(SAM)が登場するところです。

2.1. AWS CloudFormation

  • CloudFormationは、AWSインフラストラクチャリソースの自動プロビジョニング用のAWSサービスです。ユーザーはすべての必要なリソースをブループリント(テンプレートと呼ばれる)で定義し、AWSはプロビジョニングと設定を行います。

次の用語と概念は、CloudFormationとSAMを理解するために不可欠です。

  • テンプレートはアプリケーションの説明** であり、実行時にどのように構造化されるべきかです。一連の必要なリソース、およびこれらのリソースの構成方法を定義できます。 CloudFormationはテンプレートを定義するための共通言語を提供し、フォーマットとしてJSONとYAMLをサポートします。

  • リソースはCloudFormationのビルディングブロックです** リソースは、RestApi、RestApiのステージ、バッチジョブ、DynamoDBテーブル、EC2インスタンス、ネットワークインターフェイス、IAMロールなど、さまざまなものにすることができます。

公式ドキュメント には、現在CloudFormationの約300のリソースタイプが記載されています。

  • スタックはテンプレートのインスタンス化です** CloudFormationはスタックのプロビジョニングと設定を行います。

2.2. サーバーレスアプリケーションモデル(SAM)

多くの場合、強力なツールの使用は非常に複雑で扱いにくいものになる可能性があります。これもCloudFormationの場合です。

AmazonがServerless Application Model(SAM)を導入したのはそのためです。

  • SAMは、サーバーレスアプリケーションを定義するための明確で直接的な構文を提供するという主張から始めました。現在、Lambda関数、DynamoDBテーブル、およびAPI ** の3つのリソースタイプしかありません。

SAMはCloudFormationテンプレート構文に基づいているため、単純なSAM構文を使用してテンプレートを定義できます。CloudFormationはそのテンプレートをさらに処理します。

詳細はhttps://github.com/awslabs/serverless-application-model[公式GitHubレポジトリに]およびhttps://docs.aws.amazon.com/lambda/latest/dg/serverless__app内で入手可能です.html[AWSのドキュメント]。

3前提条件

次のチュートリアルでは、AWSアカウントが必要です。

それに加えて、AWS CLI installed が必要です。

最後に、リージョンにS3バケットが必要です。これはAWS CLIで次のコマンドを使用して作成できます。

$>aws s3 mb s3://baeldung-sam-bucket

このチュートリアルでは baeldung-sam-bucket を使用していますが、バケット名は一意である必要があるため、名前を選択する必要があります。

デモアプリケーションとして、https://www.baeldung.com/using-aws-lambda-with-api-gateway/[API GatewayでAWS Lambdaを使用する]のコードを使用します。

4テンプレートを作成する

このセクションでは、SAMテンプレートを作成します。

個々のリソースを定義する前に、まず全体的な構造を見ていきます。

4.1. テンプレートの構造

まず、テンプレートの全体的な構造を見てみましょう。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Baeldung Serverless Application Model example

Resources:
  PersonTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      # Define table properties here
  StorePersonFunction:
    Type: AWS::Serverless::Function
    Properties:
      # Define function properties here
  GetPersonByHTTPParamFunction:
    Type: AWS::Serverless::Function
    Properties:
      # Define function properties here
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      # Define API properties here

ご覧のとおり、テンプレートはヘッダーと本体で構成されています。

ヘッダーは、CloudFormationテンプレートのバージョン( AWSTemplateFormatVersion )とSAMテンプレートのバージョン( Transform )を指定します。 Description を指定することもできます。

本体は一連のリソースで構成されています。各リソースは名前、リソース Type 、および一連の Properties を持ちます。

SAMの仕様では現在、__AWS

Serverless :: Api AWS :: Serverless :: Function 、および AWS :: Serverless :: SimpleTable__の3種類がサポートされています。

example application をデプロイする場合は、1つの SimpleTable 、2つの Functions 、および1つの Api を定義する必要があります。テンプレート本体。

4.2. DynamoDBテーブルの定義

それでは、DynamoDBテーブルを定義しましょう。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Baeldung Serverless Application Model example

Resources:
  PersonTable:
    Type: AWS::Serverless::SimpleTable
    Properties:
      PrimaryKey:
          Name: id
          Type: Number
      TableName: Person

SimpleTable には、テーブル名と主キーの2つのプロパティを定義するだけで済みます。主キーは、 id と呼ばれ、この場合は __Number __型になります。

サポートされている SimpleTable プロパティの全リストはhttps://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlesssimpletable[公式仕様]にあります。

注:主キーを使用してテーブルにアクセスするだけなので、__AWS

Serverless :: SimpleTable で十分です。より複雑な要件については、代わりにネイティブのCloudFormation型 AWS :: DynamoDB :: Table__を使用できます。

4.3. ラムダ関数の定義

次に、2つの機能を定義しましょう。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Baeldung Serverless Application Model example

Resources:
  StorePersonFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleRequest
      Runtime: java8
      Timeout: 15
      MemorySize: 512
      CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
      Policies: DynamoDBCrudPolicy
      Environment:
        Variables:
          TABLE__NAME: !Ref PersonTable
      Events:
        StoreApi:
          Type: Api
            Properties:
              Path:/persons
              Method: PUT
              RestApiId:
                Ref: MyApi
  GetPersonByHTTPParamFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleGetByParam
      Runtime: java8
      Timeout: 15
      MemorySize: 512
      CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
      Policies: DynamoDBReadPolicy
      Environment:
        Variables:
          TABLE__NAME: !Ref PersonTable
      Events:
        GetByPathApi:
          Type: Api
            Properties:
              Path:/persons/{id}
              Method: GET
              RestApiId:
                Ref: MyApi
        GetByQueryApi:
          Type: Api
            Properties:
              Path:/persons
              Method: GET
              RestApiId:
                Ref: MyApi

ご覧のとおり、各関数は同じプロパティを持ちます。

  • Handler は、関数のロジックを定義します** Javaを使用しているので、メソッド名に関連して、パッケージを含むクラス名です。

  • Runtime は関数がどのように実装されたかを定義します** 、これは私たちの場合Java 8です。

  • Timeout は、AWSが実行を終了するまでにコードの実行に最大で** どれくらいの時間がかかるかを定義します。

MemorySize は、割り当てられたメモリのサイズをMB単位で定義します。 AWSは MemorySize に比例してCPUリソースを割り当てます。そのため、CPUを多用する関数の場合は、その関数がそれほど多くのメモリを必要としない場合でも、 MemorySize を増やす必要があるかもしれません。

CodeUri は、機能コードの場所を定義します。 現在、ローカルワークスペース内のターゲットフォルダを参照しています。後でCloudFormationを使用して関数をアップロードすると、S3オブジェクトへの参照を含む更新されたファイルが得られます。

Policies は、一連のAWS管理IAMポリシーまたはSAM固有のポリシーテンプレートを保持できます GetPersonByPathParamFunction および GetPersonByQueryParamFunction には、 StorePersonFunction および DynamoDBReadPolicy にSAM固有のポリシー DynamoDBCrudPolicy を使用します。

Environment は実行時に環境プロパティを定義します。 DynamoDBテーブルの名前を保持するために環境変数を使用します。

イベント はAWSイベントのセットを保持することができ、それは関数をトリガすることができます。 私たちのケースでは、 Api 型の Event を定義します。 path 、HTTP Method 、および RestApiId の独自の組み合わせによって、関数がAPIのメソッドにリンクされます。これについては次のセクションで定義します。

サポートされている Function プロパティの全リストはhttps://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction[公式の仕様書]にあります。

4.4. SwaggerファイルとしてのAPI定義

DynamoDBテーブルと関数を定義した後、APIを定義できます。

最初の可能性はSwaggerフォーマットを使ってインラインでAPIを定義することです:

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Baeldung Serverless Application Model example

Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: test
      EndpointConfiguration: REGIONAL
      DefinitionBody:
        swagger: "2.0"
        info:
          title: "TestAPI"
        paths:
         /persons:
            get:
              parameters:
              - name: "id"
                in: "query"
                required: true
                type: "string"
              x-amazon-apigateway-request-validator: "Validate query string parameters and\
                \ headers"
              x-amazon-apigateway-integration:
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetPersonByHTTPParamFunction.Arn}/invocations
                responses: {}
                httpMethod: "POST"
                type: "aws__proxy"
            put:
              x-amazon-apigateway-integration:
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${StorePersonFunction.Arn}/invocations
                responses: {}
                httpMethod: "POST"
                type: "aws__proxy"
         /persons/{id}:
            get:
              parameters:
              - name: "id"
                in: "path"
                required: true
                type: "string"
              responses: {}
              x-amazon-apigateway-integration:
                uri:
                  Fn::Sub: arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetPersonByHTTPParamFunction.Arn}/invocations
                responses: {}
                httpMethod: "POST"
                type: "aws__proxy"
        x-amazon-apigateway-request-validators:
          Validate query string parameters and headers:
            validateRequestParameters: true
            validateRequestBody: false

__Api には3つのプロパティがあります。 StageName は、APIの段階を定義し、 EndpointConfiguration は、APIがリージョナルかエッジ最適化かを定義し、 __DefinitionBodyは、APIの実際の構造を含みます。

DefinitionBody では、次の3つのパラメータを定義します。

ご覧のとおり、 paths はAPI構造を表しており、https://www.baeldung.com/using-aws-lambda-with-api-gateway#create-api[before]を手動で定義する必要がありました。

Swaggerの paths は、AWSコンソールのリソースと同じです。そのように、各 path は1つ以上のHTTP動詞を持つことができます。これはAWSコンソールのメソッドと同等です。

各メソッドは1つ以上のパラメータとリクエストバリデータを持つことができます。

  • 最もエキサイティングな部分は、属性 x-amazon-apigateway-integration です。これは、Swaggerに対するAWS固有の拡張機能です。**

uri はどのLambda関数を呼び出すかを指定します。

responses は、関数によって返された応答を変換する方法を指定します。 Lambda Proxy Integrationを使用しているので、特別な規則は必要ありません。

type は、Lambda Proxy Integrationを使用することを定義しています。そのため、これはLambda関数が期待するものであるため、 httpMethod “ POST” に設定する必要があります。

サポートされている Api プロパティの完全なリストはhttps://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessapi[公式仕様]にあります。

4.5. 暗黙のAPI定義

2番目のオプションは、関数リソース内で暗黙的にAPIを定義することです。

AWSTemplateFormatVersion: '2010-09-09'
Transform: 'AWS::Serverless-2016-10-31'
Description: Baeldung Serverless Application Model Example with Implicit API Definition

Globals:
  Api:
    EndpointConfiguration: REGIONAL
    Name: "TestAPI"

Resources:
  StorePersonFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleRequest
      Runtime: java8
      Timeout: 15
      MemorySize: 512
      CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
      Policies:
        - DynamoDBCrudPolicy:
            TableName: !Ref PersonTable
      Environment:
        Variables:
          TABLE__NAME: !Ref PersonTable
      Events:
        StoreApi:
          Type: Api
          Properties:
            Path:/persons
            Method: PUT
  GetPersonByHTTPParamFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: com.baeldung.lambda.apigateway.APIDemoHandler::handleGetByParam
      Runtime: java8
      Timeout: 15
      MemorySize: 512
      CodeUri: ../target/aws-lambda-0.1.0-SNAPSHOT.jar
      Policies:
        - DynamoDBReadPolicy:
            TableName: !Ref PersonTable
      Environment:
        Variables:
          TABLE__NAME: !Ref PersonTable
      Events:
        GetByPathApi:
          Type: Api
          Properties:
            Path:/persons/{id}
            Method: GET
        GetByQueryApi:
          Type: Api
          Properties:
            Path:/persons
            Method: GET
見ての通り、私達のテンプレートは今や少し異なります:____AWS

Serverless :: Api ____resourceはもうありません。

  • しかし、CloudFormationはタイプ Api Events 属性を暗黙の定義として受け取り、とにかくAPIを作成します。アプリケーションをテストするとすぐに、Swaggerを使用してAPIを明示的に定義した場合と同じように動作することがわかります。

その上、私たちのAPIの名前を定義することができる、そして私たちのエンドポイントが地域的でなければならないということができる グローバル セクションがあります。

唯一の制限が発生します。暗黙のうちにAPIを定義するとき、私たちはステージ名を設定することができません。 AWSが Prod という名前のステージを作成するのはこのためです。

5展開とテスト

テンプレートを作成したら、配置とテストを続行できます。

このため、実際の配置を開始する前に、機能コードをS3にアップロードします。

最後に、任意のHTTPクライアントを使用してアプリケーションをテストできます。

5.1. S3へのコードアップロード

最初のステップでは、機能コードをS3にアップロードする必要があります。

AWS CLI経由でCloudFormationを呼び出すことでそれを実現できます。

$> aws cloudformation package --template-file ./sam-templates/template.yml --s3-bucket baeldung-sam-bucket --output-template-file ./sam-templates/packaged-template.yml

このコマンドで、CloudFormationをトリガーして CodeUri: で指定された機能コードを取得し、それをS3にアップロードします。 CloudFormationは packaged-template.yml ファイルを作成します。これは CodeUri: がS3オブジェクトを指すことを除いて同じ内容です。

CLIの出力を見てみましょう。

Uploading to 4b445c195c24d05d8a9eee4cd07f34d0 92702076/92702076.0 (100.00%)
Successfully packaged artifacts and wrote output template to file packaged-template.yml.
Execute the following command to deploy the packaged template
aws cloudformation deploy --template-file c:\zz__workspace\tutorials\aws-lambda\sam-templates\packaged-template.yml --stack-name <YOUR STACK NAME>

5.2. 展開

これで、実際の配置を開始できます。

$> aws cloudformation deploy --template-file ./sam-templates/packaged-template.yml --stack-name baeldung-sam-stack  --capabilities CAPABILITY__IAM

スタックにはIAMロールも必要なので(DynamoDBテーブルにアクセスするための関数のロールのように)、 -capabilitiesパラメーター を指定することによってそれを明示的に確認する必要があります。

CLIの出力は次のようになります。

Waiting for changeset to be created..
Waiting for stack create/update to complete
Successfully created/updated stack - baeldung-sam-stack

5.3. 展開レビュー

展開後、結果を確認できます。

$> aws cloudformation describe-stack-resources --stack-name baeldung-sam-stack

CloudFormationは、スタックの一部であるすべてのリソースをリストします。

5.4. テスト

最後に、HTTPクライアントを使ってアプリケーションをテストできます。

これらのテストに使用できる cURL コマンドの例をいくつか見てみましょう。

StorePersonFunction :

$> curl -X PUT 'https://0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons' \
   -H 'content-type: application/json' \
   -d '{"id": 1, "name": "John Doe"}'

GetPersonByPathParamFunction :

$> curl -X GET 'https://0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons/1' \
   -H 'content-type: application/json'

GetPersonByQueryParamFunction :

$> curl -X GET 'https://0skaqfgdw4.execute-api.eu-central-1.amazonaws.com/test/persons?id=1' \
   -H 'content-type: application/json'

5.5. 掃除

最後に、スタックと含まれているすべてのリソースを削除することでクリーンアップできます。

aws cloudformation delete-stack --stack-name baeldung-sam-stack

6. 結論

この記事では、テンプレートベースの記述とAWS上でのサーバーレスアプリケーションの自動デプロイを可能にするAWSサーバーレスアプリケーションモデル(SAM)を見ました。

詳細には、以下のトピックについて説明しました。

  • サーバーレスアプリケーションモデル(SAM)の基本

基礎となるCloudFormation SAMテンプレート構文を使用した、サーバレスアプリケーションの定義

  • CloudFormation CLIを使用したアプリケーションの自動デプロイメント

いつものように、この記事のすべてのコードはhttps://github.com/eugenp/tutorials/tree/master/aws-lambda[on GitHub]から入手できます。