AWS SAMを利用したサーバレスAPIの構築
最近少しAWSに触れる機会が減ってしまっているため、久々にAWSネタです。
AWS SAM(サーバレスアプリケーションモデル)とは
AWS上でサーバーレスアプリケーションを構築するために使用することができるオープンソースフレームワークです。
提供してくれること
インストール(Macの場合)
- Dockerがインストールされていることが前提(ローカル上でのテストでDockerを内部で利用しているため)
$ brew upgrade $ brew tap aws/tap $ brew install aws-sam-cli
CLIツールの概要
init
AWS SAMテンプレートを利用したサーバレスアプリケーションの初期化
$ sam init --runtime <runtime>
- AWS Lambdaで使用できるランタイム
invoke
ローカル上で擬似的にLambdaを呼び出す
$ sam local invoke [OPTIONS] [FUNCTION_IDENTIFIER]
option
--event|-e
: 呼び出された時にLambda関数に渡されるイベントファイル(JSON)
generate-event
Amazon S3、Amazon API Gateway、Amazon SNSなどのさまざまなイベントソースからサンプルペイロードを生成します。 これらのペイロードには、イベントソースがLambda関数に送信する情報が含まれています。
$ sam local generate-event
現状使用できるリソース
- alexa-skills-kit
- alexa-smart-home
- apigateway
- batch
- cloudformation
- cloudfront
- cloudwatch
- codecommit
- codepipeline
- cognito
- config
- dynamodb
- kinesis
- lex
- rekognition
- s3
- ses
- sns
- sqs
- stepfunctions
local
start-api
サーバレスアプリケーションをローカル上で実行可能なHTTPサーバを立ち上げます。(Dockerを内部で利用) API Gateway+Lambdaをローカル上で確認するのに役立ちます。
$ sam local start-api [OPTIONS]
start-lambda
AWS Lambdaをエミュレートするローカルエンドポイントを起動します。エンドポイントに対して、AWS SDKやAWS CLIを利用してローカルでLambda関数を呼び出すことができます。
$ sam local start-lambda # 立ち上げたままで、endpoint-urlをローカルの物にして呼び出すことができる $ aws lambda invoke --function-name "HelloWorldFunction" --endpoint-url "http://127.0.0.1:3001" --no-verify-ssl out.txt
invoke
local上でLambda関数を呼び出します。呼び出が完了した後終了します。
$ sam local invoke [FunctionName] --event event.json
validate
AWS SAMのテンプレートのバリデーションを行います。
$ sam validate
logs
Lambda関数によって生成されたログを取得します。
$ sam logs -n FunctionName
package
AWS SAMアプリケーションをパッケージ化します。 これはaws cloudformationパッケージのエイリアスです。
sam package \ --output-template-file packaged.yaml \ --s3-bucket REPLACE_THIS_WITH_YOUR_S3_BUCKET_NAME
--output-template-file
: コマンドがパッケージ化されたテンプレートを書き込むファイルへのパス。--s3-bucket
: アップロード先のS3のバケット名を指定する。
deploy
AWS SAMアプリケーションをデプロイします。 これはaws cloudformation deploy
のエイリアスです。
sam deploy \ --template-file packaged.yaml \ --stack-name <stack-name> \ --capabilities CAPABILITY_IAM
publish
AWS SAMアプリケーションをAWS Serverless Application Repositoryに公開します。 このコマンドは、パッケージ化されたAWS SAMテンプレートを受け取り、指定されたリージョンにアプリケーションを公開します。
$ sam publish
build
このコマンドを使用して、Lambdaソースコードをビルドし、Lambdaの実行環境をターゲットとするデプロイメント成果物を生成します。 依存関係を含むマニフェストファイル(Pythonならrequirements.txt等)を探し、依存関係をビルドパッケージに含めることが出来ます。
$ sam build
AWS SAMテンプレート
AWS SAMテンプレートは、AWS CloudFormationテンプレートの拡張です。 つまり、AWS CloudFormationテンプレートで宣言できるリソースであれば、AWS SAMテンプレートでも宣言できます。 さらに、AWS SAMが提供する追加のリソースタイプ(サーバーレスリソースの宣言で説明されているリソースなど)を、サーバーレスアプリケーションの一部のコンポーネントのショートカットとして使用できます。
- AWS SAM Template Concepts - AWS Serverless Application Model
- Globals Section
- AWS Serverless Application Model
例) python3.7のランタイムを使用したAPI Gatewayの作成
AWS SAMを利用した初期化
$ sam init --runtime python3.7 $ cd sam-app
Localでのテスト(* Dockerが既にインストールされていることが前提)
$ sam local start-api $ curl http://127.0.0.1:3000/hello
ビルドとデプロイ
$ aws s3 mb s3://bucket_name # bucketは新規に必要 $ sam package \ --output-template-file packaged.yaml \ --s3-bucket bucket_name $ sam deploy \ --template-file packaged.yaml \ --stack-name sam-app \ --capabilities CAPABILITY_IAM
API Gatewayの動作確認
$ aws cloudformation describe-stacks \ --stack-name sam-app \ --query 'Stacks[].Outputs[?OutputKey==`HelloWorldApi`]' \ --output table $ curl -XGET ${OutputValue} // 上記の結果のOutputValueに対してAPIを呼び出し、レスポンスが返ってくればOK
セキュリティについて
API Gatwayに対して、アクセス制限をかけたい場合、APIリソースに対して、リソースポリシーを設定することでアクセス制限を掛けることが出来ます。 基本IAMポリシーの記述と同じようです。
Amazon API Gateway リソースポリシーを使用して API へのアクセスを制御する - Amazon API Gateway
所感
今までLambda Function自体は、小さいバッチ等に利用することが多かったですが、AWS SAMを利用することにより、API Gatewayとの連携がしやすくなり、簡単なモックを作るのに適しているように感じました。
疑問点
API Gatway想定で作られているからか、新規にバケットから作成する必要があるので、API想定ならドメインとかも考えるのでいいとして、通常のバッチ用途とかの場合でも、新規バケットからだと、バケット命名がちょっとつらそうな気がしました。。。S3にアップロードされているものは拡張子はないですが、パッケージングされたzipのようです。