- 公開日
- 最終更新日
CloudFormationで環境差分を解決する:よく使うテクニック4選
この記事を共有する

目次
はじめに
こんにちは!パーソル&サーバーワークスの野間です。
AWS CloudFormation(以下、CloudFormatin)で複数環境(dev / stg / prd)を別々のテンプレートで管理していると、設定変更時の手間が増えたりオペレーションミスの原因にもなります。
本記事では CloudFormationテンプレートの環境差分を吸収し、運用効率化をするためによく使うテクニックをまとめます。
よく使うテクニック4選
個人的によく使うテクニックを、以下の AWS Lambda 関数を作成するテンプレートを使って紹介します!
テンプレートではParametersで環境を選択できるようにしています。
CloudFormationテンプレート
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Parameters:
Env:
Type: String
AllowedValues: [dev, stg, prd]
Project:
Type: String
Handler:
Type: String
Mappings:
EnvMapping:
dev:
MemorySize: 128
Timeout: 5
stg:
MemorySize: 256
Timeout: 10
prd:
MemorySize: 256
Timeout: 10
Conditions:
IsPrd: !Equals [!Ref Env, prd]
Resources:
LambdaSG:
Type: AWS::EC2::SecurityGroup
Properties:
GroupDescription: !Sub lambda-sg-${Project}-${Env}
VpcId: !ImportValue LambdaVpcId
LambdaFunction:
Type: AWS::Serverless::Function
Properties:
FunctionName: !Sub api-${Env}
Role: !Sub arn:aws:iam::${AWS::AccountId}:role/${Project}-${Env}-lambda-exec
Handler: !Ref Handler
Runtime: python3.12
MemorySize: !FindInMap [EnvMapping, !Ref Env, MemorySize]
Timeout: !FindInMap [EnvMapping, !Ref Env, Timeout]
ReservedConcurrentExecutions: !If [IsPrd, 20, !Ref AWS::NoValue]
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSG
SubnetIds:
- Fn::ImportValue: !Sub ${Project}-PrivateSubnet1
- Fn::ImportValue: !Sub ${Project}-PrivateSubnet2
Environment:
Variables:
STAGE: !Ref Env
Events:
Api:
Type: HttpApi
1.環境毎に設定値が異なる場合は Mappings 使う
環境ごとに設定値が異なっている場合は Mappings を使って差分を吸収します。
今回の場合は、メモリ/タイムアウトの値を環境別に切り替えるようにしています。
Mappings:
EnvMapping:
dev:
MemorySize: 128
Timeout: 5
stg:
MemorySize: 256
Timeout: 10
prd:
MemorySize: 256
Timeout: 10
また、AWS::Serverless::Functionで呼び出す際は、以下のように記載します。
MemorySize: !FindInMap [EnvMapping, !Ref Env, MemorySize]
Timeout: !FindInMap [EnvMapping, !Ref Env, Timeout]
2.アカウントIDなどは疑似パラメーターを使う
アカウントIDやリージョンなどは疑似パラメーターを利用することで差分を吸収します。
今回は IAM Role の ARN の記載に利用しています。
Role: !Sub arn:aws:iam::${AWS::AccountId}:role/${Project}-${Env}-lambda-exec
3. 固有のリソースIDはハードコードしない
リソース固有のIDはハードコードせずに組み込み関数(!Ref、!ImportValue など)を利用することで差分を吸収します。
同じテンプレート内にある場合は !Ref や !GetAtt を使って記載します。
VpcConfig:
SecurityGroupIds:
- !Ref LambdaSG
別テンプレートファイルに存在するリソースは !ImportValue を使って記載します。
Properties:
GroupDescription: !Sub lambda-sg-${Project}-${Env}
VpcId: !ImportValue LambdaVpcId
!Sub と !ImportValue を組み合わせることも可能です。
SubnetIds:
- Fn::ImportValue: !Sub ${Project}-PrivateSubnet1
- Fn::ImportValue: !Sub ${Project}-PrivateSubnet2
4. 環境差分は Conditions や AWS::NoValue を使う
prd環境のみ同時実行数の設定を追加する場合など、環境差分は Conditions や AWS::NoValue を利用することで差分を吸収します。
まずは Conditions セクションに条件を記載します。今回の場合は「prd環境のみ」なので以下のように記載しました。
Conditions:
IsProd: !Equals [!Ref Env, prd]
また、AWS::Serverless::Function の中では、以下のように記載します。
20 がprd環境の同時実行数で、それ以外の環境の場合は !Ref AWS::NoValue が適用されます。
つまり、dev、stg環境では同時実行数の設定自体行わないという意味になります。
ReservedConcurrentExecutions: !If [IsPrd, 20, !Ref AWS::NoValue]
まとめ
複数環境 を"1枚のテンプレート"で運用できるのは、運用効率化に大きく貢献するアプローチだと感じました。
CloudFormation を複数環境で運用している方の参考になれば幸いです!
この記事は私が書きました
野間 太一
記事一覧猫とCloudFormationが好きです。
