はじめに
今回はMappings
セクションとConditions
セクションを使って、環境ごとの値設定と、条件関数による切り替えを実施してみようと思います。
Mappingsセクションについて
キーと名前付きの値が対応付けられたグループ化機能となります。
「AWS CloudFormationユーザガイド」ではリージョンごとにAMI ID
をマッピングした例が紹介されております。
Mappings:
RegionMap:
us-east-1:
"HVM64": "ami-0ff8a91507f77f867"
us-west-1:
"HVM64": "ami-0bdb828fd58c52235"
また、Mappings
セクションで対応付けた値は以下の様にFn::FindInMap:
(短縮形!FindInMap
)関数で呼び出すことができます。
AWSTemplateFormatVersion: "2010-09-09"
Mappings:
RegionMap:
us-east-1:
HVM64: ami-0ff8a91507f77f867
us-west-1:
HVM64: ami-0bdb828fd58c52235
Resources:
myEC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", HVM64]
InstanceType: m1.small
Conditionsセクションについて
条件式を記載するセクションとなります。
他の開発言語と比べると使用できる条件は少ないですが、よほど凝ったことをしなければ問題にはならないでしょう。
内容 | 条件関数 | 完全名関数の構文 | 短縮形の構文 |
---|---|---|---|
AND条件 | Fn::And | Fn::And: [condition] | !And [condition] |
比較 | Fn::Equals | Fn::Equals: [value_1, value_2] | !Equals [value_1, value_2] |
IF条件 | Fn::If | Fn::If: [condition_name, value_if_true, value_if_false] | !If [condition_name, value_if_true, value_if_false] |
否定 | Fn::Not | Fn::Not: [condition] | !Not [condition] |
OR条件 | Fn::Or | Fn::Or: [condition, ...] | !Or [condition, ...] |
使い方としてはConditions
セクションで判定方法を記載して、他のセクションでリソース作成の条件等で、Conditions
セクションで指定した名前を呼び出して使用します。
最初いまいちイメージが掴みづらかったのですが、シェルスクリプトのif文
でいうtestコマンド
による判定部分がConditions
セクションに当たり、後からCondition名
として他セクションから呼び出します。
Conditions:
CreateProdResources: !Equals [ !Ref EnvType, prod ]
Resources:
EC2Instance:
Type: "AWS::EC2::Instance"
Properties:
ImageId: !FindInMap [RegionMap, !Ref "AWS::Region", AMI]
MountPoint:
Type: "AWS::EC2::VolumeAttachment"
Condition: CreateProdResources
Properties:
InstanceId:
!Ref EC2Instance
VolumeId:
!Ref NewVolume
Device: /dev/sdh
NewVolume:
Type: "AWS::EC2::Volume"
Condition: CreateProdResources
Properties:
Size: 100
AvailabilityZone:
!GetAtt EC2Instance.AvailabilityZone
Outputs:
VolumeId:
Condition: CreateProdResources
Value:
!Ref NewVolume
今回作成する構成
今回は以下のようなシナリオを想定して構成を作ってみようと思います。
- 開発環境か本番環境かをユーザに選択させる。
- 選択した環境用のキーペアを
EC2インスタンス
に紐づける。 - 本番環境の場合、追加で
EC2インスタンス
を作成して2台構成とする。
事前準備
今回は予め各環境用のキーペアを作成しておきます。
環境 | キーペア名 |
---|---|
開発環境用キーペア | staging_key |
本番環境用キーペア | production_key |
Parametersセクションへの設定追加
今回も前回作成したテンプレートとパラメータファイルをベースに作成していきます。
前回のテンプレート(展開して下さい)
AWSTemplateFormatVersion: 2010-09-09
Metadata:
'AWS::CloudFormation::Designer':
e1390660-013a-4523-9893-ccd6074e430f:
size:
width: 190
height: 190
position:
x: 390
'y': 90
z: 0
embeds:
- e6cc612e-5a0f-459b-8329-3a5852613031
e6cc612e-5a0f-459b-8329-3a5852613031:
size:
width: 140
height: 140
position:
x: 410
'y': 130
z: 1
parent: e1390660-013a-4523-9893-ccd6074e430f
iscontainedinside:
- e1390660-013a-4523-9893-ccd6074e430f
Resources:
EC2VPC1WR8B:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VPCRange
Metadata:
'AWS::CloudFormation::Designer':
id: e1390660-013a-4523-9893-ccd6074e430f
EC2SJOWQ:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref EC2VPC1WR8B
CidrBlock: !Ref SubnetRange
Metadata:
'AWS::CloudFormation::Designer':
id: e6cc612e-5a0f-459b-8329-3a5852613031
EC2I3Q8S8:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0cc75a8978fbbc969
InstanceType: t2.micro
NetworkInterfaces:
- SubnetId: !Ref EC2SJOWQ
DeviceIndex: 0
Parameters:
VPCRange:
Type: String
Description: "VPC Subnet Range"
SubnetRange:
Type: String
Description: "Subnet Range"
Outputs:
VPCRegion:
Description: "Region Name"
Value: !Ref AWS::Region
前回のパラメータファイル(展開して下さい)
[
{ "ParameterKey" : "VPCRange", "ParameterValue" : "172.24.0.0/16" },
{ "ParameterKey" : "SubnetRange", "ParameterValue" : "172.24.0.0/24" }
]
今回は環境をユーザに選択させたいためAllowedValues
で選択させるようにしようと思います。
ちなみにAllowedValues
を設定するとデザイナー画面から入力する際に以下のように選択式にすることができます。
まぁ、CLIからやるのであればあまり関係ありませんが・・・
前回VPCRange
とSubnetRange
のパラメータを作成しているので、その下にEnvType
を追記してください。
Parameters:
EnvType:
Type: String
Description: "Production or Staging"
AllowedValues: ["Production", "Staging"]
Mappingsセクションの記載
事前作業として作成した各環境のキーペアを指定するようにMappings
セクションを作成します。
Mappings:
Keypair: ★Map名
productionkey: ★キー値
"KEYPAIR": "production_key" ★値
stagingkey:
"KEYPAIR": "staging_key"
Mappings
セクションで指定した値は!FindInMap ["Map名", "キー値", "値"]
で取得します。
Conditionsセクションの記載
先ほどParameters
セクションで作成したEnvType
を呼び出し、本番環境を選択しているかどうかを判定します。
Conditions:
EnvSelect: {"Fn::Equals": [{"Ref" : "EnvType"}, "Production"]}
Resourcesセクションの記載
Conditions
セクションで作成した本番環境の判定条件を、本番環境用キーペアの作成と、2台目のEC2インスタンス
作成条件として使用します。
本番環境用キーペアの作成条件
キーペアを指定するEC2インスタンス
リソースのKeyName
にConditions
セクションで作成した条件を使用して本番環境用キーペアと開発環境用キーペアを指定するようにしたいと思います。
前回のテンプレートを使用してKeyName
を以下のように指定します。
EC2I3Q8S8:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0cc75a8978fbbc969
InstanceType: t2.micro
KeyName: {Fn::If: [EnvSelect, !FindInMap [ Keypair, productionkey, KEYPAIR ], !FindInMap [ Keypair, stagingkey, KEYPAIR ]]}
NetworkInterfaces:
- SubnetId: !Ref EC2SJOWQ
DeviceIndex: 0
上記はFn::If
で条件関数を使用し、判定条件をEnvSelect
で呼び出し、EnvSelect
の結果が真
の場合はMappings
セクションのproductionkey
のキーペア名を指定、偽
の場合はMappings
セクションのstagingkey
のキーペア名を指定する条件式となります。
本番環境用インスタンスの作成
本番環境の場合に、2台目のEC2インスタンス
を作成するようにします。
下記1行目のインスタンス名以外、「本番環境用キーペアの作成条件」で作成した内容とほぼ同じですが、最終行のCondition
でEnvSelect
が真
の場合にのみEC2インスタンス
を作成するようにします。
EC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0cc75a8978fbbc969
InstanceType: t2.micro
KeyName: {Fn::If: [EnvSelect, !FindInMap [ Keypair, productionkey, KEYPAIR ], !FindInMap [ Keypair, stagingkey, KEYPAIR ]]}
NetworkInterfaces:
- SubnetId: !Ref EC2SJOWQ
DeviceIndex: 0
Condition: EnvSelect
テンプレートの実行
今回もCLIで実行するため、パラメータファイルにも今回追加した設定を記載して実行していきます。
完成したテンプレート(展開して下さい)
AWSTemplateFormatVersion: 2010-09-09
Metadata:
'AWS::CloudFormation::Designer':
e1390660-013a-4523-9893-ccd6074e430f:
size:
width: 190
height: 190
position:
x: 390
'y': 90
z: 0
embeds:
- e6cc612e-5a0f-459b-8329-3a5852613031
e6cc612e-5a0f-459b-8329-3a5852613031:
size:
width: 140
height: 140
position:
x: 410
'y': 130
z: 1
parent: e1390660-013a-4523-9893-ccd6074e430f
iscontainedinside:
- e1390660-013a-4523-9893-ccd6074e430f
Resources:
EC2VPC1WR8B:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VPCRange
Metadata:
'AWS::CloudFormation::Designer':
id: e1390660-013a-4523-9893-ccd6074e430f
EC2SJOWQ:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !Ref EC2VPC1WR8B
CidrBlock: !Ref SubnetRange
Metadata:
'AWS::CloudFormation::Designer':
id: e6cc612e-5a0f-459b-8329-3a5852613031
EC2I3Q8S8:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0cc75a8978fbbc969
InstanceType: t2.micro
KeyName: {Fn::If: [EnvSelect, !FindInMap [ Keypair, productionkey, KEYPAIR ], !FindInMap [ Keypair, stagingkey, KEYPAIR ]]}
NetworkInterfaces:
- SubnetId: !Ref EC2SJOWQ
DeviceIndex: 0
EC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0cc75a8978fbbc969
InstanceType: t2.micro
KeyName: {Fn::If: [EnvSelect, !FindInMap [ Keypair, productionkey, KEYPAIR ], !FindInMap [ Keypair, stagingkey, KEYPAIR ]]}
NetworkInterfaces:
- SubnetId: !Ref EC2SJOWQ
DeviceIndex: 0
Condition: EnvSelect
Parameters:
VPCRange:
Type: String
Description: "VPC Subnet Range"
SubnetRange:
Type: String
Description: "Subnet Range"
EnvType:
Type: String
Description: "Production or Staging"
AllowedValues: ["Production", "Staging"]
Outputs:
VPCRegion:
Description: "Region Name"
Value: !Ref AWS::Region
Mappings:
Keypair:
productionkey:
"KEYPAIR": "production_key"
stagingkey:
"KEYPAIR": "staging_key"
Conditions:
EnvSelect: {"Fn::Equals": [{"Ref" : "EnvType"}, "Production"]}
完成したパラメータファイル(開発環境向け)(展開して下さい)
[
{ "ParameterKey" : "VPCRange", "ParameterValue" : "172.24.0.0/16" },
{ "ParameterKey" : "SubnetRange", "ParameterValue" : "172.24.0.0/24" },
{ "ParameterKey" : "EnvType", "ParameterValue" : "Staging" }
]
開発環境用EC2インスタンスの作成
上記のパラメータファイルはEnvType
のParameterValue
にStaging
を指定しているので、以下コマンドを実行すると、開発環境用のキーペアが指定されたEC2インスタンス
が作成されます。
aws cloudformation create-stack --template-body file:///home/ec2-user/cloudformation.yaml --stack-name stack-test --parameters file:///home/ec2-user/param.json
CloudFormation
のリソース画面とEC2
のインスタンス画面を見ると、開発環境用のキーペアが付与されたEC2インスタンス
が1台作成されているのが確認できます。
次の作業のためにいったんテンプレートを削除しておきます。
aws cloudformation delete-stack --stack-name stack-test
本番環境用EC2インスタンスの作成
パラメータファイルのEnvType
のParameterValue
をProduction
に書き換えて再度テンプレートを作成します。
完成したパラメータファイル(本番環境向け)(展開して下さい)
[
{ "ParameterKey" : "VPCRange", "ParameterValue" : "172.24.0.0/16" },
{ "ParameterKey" : "SubnetRange", "ParameterValue" : "172.24.0.0/24" },
{ "ParameterKey" : "EnvType", "ParameterValue" : "Production" }
]
aws cloudformation create-stack --template-body file:///home/ec2-user/cloudformation.yaml --stack-name stack-test --parameters file:///home/ec2-user/param.json
CloudFormation
のリソース画面とEC2
のインスタンス画面を見ると、本番環境用のキーペアが付与されたEC2インスタンス
が2台作成されているのが確認できます。
おわりに
Mappings
とConditions
を使用することで、1つのソースを複数の環境で使いまわすことができるので、特定の環境だけ追加した設定を反映し忘れたといったことが防げそうです。
次回はまだ使っていないTransform
セクションを使ってみようと思います。