ENGINEER BLOG ENGINEER BLOG
  • 公開日
  • 最終更新日

【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

お疲れさまでした。

この記事は私が書きました

嶋田 龍登

記事一覧

インフラからアプリのことまでなんでもやりたい、フルスタックを目指すエンジニア

嶋田 龍登

この記事を共有する

クラウドのご相談

CONTACT

クラウド導入や運用でお悩みの方は、お気軽にご相談ください。
専門家がサポートします。

サービス資料ダウンロード

DOWNLOAD

ビジネスをクラウドで加速させる準備はできていますか?
今すぐサービス資料をダウンロードして、詳細をご確認ください。