AWSサーバーレスアプリケーションモデルの概要
1. 概要
前回の記事では、RESTエンドポイント用のAPI Gateway、ビジネスロジック用のAWS Lambda、データベースとしてのDynamoDBを使用して、フルスタックサーバーレスアプリケーションをAWSに実装しました。
ただし、展開は多くの手動の手順で構成されているため、複雑さが増したり、環境の数が増えたりすると、手に負えなくなる可能性があります。
このチュートリアルでは、 AWSサーバーレスアプリケーションモデル(SAM)の使用方法について説明します。これにより、テンプレートベースの説明とAWSでのサーバーレスアプリケーションの自動デプロイが可能になります。
詳細については、次のトピックを見ていきます。
- サーバーレスアプリケーションモデル(SAM)の基本、および基盤となるCloudFormationの基本
- SAMテンプレート構文を使用したサーバーレスアプリケーションの定義
- CloudFormationCLIを使用したアプリケーションの自動デプロイ
2. 基本
以前で説明したように、AWSでは、API Gateway、Lambda関数、DynamoDBを使用して、完全にサーバーレスのアプリケーションを実装できます。 間違いなく、これはパフォーマンス、コスト、およびスケーラビリティに関してすでに多くの利点を提供します。
ただし、欠点は、各関数の作成、コードのアップロード、DynamoDBテーブルの作成、IAMロールの作成、APIおよびAPI構造の作成など、現時点でAWSコンソールに多くの手動手順が必要なことです。
複雑なアプリケーションや、テスト、ステージング、本番環境などの複数の環境では、その労力は急速に増大します。
ここで、一般的なAWS上のアプリケーション用のCloudFormationと、特にサーバーレスアプリケーション用のサーバーレスアプリケーションモデル(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はサーバーレスアプリケーションモデル(SAM)を導入しました。
SAMはCloudFormationテンプレート構文に基づいているため、単純なSAM構文を使用してテンプレートを定義でき、CloudFormationはそのテンプレートをさらに処理します。
詳細については、公式GitHubリポジトリおよびAWSドキュメントをご覧ください。
3. 前提条件
次のチュートリアルでは、AWSアカウントが必要です。 無料利用枠アカウントで十分です。
さらに、AWSCLIをインストールする必要があります。
最後に、リージョンにS3バケットが必要です。これは、AWSCLIを介して次のコマンドで作成できます。
$>aws s3 mb s3://baeldung-sam-bucket
チュートリアルでは以下でbaeldung-sam-bucketを使用しますが、バケット名は一意である必要があるため、名前を選択する必要があることに注意してください。
デモアプリケーションとして、 Using AWS Lambda with APIGatewayのコードを使用します。
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 )を指定します。 説明を指定することもできます。
本体は一連のリソースで構成されます。各リソースには、名前、リソース Type 、および一連のPropertiesがあります。
SAM仕様は現在、 AWS :: Serverless :: Api 、 AWS :: Serverless :: Function 、および AWS :: Serverless ::SimpleTableの3つのタイプをサポートしています。 ]。
サンプルアプリケーションをデプロイするため、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 と呼ばれ、タイプ Numberinの主キーです。私たちの場合。
サポートされているSimpleTableプロパティの完全なリストは、公式仕様のにあります。
注:主キーを使用してテーブルにアクセスするだけなので、 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
ご覧のとおり、各関数には同じプロパティがあります。
ハンドラーは関数のロジックを定義します。Javaを使用しているため、メソッド名に関連するパッケージを含むクラス名です。
ランタイムは、関数の実装方法を定義します。この場合はJava8です。
Timeoutは、AWSが実行を終了するまでにコードの実行に最大でかかる時間を定義します。
MemorySize は、割り当てられたメモリのサイズをMB単位で定義します。AWSはCPUリソースをMemorySizeに比例して割り当てることを知っておくことが重要です。 そのため、CPUを集中的に使用する関数の場合、関数がそれほど多くのメモリを必要としない場合でも、MemorySizeを増やす必要がある場合があります。
CodeUri は、関数コードの場所を定義します。現在、ローカルワークスペースのターゲットフォルダーを参照しています。 後でCloudFormationを使用して関数をアップロードすると、S3オブジェクトへの参照を含む更新されたファイルが取得されます。
ポリシーは、AWSが管理するIAMポリシーまたはSAM固有のポリシーテンプレートのセットを保持できます。 StorePersonFunctionには、SAM固有のポリシーDynamoDBCrudPolicyを使用しますGetPersonByPathParamFunctionおよびGetPersonByQueryParamFunctionのおよびDynamoDBReadPolicy。
環境実行時に環境プロパティを定義します。DynamoDBテーブルの名前を保持するために環境変数を使用します。
イベントは、関数をトリガーできる一連のAWSイベントを保持できます。この場合、タイプApiのイベントを定義します。 。 path 、HTTP Method 、および RestApiId の独自の組み合わせにより、関数がAPIのメソッドにリンクされます。これについては次のセクションで定義します。 。
サポートされている機能プロパティの完全なリストは、公式仕様のにあります。
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 では、3つのパラメーターを定義します。 swagger version as “ 2.0” 、 info:title: as 「testAPI」、および一連のパス。
ご覧のとおり、パスはAPI構造を表しており、の前に手動で定義する必要がありました。 Swaggerのpathsは、AWSコンソールのリソースと同等です。 そのように、各 path には1つ以上のHTTP動詞を含めることができます。これは、AWSコンソールのメソッドと同等です。
各メソッドは、1つ以上のパラメーターとリクエストバリデーターを持つことができます。
最もエキサイティングな部分は、属性 x-amazon-apigateway-integration です。これは、SwaggerのAWS固有の拡張機能です。
uri は、呼び出されるLambda関数を指定します。
response は、関数によって返される応答を変換する方法のルールを指定します。 Lambda Proxy Integrationを使用しているため、特定のルールは必要ありません。
type は、Lambdaプロキシ統合を使用することを定義します。したがって、httpMethodを「POST」に設定する必要があります。これはLambda関数が期待するものです。
サポートされているApiプロパティの完全なリストは、公式仕様のにあります。
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リソースはもうありません。
ただし、CloudFormationは、タイプApiのEvents属性を暗黙の定義として受け取り、とにかくAPIを作成します。 アプリケーションをテストするとすぐに、Swaggerを使用してAPIを明示的に定義した場合と同じように動作することがわかります。
さらに、 Globals セクションがあり、APIの名前を定義できます。また、エンドポイントはリージョナルである必要があります。
唯一の制限が発生します。APIを暗黙的に定義する場合、ステージ名を設定することはできません。 これが、AWSがProdというステージを作成する理由です。
5. 展開とテスト
テンプレートを作成したら、展開とテストに進むことができます。
このため、実際のデプロイをトリガーする前に、関数コードをS3にアップロードします。
最終的には、任意のHTTPクライアントを使用してアプリケーションをテストできます。
5.1. S3へのコードのアップロード
最初のステップでは、機能コードをS3にアップロードする必要があります。
これを行うには、AWSCLIを介して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サーバーレスアプリケーションモデル(SAM)について説明しました。これにより、テンプレートベースの説明とAWSでのサーバーレスアプリケーションの自動デプロイが可能になります。
詳細には、次のトピックについて説明しました。
- サーバーレスアプリケーションモデル(SAM)の基本、および基盤となるCloudFormation
- SAMテンプレート構文を使用したサーバーレスアプリケーションの定義
- CloudFormationCLIを使用したアプリケーションの自動デプロイ
いつものように、この記事のすべてのコードは、GitHubのから入手できます。