この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
花見に行きたい(酒飲みたい)森永です。
CloudFormationに素敵なアップデートが来たのでご紹介します!
Change Setsとは
今まではCloudFormationのテンプレートをアップデートする際、どのリソースが追加・削除・変更されるのか、変更される場合は、置換が発生するかしないのかという確認は、実際に実行してみないと困難でした。
今回追加されたChange Setsで、アップデートを実行する前にどのような変更が加えられるかを確認できるようになりました!
アップデートにおける簡単なdry-runのような機能と考えるといいかと思います!すごい!
あくまでも簡単なです。詳しくは後述します。
AWS CloudFormation Adds Change Sets for Insight into Stack Updates
試してみる
以下の図のようにVPCにSubnetを2つ配置という構成でひとまずスタックを作成します。
ひとつのAZにサブネットが寄っていて気持ち悪いですね。
テンプレートはこんな感じです。
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "VPC Network Template",
"Mappings" : {
"StackConfig" : {
"VPC" : { "CIDR" : "10.0.0.0/16" },
"Subnet1" : { "CIDR" : "10.0.0.0/24" },
"Subnet2" : { "CIDR" : "10.0.1.0/24" }
}
},
"Resources" : {
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]},
"InstanceTenancy" : "default"
}
},
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway"
},
"AttachGateway" : {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"InternetGatewayId" : { "Ref" : "InternetGateway" }
}
},
"RouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"DependsOn" : "AttachGateway",
"Properties" : {
"VpcId" : { "Ref" : "VPC" }
}
},
"Route" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "AttachGateway",
"Properties" : {
"RouteTableId" : { "Ref" : "RouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
"Subnet1": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs" : { "Ref": "AWS::Region" } }] },
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "Subnet1", "CIDR" ]}
}
},
"Subnet1RouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "Subnet1" },
"RouteTableId" : { "Ref" : "RouteTable" }
}
},
"Subnet2": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs" : { "Ref": "AWS::Region" } }] },
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "Subnet2", "CIDR" ]}
}
},
"Subnet2RouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "Subnet2" },
"RouteTableId" : { "Ref" : "RouteTable" }
}
}
}
}
スタックの作成時には特に変わったことはありません。
今までどおり作成します。
ここからが本番です。
先ほどのテンプレートを以下のようにアップデートしようと思います。
- サブネットを2つのAZに分散
- 別のAZに作り直すことになるので、サブネットの置換が発生するはず!
- VPCでDNSホスト名の設定をオンに
- サブネットでパブリックIP自動割当をオンに
- 設定変更だけなので、置換は発生しないはず!
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "VPC Network Template",
"Mappings" : {
"StackConfig" : {
"VPC" : { "CIDR" : "10.0.0.0/16" },
"Subnet1" : { "CIDR" : "10.0.0.0/24" },
"Subnet2" : { "CIDR" : "10.0.2.0/24" }
}
},
"Resources" : {
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"CidrBlock" : { "Fn::FindInMap" : [ "StackConfig", "VPC", "CIDR" ]},
"InstanceTenancy" : "default",
"EnableDnsHostnames" : "true"
}
},
...省略...
"Subnet1": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::Select": [ "0", { "Fn::GetAZs" : { "Ref": "AWS::Region" } }] },
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "Subnet1", "CIDR" ]},
"MapPublicIpOnLaunch" : "true"
}
},
...省略...
"Subnet2": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::Select": [ "1", { "Fn::GetAZs" : { "Ref": "AWS::Region" } }] },
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "Subnet2", "CIDR" ]}
}
},
...省略...
}
}
では早速やっていきましょう。
先ほど作成したスタックを選択し、「Create Change Set」を選択します。
新しいテンプレートを選択します。
勿論、テンプレートはそのままに、パラメータだけ変更することも可能です。
Change Setの名前と説明を記載します。
こちらはスタック名とはまた違うものとなります。
最後に、タグや通知の設定を行います。
今回は何も指定しないで先へ進みます。
レビュー画面で問題なければ「Create change set」を選択します。
Change Setの詳細画面が出てきて、しばらくすると「Status」がCREATE_COMPLETE
になります。
この時点では実際にアップデートはしていないので早いです。
今回は変更だけを加えたので、「Action」がModify
となっていることが確認できます。
個人的に嬉しいのは「Replacement」です。
CloudFormationでアップデートをした際に、変更するプロパティによってはリソースを作りなおす(置換する)必要があるのですが、EC2のインスタンスを作りなおされたら結構困ります。
「Replacement」を確認することで、アップデート時にそのリソースが置換されるのかが分かります。
ちなみにこの詳細画面は、スタック詳細画面の一番最下段から確認できます。
では、実際にアップデートを実行してみましょう!
Change Setの詳細画面の右上にある「Execute」をクリックします。
確認画面が出ますので、「Execute」!
すると実際のアップデート作業が始まります。
正常に完了したらUPDATE_COMPLETE
と出ます!
Replacement
と出ていたSubnet2は削除されているのが分かりますね。
もう一つ別のChange Setを作成してみましょう。
今度は以下の様な変更を加えます。
- Subnet2を消して、Subnet3を追加
- 実際にはリネームするだけですが、
remove
とadd
を確認できるはず!
- 実際にはリネームするだけですが、
AvailabilityZone
に存在しないAZを指定- dry-runであれば検知して警告して欲しいところ…
{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "VPC Network Template",
"Mappings" : {
"StackConfig" : {
"VPC" : { "CIDR" : "10.0.0.0/16" },
"Subnet1" : { "CIDR" : "10.0.0.0/24" },
"Subnet3" : { "CIDR" : "10.0.3.0/24" }
}
},
"Resources" : {
...省略...
"Subnet3": {
"Type": "AWS::EC2::Subnet",
"DependsOn" : "AttachGateway",
"Properties": {
"VpcId": { "Ref": "VPC" },
"AvailabilityZone": { "Fn::Select": [ "3", { "Fn::GetAZs" : { "Ref": "AWS::Region" } }] },
"CidrBlock": { "Fn::FindInMap" : [ "StackConfig", "Subnet3", "CIDR" ]}
}
},
"Subnet3RouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "Subnet3" },
"RouteTableId" : { "Ref" : "RouteTable" }
}
}
}
}
手順はさきほどと同じなので省略しますが、詳細画面に予想していたRemove
とAdd
が出ていることを確認できました。
が、期待していたAvailabilityZone
に関しての警告は出ず、「Status」はCREATE_COMPLETE
となりました。
実行してみたらどうなるでしょうか。
やはり、アップデートに失敗しました。
エラー文を見ると、AZのインデックス3なんて存在しないよ!とのことです。ごもっとも。
最後に
CloudFormationのアップデートを事前に確認できるということで非常に嬉しいアップデートでした。
これで、テンプレートを間違えて消したくないリソースを消してしまったり、リソースの置換をしてしまって大変なことになる、ということは減るかと思います。
が、設定した値が正しいかどうかは未だ確認できないようですので、簡単なdry-runの機能として捉えて、今までどおりしっかり確認したうえでアップデート作業は行ったほうが宜しいかと思います。