この記事は、AWS LambdaとServerless Advent Calendar 2022 アドベントカレンダーの19日目の記事です。
はじめに
皆さん、こんにちは。AWSのソリューションアーキテクトの福井です。今年もAWS re:Inventで数多くの新しいサービスとサービスのアップデートが発表されました。本記事では、今回新たに発表された AWS Application Composer (Preview)を使ってサーバーレスアプリケーションを構築してみましたので、紹介させて頂きます。
AWS Application Composerとは
AWS Application Composer は、ビジュアルなエディターを使って様々なAWSのサービスを組み合わせて、サーバーレスアプリケーションを構築することができるサービスで、ビジュアルエディタで編集した内容をAWS Serverless Application Model (SAM) のテンプレートを生成したり、テンプレートを編集した結果をビジュアルエディター側に自動的に反映する機能を提供しています。
なお、AWS Application Composerは2022年12月現在、Previewとして公開されています。一般利用可能となるまでは、本番環境への適用はしないようにしてください。
AWS Application Composerを触ってみた
AWS Application Composerは現在、米国東部 (オハイオ)、 米国東部 (北バージニア)、 米国西部 (オレゴン)、 アジアパシフィック (東京)、ヨーロッパ (フランクフルト)、ヨーロッパ (アイルランド)の各リージョンで利用可能です。今回は、米国西部(オレゴン)リージョンを選択しました。
AWSマネジメントコンソールにログインして、リージョンを選択し、AWS Application Composerのマネジメントコンソールを開きます。
[Create project]ボタンをクリックします。
Create projectのダイアログが表示されるので、[New blank project]を選択し、[Connected]を選択した状態で、[Select folder]ボタンをクリックします。フォルダの選択ダイアログが開きますので、任意のフォルダを選択します。
現在のところ、[Connected]モードが利用できるブラウザはChromeのみになります。
[サイトにファイルの読み取りを許可しますか?]というダイアログが表示されるので、[ファイルを表示する]ボタンをクリックします。
[「指定したフォルダ」に変更を保存しますか?]というダイアログが表示されるので、[変更を保存]ボタンをクリックします。
AWS Application Composerのキャンバスが表示され、編集が可能になります。
キャンバス上にサーバーレスリソースをドラッグ&ドロップして編集
キャンバスの左側のペインにはサーバーレスリソースを表すアイコンが並んでいます。このアイコンを掴んでキャンバスにドラッグ&ドロップすることで、SAMのテンプレートを組み立てることができます。
Amazon API Gatewayリソースの作成
以下の手順で、API Gatewayをイベントソースとする Lambdaアプリケーションを構築します。
- キャンバスに API Gatewayのアイコンをドラッグ&ドロップします。
- キャンバスにドロップしたリソースをクリックし、右側のペインでプロパティーを入力します。ここでは、Logical ID をItemApiに変更しました。
- 最初のGETメソッドのRouteを /items に変更し、[Add route] ボタンをクリックして図のようにルートを追加し、[Save]ボタンをクリックして変更を保存します。
AWS Lambda リソースの作成
同じように、今度は Lambdaのアイコンをドラッグ&ドロップします。Logical IDを入力し、Source pathを "src/listitem" のように各ファンクションごとに変更し、RuntimeをPython 3.9に変更しました。API GatewayのRouteと接続することで、自動的にAPI GatewayをLambdaのイベントソースにマップしてくれます。
ListItem:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: ListItem
CodeUri: src/listitem
Handler: handler.handler
Runtime: python3.9
MemorySize: 256
Timeout: 30
Tracing: Active
+ Events:
+ ItemApiGETitems:
+ Type: Api
+ Properties:
+ Path: /items
+ Method: GET
+ RestApiId: !Ref ItemApi
すべてのAPI Gatewayのルートに対応するLambdaファンクションを作成しました。
ローカルファイルとの同期
ここまでの作業でローカルのフォルダは以下のようになっています。
.
├── src
│ ├── Function
│ │ ├── handler.py
│ │ ├── index.js
│ │ ├── package.json
│ │ └── requirements.txt
│ ├── createitem
│ │ ├── handler.py
│ │ └── requirements.txt
│ ├── deleteitem
│ │ ├── handler.py
│ │ └── requirements.txt
│ ├── getitem
│ │ ├── handler.py
│ │ └── requirements.txt
│ ├── listitem
│ │ ├── handler.py
│ │ └── requirements.txt
│ └── updateitem
│ ├── handler.py
│ └── requirements.txt
└── template.yaml
最初に作成されるsrc/Function ディレクトリは不要なので、削除します。ローカルファイルと同期されているので、ローカルのファイルを編集するとその内容をApplication Composerに反映することもできます。 template.yamlをエディタで開いて編集してみます。Lambdaのメモリサイズを3008から256に置換し、保存したところ、Application Composer側にも反映されました。
Amazon DynamoDB リソースの追加と接続
同じように Amazon DynamoDB のアイコンもドラッグ&ドロップして、すべてのLambdaファンクションと接続します。
AWS SAM テンプレートを確認
左上の[Template]ボタンをクリックすると、生成されたAWS SAM (Serverless Application Model) のテンプレートを確認することができます。このテンプレートを直接編集することも可能です。
これまでの操作で生成されたSAMテンプレートは以下の通りです。
Transform: AWS::Serverless-2016-10-31
Resources:
ItemApi:
Type: AWS::Serverless::Api
Properties:
Name: !Sub
- ${ResourceName} From Stack ${AWS::StackName}
- ResourceName: ItemApi
StageName: Prod
DefinitionBody:
openapi: '3.0'
info: {}
paths:
/items:
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${ListItem.Arn}/invocations
responses: {}
post:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${CreateItem.Arn}/invocations
responses: {}
/items/{id}:
get:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${GetItem.Arn}/invocations
responses: {}
put:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${UpdateItem.Arn}/invocations
responses: {}
delete:
x-amazon-apigateway-integration:
httpMethod: POST
type: aws_proxy
uri: !Sub arn:${AWS::Partition}:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${DeleteItem.Arn}/invocations
responses: {}
EndpointConfiguration: REGIONAL
TracingEnabled: true
ListItem:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: ListItem
CodeUri: src/listitem
Handler: handler.handler
Runtime: python3.9
MemorySize: 256
Timeout: 30
Tracing: Active
Events:
ItemApiGETitems:
Type: Api
Properties:
Path: /items
Method: GET
RestApiId: !Ref ItemApi
Environment:
Variables:
TABLE_NAME: !Ref Items
TABLE_ARN: !GetAtt Items.Arn
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Items
ListItemLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Retain
Properties:
LogGroupName: !Sub /aws/lambda/${ListItem}
GetItem:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: GetItem
CodeUri: src/getitem
Handler: handler.handler
Runtime: python3.9
MemorySize: 256
Timeout: 30
Tracing: Active
Events:
ItemApiGETitemsid:
Type: Api
Properties:
Path: /items/{id}
Method: GET
RestApiId: !Ref ItemApi
Environment:
Variables:
TABLE_NAME: !Ref Items
TABLE_ARN: !GetAtt Items.Arn
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Items
GetItemLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Retain
Properties:
LogGroupName: !Sub /aws/lambda/${GetItem}
CreateItem:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: CreateItem
CodeUri: src/createitem
Handler: handler.handler
Runtime: python3.9
MemorySize: 256
Timeout: 30
Tracing: Active
Events:
ItemApiPOSTitems:
Type: Api
Properties:
Path: /items
Method: POST
RestApiId: !Ref ItemApi
Environment:
Variables:
TABLE_NAME: !Ref Items
TABLE_ARN: !GetAtt Items.Arn
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Items
CreateItemLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Retain
Properties:
LogGroupName: !Sub /aws/lambda/${CreateItem}
UpdateItem:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: UpdateItem
CodeUri: src/updateitem
Handler: handler.handler
Runtime: python3.9
MemorySize: 256
Timeout: 30
Tracing: Active
Events:
ItemApiPUTitemsid:
Type: Api
Properties:
Path: /items/{id}
Method: PUT
RestApiId: !Ref ItemApi
Environment:
Variables:
TABLE_NAME: !Ref Items
TABLE_ARN: !GetAtt Items.Arn
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Items
UpdateItemLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Retain
Properties:
LogGroupName: !Sub /aws/lambda/${UpdateItem}
DeleteItem:
Type: AWS::Serverless::Function
Properties:
Description: !Sub
- Stack ${AWS::StackName} Function ${ResourceName}
- ResourceName: DeleteItem
CodeUri: src/deleteitem
Handler: handler.handler
Runtime: python3.9
MemorySize: 256
Timeout: 30
Tracing: Active
Events:
ItemApiDELETEitemsid:
Type: Api
Properties:
Path: /items/{id}
Method: DELETE
RestApiId: !Ref ItemApi
Environment:
Variables:
TABLE_NAME: !Ref Items
TABLE_ARN: !GetAtt Items.Arn
Policies:
- DynamoDBCrudPolicy:
TableName: !Ref Items
DeleteItemLogGroup:
Type: AWS::Logs::LogGroup
DeletionPolicy: Retain
Properties:
LogGroupName: !Sub /aws/lambda/${DeleteItem}
Items:
Type: AWS::DynamoDB::Table
Properties:
AttributeDefinitions:
- AttributeName: id
AttributeType: S
BillingMode: PAY_PER_REQUEST
KeySchema:
- AttributeName: id
KeyType: HASH
StreamSpecification:
StreamViewType: NEW_AND_OLD_IMAGES
この後は Lambdaファンクションのコードを編集し、sam build
して、sam deploy -g
するだけで、AWSにサーバーレスアプリをデプロイできます。
既存のテンプレートの読み込みと表示
AWS Application Composer は、SAMテンプレートの生成だけでなく、既存のテンプレートを読み込んでキャンバスに表示することもできます。Create project のダイアログで、[Load existing project] を選択し、フォルダを指定してYAMLテンプレートを読み込むことができます。
キャンバス上でアーキテクチャが視覚化されることで、チームで素早く確認することができそうです。
SAM Accelerate との組み合わせ
SAM Accelerate とは、AWS SAM が提供する開発環境向けの高速なAWSへのデプロイの仕組みです。AWS CloudFormation スタックの変更セットの更新をスキップするため、本番環境では使えませんが、SAM Template 内のAPI Gateway や Lambda に対する変更を素早く反映できるため、開発中のコードを実行し動作を確認するのに便利です。AWS Application Composer と SAM Accelerate を組み合わせることで、素早く SAM テンプレートを作成し、デプロイして変更を確認することが可能になります。
SAM Accelelate を開始するには以下のコマンドを実行します。
sam sync --watch --stack-name sam-app
sam sync --watchコマンドを始めて実行するとAWS SAM は CloudFormation デプロイを実行します。デプロイ後、AWS SAM はアプリケーションの変更を監視します。Lambda 関数などのコードリソースへのその後の変更については、AWS SAM は、サービス API を使用して変更を自動的にデプロイします。IAM ロールなどのインフラストラクチャの変更については、AWS SAM は、AWS CloudFormation デプロイを自動的に開始します。
まとめ
いかがでしょうか。AWS Application Composer を利用することでサーバーレスアプリケーションの開発がさらに加速しそうだと感じました。現在はまだプレビューですが、利用者のフィードバックを受けて今後さらに改善されていくでしょう。またキャンバス上でサーバーレスアーキテクチャを視覚化するメリットも感じることができました。この記事を見て、面白そうだと感じたらぜひ使ってみてください。
免責
本投稿は、個人の意見で、所属する企業や団体は関係ありません。
また掲載しているサンプルプログラム等の動作に関しても一切保証しておりません。