[やってみた] Lambda@Edge のWorkshopでやったことをSAM一撃化してみた。 #NET307 #reinvent 2019
re:Inventの「Lambda@Edgeによるコンテンツ配信のカスタマイズ #NET307」のワークショップを、勢いあまってSAM一撃化したので、共有します。
Lambdaを使うので、CloudFormationではなく、SAM(Serverless Application Model)化してます。
SAM化してるので残念ながら、マウスからポチっと一撃にはなってませんが
コマンドラインからsam deploy
一撃したあとはのんびりと見てれば以下が実施されます。
- IAM, S3, DynamoDBの作成
- S3へ必要なリソースのコピー(CloudFormationカスタムリソース)
- DynamoDBへ必要なリソースのコピー(CloudFormationカスタムリソース)
- Lambda@Edge関数(6つの作成)
- Lambda@EdgeのPublish(Version, Alias)
- CloudFrontの作成
- CloudFrontへ各種Behaviorを設定
- Output CloudFrontのホスト名(https://XXXXXXX.cloudfront.net)
ということで、最後のCloudFront作成と展開が10分程度かかるんですが、ワークショップの最終形態が1撃でできあがります。
メイキングに入る前に、各ソースは公式のAWS githbuのリポジトリをクローンして公開してますので、先にsam deploy
から行きます。
Workshopの概要
「Lambda@Edgeによるコンテンツ配信のカスタマイズ #NET307」のワークショップを参照して頂きたいのですが
https://github.com/aws-samples/aws-lambda-edge-workshops/blob/master/Workshop1/README.md
In this workshop you will learn how you can use Lambda@Edge to extend functionality of your web-application or a website.
Lambda@Edgeを使用したWebサイトに対して、Lamba@Edegeを用いたアプリケーションの拡張(セキュリティの強化、apiの実装等を行います)
ワークショップでは、AWSコンソールから1つ1つ、変更を加えていくのですが、今回は機能拡張した後の状態に一撃でもっていきます。
SAM Deploy
0. SAMの準備
詳細は割愛しますが、SAMは必須ですのでSAM CLIのインストールを実施してください。
参考 https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install.html
Linux
brew tap aws/tap brew install aws-sam-cli sam --version SAM CLI, version 0.38.0
1. クローンとデプロイ
clone
SAMをまるっと公開しているのでリポジトリをクローンしてください
git clone https://github.com/cm-kajiwara-taishi/aws-lambda-edge-workshops.git cd aws-lambda-edge-workshops/Workshop1/SAM
SAM deploy 初回
--guidedオプションを付けて、samconf.tomlを作成します (S3バケットの指定を更新します。S3バケットの指定、CAPABILITY_NAMED_IAMを指定すれば一撃デプロイできますがコマンドがながくなるので) Lamda関数はlambda@Edgeで使用しますので、リージョンはus-east-1指定してください
CAPABILITY_NAMED_IAM が必要な為、CAPABILITY_IAMでは初回のデプロイは失敗します
sam deploy -t sam-template.yml --guided Configuring SAM deploy ====================== Looking for samconfig.toml : Found Reading default arguments : Success Setting default arguments for 'sam deploy' ========================================= Stack Name [WsLambdaAtEdgeAlienCardsSAM]: AWS Region [us-east-1]: #Shows you resources changes to be deployed and require a 'Y' to initiate deploy Confirm changes before deploy [y/N]: #SAM needs permission to be able to create roles to connect to the resources in your template Allow SAM CLI IAM role creation [Y/n]: Save arguments to samconfig.toml [Y/n]: Looking for resources needed for deployment: Found! Managed S3 bucket: aws-sam-cli-managed-default-samclisourcebucket-xxxxxxx A different default S3 bucket can be set in samconfig.toml Saved arguments to config file Running 'sam deploy' for future deployments will use the parameters saved above. The above parameters can be changed by modifying samconfig.toml Learn more about samconfig.toml syntax at https://docs.aws.amazon.com/serverless-application-model/latest/developerguide/serverless-sam-cli-config.html Deploying with following values =============================== Stack name : WsLambdaAtEdgeAlienCardsSAM Region : us-east-1 Confirm changeset : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxxx Capabilities : ["CAPABILITY_IAM"] Parameter overrides : {} Initiating deployment ===================== Waiting for changeset to be created.. Error: Failed to create changeset for the stack: WsLambdaAtEdgeAlienCardsSAM, ex: Waiter ChangeSetCreateComplete failed: Waiter encountered a terminal failure state Status: FAILED. Reason: Requires capabilities : [CAPABILITY_NAMED_IAM]
SAM deploy 2回移行
sam deploy -t sam-template.yml --capabilities CAPABILITY_NAMED_IAM
もしくはsamconfig.tomlのcapabilitiesを変更し
capabilities = "CAPABILITY_NAMED_IAM" // CAPABILITY_IAM から書き換え
sam deploy -t sam-template.yml
で、2回目以降は、JavaScriptを更新すれば、sam deploy -t sam-template.yml
で行えます。
deploy 実行中
Deploying with following values =============================== Stack name : WsLambdaAtEdgeAlienCardsSAM Region : us-east-1 Confirm changeset : False Deployment s3 bucket : aws-sam-cli-managed-default-samclisourcebucket-xxxxxxxxxxx Capabilities : ["CAPABILITY_NAMED_IAM"] Parameter overrides : {} Initiating deployment ===================== Waiting for changeset to be created.. CloudFormation stack changeset ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Operation LogicalResourceId ResourceType ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ + Add AlienCardsCloudFrontDistribution AWS::CloudFront::Distribution + Add AlienCardsCloudFrontOAI AWS::CloudFront::CloudFrontOriginAccessIdentity + Add AlienCardsDynamoDBTable AWS::DynamoDB::Table + Add AlienCardsS3BucketPolicy AWS::S3::BucketPolicy + Add AlienCardsS3Bucket AWS::S3::Bucket + Add BootstrapCustomResource Custom::BootstrapFunction + Add BootstrapFunction AWS::Lambda::Function + Add IamLambdaExecutionRoleBasic AWS::IAM::Role + Add IamLambdaExecutionRoleFullAccess AWS::IAM::Role + Add IamLambdaExecutionRoleReadOnly AWS::IAM::Role + Add LambdaEdgeAddSecurityHeadersAliaslive AWS::Lambda::Alias + Add LambdaEdgeAddSecurityHeadersVersionba8ccad248 AWS::Lambda::Version + Add LambdaEdgeAddSecurityHeaders AWS::Lambda::Function + Add LambdaEdgeApiLikeAliaslive AWS::Lambda::Alias + Add LambdaEdgeApiLikeVersione3f0e31a43 AWS::Lambda::Version + Add LambdaEdgeApiLike AWS::Lambda::Function + Add LambdaEdgeCustomizeCssAliaslive AWS::Lambda::Alias + Add LambdaEdgeCustomizeCssVersion0f1abd1872 AWS::Lambda::Version + Add LambdaEdgeCustomizeCss AWS::Lambda::Function + Add LambdaEdgeGenerateCardPageAliaslive AWS::Lambda::Alias + Add LambdaEdgeGenerateCardPageVersion1140f6810d AWS::Lambda::Version + Add LambdaEdgeGenerateCardPage AWS::Lambda::Function + Add LambdaEdgeGenerateHomePageAliaslive AWS::Lambda::Alias + Add LambdaEdgeGenerateHomePageVersione27d7b8356 AWS::Lambda::Version + Add LambdaEdgeGenerateHomePage AWS::Lambda::Function + Add LambdaEdgeRedirectAliaslive AWS::Lambda::Alias + Add LambdaEdgeRedirectVersion99ca93e354 AWS::Lambda::Version + Add LambdaEdgeRedirect AWS::Lambda::Function ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ Changeset created successfully. arn:aws:cloudformation:us-east-1:xxxxxxxxxx:changeSet/samcli-deploy1576813459/317ce883-2970-4a65-8c8a-xxxxxxxxxxx 2019-12-20 12:44:27 - Waiting for stack create/update to complete CloudFormation events from changeset --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- ResourceStatus ResourceType LogicalResourceId ResourceStatusReason --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- CREATE_IN_PROGRESS AWS::IAM::Role IamLambdaExecutionRoleReadOnly Resource creation Initiated CREATE_IN_PROGRESS AWS::IAM::Role IamLambdaExecutionRoleBasic Resource creation Initiated CREATE_IN_PROGRESS AWS::IAM::Role IamLambdaExecutionRoleFullAccess Resource creation Initiated CREATE_IN_PROGRESS AWS::DynamoDB::Table AlienCardsDynamoDBTable Resource creation Initiated CREATE_IN_PROGRESS AWS::IAM::Role IamLambdaExecutionRoleReadOnly - CREATE_IN_PROGRESS AWS::IAM::Role IamLambdaExecutionRoleFullAccess - CREATE_IN_PROGRESS AWS::CloudFront::CloudFrontOriginAccessIdentity AlienCardsCloudFrontOAI - CREATE_IN_PROGRESS AWS::IAM::Role IamLambdaExecutionRoleBasic - CREATE_IN_PROGRESS AWS::DynamoDB::Table AlienCardsDynamoDBTable - CREATE_IN_PROGRESS AWS::S3::Bucket AlienCardsS3Bucket - CREATE_IN_PROGRESS AWS::S3::Bucket AlienCardsS3Bucket Resource creation Initiated
後はCloudFrontの展開まで少々時間がかかるので、作成まで待ちます。
Stack WsLambdaAtEdgeAlienCardsSAM outputs: ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- OutputKey-Description OutputValue ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- AlienCardsCloudFrontDistributionDomainName - https://xxxxxxxxx.cloudfront.net ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Successfully created/updated stack - WsLambdaAtEdgeAlienCardsSAM in us-east-1
確認
出力されたURL(https://xxxxxxxxx.cloudfront.net)にアクセスしてみてください。下記のようなワークショップで実施したLambda@Edgeでカスタマイズしたサイトができあがっていれば成功です
下記のサイトができあがります。期間限定公開(1週間程度で消します)猫好きなひとは、猫に+1してください https://d36ezg14dehmvr.cloudfront.net/
当然ながらobservatory.mozilla.org(セキュリティ評価サイト)でもA+
をとれます。
やったこと
- re:Inventで約2時間のワークショップに参加します。内容を理解します
- AWSの公式リポジトリをクローンします
- ワークショップ同様にCloudFormationにLambda関数(Lambda@Edge用)5つをテンプレートに追加します
- SAM化します
- CloudFrontのビヘイビアに設定します
つまったところ
- SAM可した際に、BootstrapのLambdaもSAM可された
- cfn-response.jsが無くエラーが発生(CloudFormationでzipでコード化する時のみに追加される)
- 1関数のみ除外する方法が不明だったためSAM化した
- Lambda@Edge関数に環境変数が使えなかった
- 変数(DynamoDBのテーブル名)を固定化した
- Lambdaのバージョンをビヘイビアで指定するがソース更新に追従しない
- AutoPublishAlias: live で対応し、バージョンを作り直すようにした
- CloudFrontの作成時にLambda関数が存在しない旨のエラーが発生する
- DependsOnにLambdaVersionを追加しようとするがSAMがランダムなリソース名が生成されるため指定できない
- DependsOnにLambdaEdgeXXXXXXAliaslive(6つ)を追加
まとめ
Lambda関数のアップデートをした際に、sam deploy
だけで、反映されるのでかなり楽になりました。
かなり楽にはなったんですが、そこも面倒になってきて、pushするだけでならないかなと思い始めたので
次は機会があれば、パイプライン可(CI/CD可)をしてみようと思います。
Cleanup
リソースの削除は、CloudFormationのスタックを消すだけなのですが、Lambda@Edgeで使用されている関数は削除されるまで1時間程度かかりますので、1度削除してエラーが発生した場合は、時間をあけて、再度削除をお願いします。
aws cloudformation delete-stack --stack-name WsLambdaAtEdgeAlienCards --region us-east-1
SAM可したtemplate
参考情報
AWS公式リポジトリ https://github.com/aws-samples/aws-lambda-edge-workshops