hogehogeプログラマ

PHPer。趣味ではServerless Frameworkをメインで触ってます

Serverless のテンプレートでCloudFormationを学ぶ

指定したURLのスクリーンショットへの保存を
API Gateway + Lambda + S3で実現する為のテンプレートを利用して
CloudFormationのテンプレートについて学習した際の記録になります。

スタックを作成してみる

https://serverless.com/blog/building-a-serverless-screenshot-service-with-lambda/
から「Launch Stack」を押下するとアイルランドリージョン(eu-west-1)で
CloudFormationのスタック作成画面が表示されます。

各画面で以下を実施し

  • パラメータのScreenshotBucketNameにS3のバケット名を入力
  • AWS CloudFormation によって IAM リソースが作成される場合があることを承認します。」にチェックを付与

作成ボタンを押下すると暫く(20分程)してアイルランドリージョンでAPI Gateway等が作成されます。

テンプレートを読む

https://s3-eu-west-1.amazonaws.com/serverless-screenshots-service/2016-09-23T12:50:03/template.yml が該当のYAML形式で記述されたテンプレートになります。

これにAWSのドキュメントとにらめっこしてコメントを追記してみました。

※ コメントがYAML形式に沿ってないのでこれをコピペしてもエラーになります

東京リージョン(ap-northeast-1)でスタックを作成する

最初に作成した際はアイルランドリージョンのまま作成しましたが
次は東京リージョンに変更して実施してみます。

f:id:hogehoge0604:20180118213844p:plain

CREATE_FAILED AWS::CloudFront::Distribution CloudFrontEndpoint Resource creation cancelled
CREATE_FAILED AWS::IAM::Policy IamPolicyLambdaExecution Resource creation cancelled
CREATE_FAILED AWS::Lambda::Function ListScreenshotsLambdaFunction Resource creation cancelled
CREATE_FAILED AWS::Lambda::Function TakeScreenshotLambdaFunction Error occurred while GetObject. S3 Error Code: PermanentRedirect. S3 Error Message: The bucket is in this region: eu-west-1. Please use this region to retry the request
CREATE_FAILED AWS::Lambda::Function CreateThumbnailsLambdaFunction Error occurred while GetObject. S3 Error Code: PermanentRedirect. S3 Error Message: The bucket is in this region: eu-west-1. Please use this region to retry the request

東京リージョンに切り替えて作成したところエラーとなってしまいました。

エラーの原因と解決

Lambdaに配置するzipファイルをS3から取得していますがS3のリージョンを見たところ
アイルランドリージョンになっています。
https://s3-eu-west-1.amazonaws.com/serverless-screenshots-service/2016-09-23T12:50:03/lambda-screenshots.zip

AWS Lambda 関数コード - AWS CloudFormation

このバケットは、Lambda 関数を作成するのと同じ AWS リージョン内に存在する必要があります。
Lambda 関数とバケットが同じリージョンにある限り、別の AWS アカウントからバケットを指定できます。

上記の通り、別リージョンのS3に取得に行ったことによるエラーになります。

AWS Lambda 関数コード - AWS CloudFormationを見た感じだとZipFileは関数のソースコードを埋め込むプロパティのようなのでS3にzipを配置する以外に手はなさそうです。そのため以下の対応を行いました。

  1. S3バケットを東京リージョンに立ててLambdaに設置するzipファイルを配置
  2. CloudFormationのテンプレートをダウンロードし以下のS3バケット名とパスの記述を全て1で作成した内容に変更する
S3Bucket: serverless-screenshots-service
S3Key: 2016-09-23T12:50:03/lambda-screenshots.zip
  1. CloudFormationにアクセスし「テンプレートをAmazon S3にアップロード」の方から修正したテンプレートを設定する

で再度スタックの作成を行ったところ無事に作成できました。

実際に実行してみる

curl -X POST https://djln6al5ml.execute-api.ap-northeast-1.amazonaws.com/dev/screenshots?url=http://google.com/ -H "x-api-key: {APIキー}"
{"message":"Forbidden"}

アクセス制限に掛かってしまいました……
調べたところAPI Gatewayの使用量プランを設定が無かったので
使用量プランを設定しステージとAPIキーを紐付けたら改めて実行します。

curl -X POST https://djln6al5ml.execute-api.ap-northeast-1.amazonaws.com/dev/screenshots?url=http://google.com/ -H "x-api-key: {APIキー}"
{
  "hash":"6ab016b2dad7ba49a992ba0213a91cf8",
  "key":"6ab016b2dad7ba49a992ba0213a91cf8/original.png",
  "bucket":"hogehoge-serverless-screenshots-service",
  "url":"https://d2iiuopwdwbiap.cloudfront.net/6ab016b2dad7ba49a992ba0213a91cf8/original.png"
}

スタックを削除する

一度でもAPIを動作しスクリーンショットを作成するとS3のバケット削除でエラーとなります。

f:id:hogehoge0604:20180118213841p:plain

DELETE_FAILED AWS::S3::Bucket S3BucketScreenshots The bucket you tried to delete is not empty

CloudFormationで作成したバケットの中身を空にしてから再度削除することで
綺麗に削除できました。
ちなみにAPI Gatewayの使用量プランは手動で作成したため
CloudFormationの管理外なので別途手動で削除する必要があります。

紆余曲折ありましたがこれでようやくServerlessなScreenshot APIが出来ました。
使用量プランの設定をCloudFormationのテンプレートに含めたいところですが
気が向いたらやってみて追記します。