AWS CloudFormationのLambda-Backedカスタムリソースでリソース作成を待ち受けできるようにする

cloudpack あら便利カレンダー 2019 の記事となります。誕生秘話 はこちら。

AWS CloudFormation(CFn)のLambda-Backedカスタムリソースを利用するとCFnが対応していないリソースでもAWS Lambdaを利用して管理できます。

AWS Lambda-backed カスタムリソース - AWS CloudFormation

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html

その際に、リソース作成するとレスポンスはすぐに返ってくるけど、リソースが利用できるまでに時間がかかるものを取り扱えるようにしてみました。


テンプレート

CFnでリソース作成を待ってから関連するリソース作成などができるようにするテンプレートです。

Resources:

CreateResource:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt CreateResourceFunction.Arn

CustomResource:
Type: Custom::CustomResource
Properties:
ServiceToken: !GetAtt CustomResourceFunction.Arn
ResourceId: !GetAtt CreateResource.Id
DependsOn: CreateResource

CreateResourceFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: !GetAtt FunctionExecutionRole.Arn
Code:
ZipFile: !Sub |
import cfnresponse
def handler(event, context):
response = {}
if event['RequestType'] == 'Create':
try:
# ほんとはここでリソース作成
response = {
"Id": "hoge"
}
except Exception as e:
response = {'error': str(e)}
cfnresponse.send(event, context, cfnresponse.FAILED, response)
return

cfnresponse.send(event, context, cfnresponse.SUCCESS, response)
Runtime: python3.7

CustomResourceFunction:
Type: AWS::Lambda::Function
Properties:
Handler: index.handler
Role: !GetAtt FunctionExecutionRole.Arn
Code:
ZipFile: !Sub |
import cfnresponse
import time
def handler(event, context):
Id = event['ResourceProperties']['ResourceId']

# リソース作成完了を待ち受ける
response = {}
while True:
# ホントはここでリソース取得
response = {
"Id": Id,
"Status": "AVAILABLE"
}

# 特定のステータスになったら抜ける
if response['Status'] == 'AVAILABLE':
break
print('create wait...')
time.sleep(60)

cfnresponse.send(event, context, cfnresponse.SUCCESS, response)
Runtime: python3.7
Timeout: 900

FunctionExecutionRole:
Type: AWS::IAM::Role
Properties:
AssumeRolePolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Principal:
Service:
- lambda.amazonaws.com
Action:
- sts:AssumeRole
Path: "/"
Policies:
- PolicyName: root
PolicyDocument:
Version: '2012-10-17'
Statement:
- Effect: Allow
Action:
- logs:CreateLogGroup
- logs:CreateLogStream
- logs:PutLogEvents
Resource: "arn:aws:logs:*:*:*"


ポイント


カスタムリソースを2つ用意する

リソースを作成するCreateResource とリソース情報を取得するCustomResource のカスタムリソースを定義することで、リソース作成を待ち受けできるようにしています。


Lambda関数のタイムタウト x 3回まで待ち受けできる

AWS Lambdaの関数は最大15分のタイムタウト設定ができます。またLambda-Backedカスタムリソースで関数実行に失敗すると3回までリトライしてくれるのでそれを利用して最大45分間待ち受けできるようになります。

AWS Lambda の制限 - AWS Lambda

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html

※Lambda-Backedカスタムリソースでのリトライ回数について必ず3回実行されるのかはドキュメントが見当たらず不明確となります。

AWS Lambda 再試行動作 - AWS Lambda

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/retries-on-errors.html


DependsOn 属性を利用してリソース作成順を制御する

CFnのDependsOn 属性を利用することで、リソース作成CreateResource 後、リソース情報取得CustomResource が実行されるようにします。

後続するリソースはCustomResourceDependsOn 属性に指定することでリソース作成完了してから実行されるようにできます。

DependsOn 属性 - AWS CloudFormation

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html


カスタムリソースの更新・削除と絡めて利用する

下記記事の内容と組み合わせることで、カスタムリソースの更新・削除が実現できます。

AWS CloudFormationのLambda-backedカスタムリソースでリソースの更新・削除をする方法 - Qiita

https://qiita.com/kai_kou/items/7be2eb9a36611bb5da12


参考

AWS Lambda-backed カスタムリソース - AWS CloudFormation

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/template-custom-resources-lambda.html

AWS Lambda の制限 - AWS Lambda

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/limits.html

AWS Lambda 再試行動作 - AWS Lambda

https://docs.aws.amazon.com/ja_jp/lambda/latest/dg/retries-on-errors.html

DependsOn 属性 - AWS CloudFormation

https://docs.aws.amazon.com/ja_jp/AWSCloudFormation/latest/UserGuide/aws-attribute-dependson.html

AWS CloudFormationのLambda-backedカスタムリソースでリソースの更新・削除をする方法 - Qiita

https://qiita.com/kai_kou/items/7be2eb9a36611bb5da12