AWS Lambda の Provisioned Concurrency の設定を CloudFormation テンプレートのパラメータで有効無効を切り替えられる Conditions と If の組み合わせ例の紹介

CloudFromation の Conditions, If, AWS::NoValue を使ったパラメータの値を判定して設定を切り替えるテンプレート設定例の紹介です。
2022.02.03

Lambda のコールドスタート対策で利用する Provisioned Concurrency の設定をパラメータの値によって有効、無効にするSAMテンプレートを紹介します。SAMテンプレートベースですがCloudFormationテンプレートのConditionsIfの組み合わせ例の参考にもなるかと思います。

実現したいこと

お題はシンプルです。

  • 同時実行数の数をCloudFormationのパラメータで指定します。
  • パラメータの数値が0の場合は Provisioned Concurrency を無効化(未設定状態にしたい)
  • パラメータの雛妓は1以上の場合は Provisioned Concurrency を設定し有効化

ですが、CloudFormationは愚直な書き方になりがちなので意外とややこしいことになります。 それではConditionsIfAWS::NoValueを駆使して処理してみましょう。

SAMテンプレート

sam initコマンドで生成した Hello World テンプレートをベースに設定を追加しました。

コードは以下のリンクに置いてあります。

解説

解説はテンプレート内にコメントで記しました。ポイントはIfAWS::NoValueの組み合わせにより設定する予定のプロパティを削除するところです。

本文中にコメントで書いた方が見やすいと思ってたのですが横幅の関係でみづらいかもしれません。コピペして画面いっぱい広げられるエディタで見てい頂いた方が見やすいかと思います。

template.yaml

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Description: >
  sam-app

  Sample SAM Template for sam-app

# ----- Parameter設定 -----
Parameters:
  ProvisionedConcurrentCount: # パラメータで同時実行数を指定します
    Type: Number
    Default: 0 # デフォルト値は0にしていますが、デプロイ時にパラメータの指定で上書きできます
Conditions: # 0かそれ以外かの判定をします
  ProvisionedConcurrency: # 1つ下の行の判定結果が格納されます
    !Not [!Equals [!Ref ProvisionedConcurrentCount, 0]] # True: 0以外のとき / False: 0のときという意味の判定文です
# ----- ここまで -----

Globals:
  Function:
    Timeout: 5

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      # ---- 同時実行数設定 -----
      AutoPublishAlias: live # Provisioned Concurrency の設定には Alias が必須
      ProvisionedConcurrencyConfig: !If # 第1引数を条件式として True / False を判定し、True であれば第2引数が False であれば第3引数が採用されます
        - ProvisionedConcurrency # 0以外のときは True であり、0のときは False が格納されています(Conditions句のところ)
        - ProvisionedConcurrentExecutions: !Ref ProvisionedConcurrentCount # True のときは第2引数が採用されます。指定された数値分の Provisioned Concurrency 設定をしています
        - !Ref "AWS::NoValue" # False のときは第3引数が採用されます。AWS::NoValue の効果により ProvisionedConcurrencyConfig プロパティを削除します。(Provisioned Concurrencyの無効化 = デフォルトの状態)
      # ---- ここまで -----
      Events:
        HelloWorld:
          Type: Api
          Properties:
            Path: /hello
            Method: get

Outputs:
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

AWS::NoValueについては以下のリンクが参考になります。

実行結果確認

解説したSAMテンプレートをsam build, sam deployコマンドでAWS上にリソースを作成します。

0指定で設定を無効にしたとき

samconfig.toml内でパラメータの値を指定します。

samconfig.toml

version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "lambdaConncurrencyConfigSample"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1lcx29wiwvv2b"
s3_prefix = "lambdaConncurrencyConfigSample"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
image_repositories = []
parameter_overrides = "ProvisionedConcurrentCount=\"0\""

パラメータProvisionedConcurrentCount0でデプロイした Lambda 関数の設定状況です。プロビジョニングされた同時実行設定は未設定となっています。普通に Lambda 関数を作成すると設定されていないことがデフォルトの状態です。

1以上を指定し有効にしたとき

samconfig.toml内でパラメータの値を変更します。

samconfig.toml

version = 0.1
[default]
[default.deploy]
[default.deploy.parameters]
stack_name = "lambdaConncurrencyConfigSample"
s3_bucket = "aws-sam-cli-managed-default-samclisourcebucket-1lcx29wiwvv2b"
s3_prefix = "lambdaConncurrencyConfigSample"
region = "ap-northeast-1"
confirm_changeset = true
capabilities = "CAPABILITY_IAM"
image_repositories = []
parameter_overrides = "ProvisionedConcurrentCount=\"1\""

パラメータProvisionedConcurrentCount1でデプロイした Lambda 関数の設定状況です。プロビジョニングされた同時実行設定が作られています。

以上、ConditionsIfAWS::NoValueの組み合わせによるプロパティ作成ありなしの判定方法でした。

終わりに

お題のようなお問い合わせを頂いた際にサンプルで提示したテンプレートに解説をつけて紹介しました。同様のケースであればググって解決できるようにブログに残しました。ConditionsIfAWS::NoValueの組み合わせ参考例としても役に立つような気がしています。どなたかのお役にたてれば光栄です。