AWS SAMをはじめる
久しぶりにSAMを触ったらやっぱり忘れていたので、AWS SAM最初の一歩をまとめておきます。
AWS SAMとは
AWS Serverless Application Model (AWS SAM) は、AWS 上でサーバーレスアプリケーションを構築および実行するデベロッパーのエクスペリエンスを改善するツールキットです。AWS SAM は次の 2 つの主要な部分で構成されます。
AWS Serverless Application Model (AWS SAM) とは
AWS SAMは「 AWS SAMテンプレート」と「 AWS SAM CLI」で構成されています。
AWS SAMテンプレートはAWS CloudFormationをベースに構築される、サーバーレスアプリケーションのインフラストラクチャコードを定義・管理するためのオープンソースフレームワークです。
AWS SAMはテンプレート変換によりAWS CloudFormationを通じてインフラストラクチャのリソースをデプロイできます。
またAWS SAMCLIとは、AWS SAMテンプレートを利用してサーバーレスアプリケーションを構築・実行できるコマンドラインツールです。
AWS SAMでプロビジョニングできるリソース
-
AWS::Serverless::Api
HTTPSエンドポイント経由で呼び出し可能なAPIGatewayリソース -
AWS::Serverless::Application
AWS Serverless Application RepositoryまたはS3バケットからのサーバーレスアプリケーションをCloudFormationのStackリソースとしてデプロイ -
AWS::Serverless::Connector
2リソース間の権限を設定 -
AWS::Serverless::Function
Lambda関数、実行ロール、トリガーとなるイベントソースのマッピング -
AWS::Serverless::GraphQLApi
AppSync GraphQLAPIを作成 -
AWS::Serverless::HttpApi
APIGateway HTTP APIの作成 -
AWS::Serverless::LayerVersion
Lambda関数に必要なライブラリ、ランタイムコード -
AWS::Serverless::SimpleTable
単一属性のPKでDynamoDBを作成。より高度な設定が必要な場合はAWS::DynamoDB::Table
を使用する。 -
AWS::Serverless::StateMachine
AWS Step Functionステートマシンを作成
SAMをはじめる
前提条件
- 利用できるAWSアカウントがあること
- AWS CLIのインストール・AWS認証情報の設定が完了していること
詳しくはこちら→AWS SAMの前提条件
AWS SAM CLIのインストール
開発者ガイドのAWS SAM CLIのインストールに手順が掲載されています。
こちらには載っていませんが、私はasdfを使用して導入しました。(公式には非掲載のサードパーティツールなので使用は自己責任です)
asdfを使用したAWS SAM CLIのインストール
- プラグインを追加する
asdf plugin add aws-sam-cli
- インストール可能なバージョンを確認
asdf list-all aws-sam-cli
- 対象のバージョンをインストールする
asdf install aws-sam-cli {バージョン}
- グローバル環境もしくはプロジェクトのディレクトリで利用するバージョンを指定する
asdfではインストールしただけでは使えるようにならないので、設定します。
今インストールできるバージョンの一覧を見る。
asdf list aws-sam-cli
グローバル環境で使うバージョンを指定するには、
asdf global aws-sam-cli {バージョン}
もしくはプロジェクトのルートディレクトリで、
asdf local aws-sam-cli {バージョン}
AWS SAMプロジェクトを開始する
以下のコマンドを実行すると新しいAWS SAMアプリケーションを初期化するためガイドが開始します。
sam init
ガイドに沿って進めるとSAM CLIによって新しいディレクトリが作成されます。
今回はひとまず、hello worldのテンプレートを使用。
作成されたディレクトリに移動して簡単にデプロイしてみます!
ビルドする
以下のコマンドを実行し、デプロイの準備を行います。
sam build
デプロイする
以下のコマンドを実行することでAWS上にリソースをデプロイ。
sam deploy --guided
このオプションでデプロイを実行するとSAM CLIによってアプリケーションの設定構成の入力が求められます。
Stack Name [hello-world]:
AWS Region [us-east-1]:
Confirm changes before deploy [Y/n]:
Allow SAM CLI IAM role creation [Y/n]:
Disable rollback [y/N]:
HelloWorldFunction has no authentication. Is this okay? [y/N]:
Save arguments to configuration file [Y/n]:
SAM configuration file [samconfig.toml]:
SAM configuration environment [default]:
【改めて】SAMで{'Hello': 'World'}を返すAPIをデプロイする
sam init
で生成したものとほぼ変わりませんが、HelloWorldを返すLambda関数とAPIGatewayをデプロイする実装を見てみます。
簡単な構成をデプロイ
ランタイムはNode.js v20、TypeScriptを使います。
template.yaml
の中身
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description:
hello-world
Resources:
HelloWorldFunction: # ここでLambda関数を定義
Type: AWS::Serverless::Function
Properties:
CodeUri: hello-world/
Handler: app.lambdaHandler
Runtime: nodejs20.x
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api # Lambda関数をトリガーするイベントとしてAPIGatewayを定義
Properties:
Path: /hello
Method: get
Metadata:
BuildMethod: esbuild
BuildProperties:
Minify: true
Target: "es2020"
Sourcemap: true
EntryPoints:
- app.ts # hello-world/app.tsにLambda関数のソースコードを書きます
Outputs: # プロビジョンされたリソースの情報を出力
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
hello-world/app.ts
の中身
import { APIGatewayProxyEvent, APIGatewayProxyResult } from 'aws-lambda';
export const lambdaHandler = async (event: APIGatewayProxyEvent): Promise<APIGatewayProxyResult> => {
try {
return {
statusCode: 200,
body: JSON.stringify({
'hello': 'world',
}),
};
} catch (err) {
console.log(err);
return {
statusCode: 500,
body: JSON.stringify({
message: 'some error happened',
}),
};
}
};
APIを叩いてみる
sam list endpoints --output json --profile {プロファイル名}
このコマンドを実行するとtemplate.yamlのOutputsセクションで指定した情報を出力することができます。この中でAPIエンドポイントの情報が得られるので、curlコマンドでGETリクエストを送信してみます。
実行結果
$ sam list endpoints --output json --profile dev-cli --region ap-northeast-1
[
{
"LogicalResourceId": "HelloWorldFunction",
"PhysicalResourceId": "hello-world-HelloWorldFunction-XXXXXXXXXXXX",
"CloudEndpoint": "-",
"Methods": "-"
},
{
"LogicalResourceId": "ServerlessRestApi",
"PhysicalResourceId": "XXXXXXXXXX",
"CloudEndpoint": [
"https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod",
"https://xxxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Stage"
],
"Methods": [
"/hello['get']"
]
}
]
GETリクストを送信
$ curl https://xxxxxxxxx.execute-api.ap-northeast-1.amazonaws.com/Prod/hello
{"hello": "world"}
まとめ
AWS SAMを利用することで簡単にAPIをデプロイできます。
基本はインフラストラクチャ定義をtemplate.yamlに記述、必要なソースコードを記述。必要な設定を行い、AWS SAM CLIでコマンド実行によりプロビジョニングやアプリケーションの実行が可能になります。
プロファイル指定など環境設定やローカルでのテスト、変更の同期などその他様々な使い方がありますが、またの機会に!
Discussion