概要
AWS Serverless Application Model (SAM) を使用して、API Gateway 経由で AWS Step Functions ステートマシンを起動するアーキテクチャを構築するプロセスについて学んだ内容を共有します。特に、swagger.yaml を S3 にアップロードし、CloudFormation スタックの中で参照する方法に焦点を当てます。
課題と解決方法
課題 1: API Gateway と Step Functions の統合
SAM テンプレートで API Gateway から Step Functions ステートマシンを起動する設定が必要でした。
解決方法:
SAM テンプレートの Resources セクションで、AWS::Serverless::Function と AWS::Serverless::StateMachine リソースを定義し、API Gateway の AWS::Serverless::Api リソースの DefinitionBody で Fn::Transform と AWS::Include を使用しました。
課題 2: Swagger 定義の管理
API の定義を外部 swagger.yaml ファイルで管理したかったが、S3 を使わずにどうやって CloudFormation に組み込むかに悩みました。
解決方法:
S3 は使わないと無理そう?
ローカルでswagger.yaml ファイルを記述し、その後S3にアップロードする方法で措置。
S3 バケットへの swagger.yaml ファイルのアップロードとその後のデプロイをスクリプトで自動化しました。詳細は後述「デプロイスクリプトの例」にて。
課題 3: Fn::Sub の使用法
swagger.yaml ファイル内で !GetAtt や !Ref のような CloudFormation の関数を使う正しい方法を理解する必要がありました。
解決方法:
CloudFormation の Fn::Sub 関数を使用して、リソース属性値の動的な置き換えを行いました。これにより、API Gateway の統合設定でステートマシンの ARN を正確に参照することができました。
完成した template.yaml の例
以下、実際に作成した SAM テンプレートの抜粋です。
Fn::Transform と AWS::Include を使えば別ファイルで管理することができます。
また、動的な変数は !Ref か !GetAtt で参照することができますが、それぞれの違いは
- !Ref
- オブジェクトそのものを参照
- 例)
!Ref ReportOutputStateMachine
- !GetAtt
- オブジェクトが持つ値を参照
- 例)
!GetAtt ReportOutputStateMachine.Arn
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
# (中略)
Resources:
SampleStateMachine:
Type: AWS::Serverless::StateMachine
Properties:
# ステートマシンの中身はstatemachine/state_machine.asl.jsonで定義
DefinitionUri: statemachine/state_machine.asl.json
DefinitionSubstitutions:
SampleFunctionArn: !GetAtt SampleFunction.Arn
Role: !GetAtt StepFunctionsExecutionRole.Arn
SampleApi:
Type: AWS::Serverless::Api
Properties:
StageName: prod
DefinitionBody:
Fn::Transform:
Name: AWS::Include
Parameters:
Location: s3://sample-bucket/swagger.yaml
swagger.yaml の例
以下、API Gateway のエンドポイント定義の抜粋です。
swagger: "2.0"
info:
title: "SampleApi"
basePath: "/prod"
# (中略)
paths:
/execution:
post:
x-amazon-apigateway-integration:
credentials:
Fn::Sub: "${StepFunctionsExecutionRole.Arn}"
uri:
Fn::Sub: "arn:aws:apigateway:${AWS::Region}:states:action/StartExecution"
# (以下略)
デプロイスクリプトの例
#!/bin/bash
aws s3 cp swagger.yaml s3://scp-report-output/swagger.yaml
sam build
sam deploy -guided
教訓
Fn::Transform と AWS::Include を活用することで、外部ファイルの管理が簡単になります。
Fn::Sub の正しい使用法を学び、SAM テンプレート内での動的な値の置き換えが可能になります。
ただ、スタック管理サービスにはCDKもあり、複数環境を管理するなど複雑なリソース管理を行うのであればCDKの方がいい気が…。公式もCDK推しっぽいですし(偏見)。