share facebook facebook twitter menu hatena pocket slack

2019.07.24 WED

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

甲斐 甲

WRITTEN BY 甲斐 甲

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://cloudpack.media/48205

参考

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://cloudpack.media/48205

元記事はこちら

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

甲斐 甲

甲斐 甲

2018/7にJOIN。 最近の好みはサーバレスです。なんでもとりあえず試します。

cloudpack

cloudpackは、Amazon EC2やAmazon S3をはじめとするAWSの各種プロダクトを利用する際の、導入・設計から運用保守を含んだフルマネージドのサービスを提供し、バックアップや24時間365日の監視/障害対応、技術的な問い合わせに対するサポートなどを行っております。
AWS上のインフラ構築およびAWSを活用したシステム開発など、案件のご相談はcloudpack.jpよりご連絡ください。