- 公開日
- 最終更新日
【CloudFormation】カスタムリソースでデプロイの振る舞いをカスタマイズする
この記事を共有する
はじめに
パーソル&サーバーワークス嶋田です。
CloudFormationテンプレートには、カスタムリソースと呼ばれるTypeがあります。
カスタムリソースの実態として、LambdaまたはSNSが裏で動作させられるため、
CloudFormationデプロイに持たせる振る舞いや効果を柔軟にカスタマイズ可能です。
本ブログではLambdaカスタムリソースの作成から実行まで簡単に紹介します。
本ブログで使うテンプレート
本ブログでは以下のテンプレートファイル名を custom-resource.yaml として扱います。
# custom-resource.yaml
AWSTemplateFormatVersion: '2010-09-09'
Description: Custom Resource Tutorial
Resources:
LambdaExecutionRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: "2012-10-17"
Statement:
- Effect: "Allow"
Principal:
Service:
- "lambda.amazonaws.com"
Action:
- "sts:AssumeRole"
ManagedPolicyArns:
- "arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole"
YesNoFunction:
Type: AWS::Lambda::Function
Properties:
Code:
ZipFile: |
const response = require("cfn-response")
const url = "https://yesno.wtf/api"
exports.handler = async function (event, context) {
try {
const result = await (await fetch(url, { method: "GET" })).json()
await response.send(
event,
context,
response.SUCCESS,
{
...result,
appendixValue: event.ResourceProperties.AppendixValue,
fullData: JSON.stringify(result)
}
)
} catch (error) {
console.error(error)
await response.send(
event,
context,
response.FAILED
)
}
};
Timeout: 30
Handler: index.handler
Role: !GetAtt LambdaExecutionRole.Arn
Runtime: nodejs22.x
Architectures:
- x86_64
CustomResourceTutorial:
Type: AWS::CloudFormation::CustomResource
Properties:
ServiceTimeout: 30
ServiceToken: !GetAtt YesNoFunction.Arn
AppendixValue: "test string"
Outputs:
YesNoResultAnswer:
Value: !GetAtt CustomResourceTutorial.answer
YesNoResultForced:
Value: !GetAtt CustomResourceTutorial.forced
YesNoResultImage:
Value: !GetAtt CustomResourceTutorial.image
YesNoResultFull:
Value: !GetAtt CustomResourceTutorial.fullData
YesNoResultAppendixValue:
Value: !GetAtt CustomResourceTutorial.appendixValue
テンプレートの中身を解説
Type: AWS::CloudFormation::CustomResource
本ブログの主役です。カスタムリソースです。
カスタムリソースには2つのプロパティ+αが使えます。
- ServiceTimeout
- タイムアウト値、単位は秒
- ServiceToken
- LambdaまたはSNSのARN
- +α
- 独自で定義したKey, Valueのセット。今回は AppendixValue が該当
今回は、カスタムリソースとしてLambdaを使います。
cfn-response
Lambdaの実装も、本テンプレートにて行っていますが、これには理由があります。
カスタムリソースの実装を楽にしてくれる cfn-response モジュールがあります。
このモジュールを使うためには、Zip化してLambdaレイヤーとしてあげるか、
CloudFormationテンプレートで、インライン(ZipFile内)でロジックを記述する必要があります。
https://yesno.wtf/api
以下のフォーマットでレスポンスを返してくれるAPIです。
{"answer":"no","forced":false,"image":"https://yesno.wtf/assets/no/17-829284e9dd894ce9fb65fbe86d2e382c.gif"}
CloudFormationテンプレートのOutputsとして値を出力する用にお借りします。
デプロイ時に、カスタムリソースとして定義したLambdaが動いていることを確認する用です。
response.send()
カスタムリソースはCloudFormationに応答を返す必要があります。
このあたりの処理を、よしなにやってくれるメソッドです。
その他
実行タイミング
カスタムリソースで定義したリソースが実行されるタイミングですが、3つあります。
これらのタイミングは、event.RequestType に値が格納されています。
PhysicalResourceId
この値が変化する場合は、カスタムリソースの置き換えが生じるようです。
AWSドキュメントには以下の記述があります。
PhysicalResourceId に返される値は、カスタム・リソースの更新操作によって変更されることがあります。返される値が同じ場合は、通常の更新と見なされます。返された値が異なる場合、AWS CloudFormationは更新を置き換えと認識し、古いリソースに削除リクエストを送信します。詳細はAWS::CloudFormation::CustomResourceを参照してください。
デプロイする
スタック名を CustomResourceTutorial としてデプロイします。
$ aws cloudformation deploy --stack-name CustomResourceTutorial --template-file custom-resource.yaml --capabilities CAPABILITY_IAM Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - CustomResourceTutorial
デプロイ後のOutputsを確認する
$ aws cloudformation describe-stacks --stack-name CustomResourceTutorial --query "Stacks[0].Outputs" --output table
---------------------------------------------------------------------------------------------------------------------------------------------
| DescribeStacks |
+--------------------------+----------------------------------------------------------------------------------------------------------------+
| OutputKey | OutputValue |
+--------------------------+----------------------------------------------------------------------------------------------------------------+
| YesNoResultFull | {"answer":"no","forced":false,"image":"https://yesno.wtf/assets/no/8-5e08abbe5aacd2cf531948145b787e9a.gif"} |
| YesNoResultAppendixValue| test string |
| YesNoResultForced | false |
| YesNoResultAnswer | no |
| YesNoResultImage | https://yesno.wtf/assets/no/8-5e08abbe5aacd2cf531948145b787e9a.gif |
+--------------------------+----------------------------------------------------------------------------------------------------------------+
まとめ
カスタムリソースをCloudFormationテンプレートに取り入れることで、
LambdaやSNSを活用し、より柔軟な機能が実現可能になります。
コードの記述が伴うので、管理・保守・運用といったことまで検討した上で取り入れたいです。
最後に、後片付けを忘れずにしておきましょう。
aws cloudformation delete-stack --stack-name CustomResourceTutorial
お疲れさまでした。
この記事は私が書きました
嶋田 龍登
記事一覧インフラからアプリのことまでなんでもやりたい、フルスタックを目指すエンジニア