【アップデート】スタック間のパラメータ渡しが便利に!!CloudFormationのDynamic referencesでSSMパラメータの最新バージョンが参照可能になりました

Cloud Formationスタック間のパラメータ受け渡しがさらに便利になりました!!
2021.04.16

この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。

CX事業本部@大阪の岩田です。

本日のアップデートによりCloudFormationのDynamic references利用時のSSMパラメータのバージョン指定が必須ではなくなりました。

AWSを触っているとCloudFormationのスタックを分割してスタック間でパラメータを受け渡す、というのはよくあるシチュエーションかと思います。スタック間でパラメータを受け渡す方法の1つとしてテンプレート内に{{resolve:ssm:...}}を埋め込み(Dynamic references)パラメータストアからパラメータを取得するという方法があります。従来この方法には課題があり、パラメータのバージョン指定が必須でした。つまりパラメータストアの更新に追随しようと思うとパラメータストアを参照するCFnテンプレートにも更新が必要だったのです。例えば以下のような流れです

  • 親スタックをデプロイ
    • デプロイされたリソースの情報をSSMパラメータストアに書き込む
  • Dynamic referencesを利用して子スタックをデプロイ
  • 親スタックを再デプロイして更新
    • 更新されたリソースの情報でSSMパラメータストアを更新
  • 子スタックがDynamic referencesを利用している箇所のバージョン指定をインクリメント (メンドイ...)
  • 子スタックを再デプロイ

本日のアップデートでバージョン指定が不要になったので、今後はいちいちバージョンのをインクリメントする必要がなくなりました。!!{{resolve:ssm:...}}でSSMパラメータのバージョンを指定しなかった場合はCloudFormation側が自動的に最新バージョンのパラメータ(LATEST)に解決してくれるとのことです。これは嬉しい!!

もちろん従来のように明示的に特定バージョンを指定することも可能です

やってみる

さっそくやってみます。以下のようなシナリオのデプロイを試してみます。

  • Lambdaレイヤーを作成する親スタックをデプロイ
    • このスタックは作成されたレイヤーのバージョンをSSMパラメータストアに書き出す
  • Lambda Functionsを作成する子スタックをデプロイ
    • このスタックは{{resolve:ssm}}を利用し、親スタックがSSMパラメータストアに書き出したレイヤーバージョンを参照する

Lambdaレイヤーを作成する親スタックのテンプレートです。

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:  
  PythonModulesLayer:
    Type: AWS::Serverless::LayerVersion
    Properties:
      Description: CFn resolve test
      ContentUri: layer
      LayerName: iwata-PythonModulesLayer
  SSMParamPythonModulesLayer:
    Type: AWS::SSM::Parameter
    Properties:
      Name: /CmIwata/Dev/PythonModulesLayer
      Type: String
      Value: !Ref PythonModulesLayer

LambdaFunctionを作成する子スタックのテンプレートです。

AWSTemplateFormatVersion: 2010-09-09
Transform: AWS::Serverless-2016-10-31
Resources:
  LambdaFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: index.handler
      Runtime: python3.8
      InlineCode: |
        def handler(event, context):
          print("Hello, world!")
      Layers:
        - '{{resolve:ssm:/CmIwata/Dev/PythonModulesLayer}}'

{{resolve:ssm:/CmIwata/Dev/PythonModulesLayer}} の記述でパラメータのバージョンを指定していないのがポイントです。従来であればエラーとなる記述です。

レイヤーをデプロイ

まずレイヤーをデプロイします。CFnテンプレートがlayerというディレクトリ配下のソースコードを参照してLambdaレイヤーとしてデプロイするので、layerというディレクトリを作成して適当なファイルを突っ込んでおいて下さい。レイヤーの準備ができたら以下のコマンドでデプロイします。

$ aws cloudformation package --template-file layer.yaml --output-template-file out.yaml --s3-bucket <適当なS3バケット>
$ aws cloudformation deploy --template-file out.yaml --stack-name ssm-resolve-test

ver1のレイヤーが作成されました

レイヤーを参照するLambda Functionをデプロイ

続いて子スタックのデプロイです。

$ aws cloudformation deploy --template-file lambda.yaml  --stack-name ssm-resolve-test-lambda --capabilities CAPABILITY_IAM

先程親スタックからデプロイされたレイヤーバージョンを参照していることが分かります。

レイヤーのコードを更新して再度デプロイ

次にレイヤーを更新してデプロイします。layerディレクトリ配下のソースコードを適当に編集し、先程と同じコマンドでデプロイを実行します。

$ aws cloudformation package --template-file layer.yaml --output-template-file out.yaml --s3-bucket <適当なS3バケット>
$ aws cloudformation deploy --template-file out.yaml --stack-name ssm-resolve-test

レイヤーがver2に更新されました。

レイヤーを参照するLambda Functionを再度デプロイ

子スタックを再度デプロイします。

$ aws cloudformation deploy --template-file lambda.yaml  --stack-name ssm-resolve-test-lambda --capabilities CAPABILITY_IAM

マネコンの「処理されたテンプレートの表示」を確認すると{{resolve:ssm...}}が最新版のパラメータを参照していることが分かります

デプロイ完了後にLambdaの設定を確認すると親スタックが更新したレイヤーバージョンを参照できています。

まとめ

以下のスライドでも紹介されているようにCloudFormationのスタック間でパラメータを受け渡すには様々な方法があり、どれも一長一短です。

Dynamic referencesを利用する場合はバージョン指定が必須という仕様がネックだったのですが、今回のアップデートによりこの問題が解消されました。パラメータの受け渡し方法にお悩みの方はぜひDynamic referencesの利用をご検討下さい。