はじめに
その8ではスタックをネスト構成
にしてテンプレートを分割しましたが、今回はクロススタックリファレンス
で前回と同じようにテンプレートを分割してみようと思います。
- 【前】CloudFormationをゼロから勉強する。(その8:スタックのネスト)
- 【次】CloudFormationをゼロから勉強する。(その10:ファイル呼び出し方法使い分け)
- 【番外編】CloudFormationをゼロから勉強する。(番外編:Former2)
クロススタックリファレンスとは
クロススタックリファレンス
も前回のネスト
同様、テンプレートを分割する方法の1つとなりますが、クロススタックリファレンス
は他のテンプレートで使用する変数だけを共有させるようにする方法となります。
クロススタックリファレンスの書式
書式としては単純で、値を参照させる側のテンプレートのOutputs
セクションで参照させたい値・変数をExport
で指定して、参照する側はImportValue
関数で他テンプレートでExport
している値・変数を読み込むだけです。簡単ですね!
Outputs:
EC2VPC1:
Value: !Ref EC2VPC1
Export:
Name: CrossStackVpcId
Resources:
EC2Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !ImportValue CrossStackVpcId
クロススタックリファレンス
は、前回のネスト構成
のように、親となるスタックを実行すれば、テンプレート内で定義されている子スタックがまとめて作成されるようなものではないため、展開する際は個々に実行する必要があります。
今回作成する構成
前回のテンプレートを手直しして以下のような構成を作ってみようと思います。
今回は親、子関係ないので、パラメータ入力・子テンプレート管理用のテンプレート(前回で言うと「cf.yaml」)は作成しません。
テンプレート、パラメータファイルの格納場所
今回は以下のファイル・ディレクトリ構成としようと思います。。
内容 | VPCのパラメータ | SUbnet1のパラメータ | Subnet2のパラメータ | EC2のパラメータ |
---|---|---|---|---|
スタック名 | cross-stack-vpc | cross-stack-subnet1 | cross-stack-subnet2 | cross-stack-ec2 |
テンプレートファイルのパス | /home/ec2-user/vpc.yaml | /home/ec2-user/subnet1.yaml | /home/ec2-user/subnet2.yaml | /home/ec2-user/ec2.yaml |
パラメータファイルのパス | /home/ec2-user/param1.json | /home/ec2-user/param2.json | /home/ec2-user/param3.json | - |
VPCスタック用テンプレートの作成
VPC
のレンジを入力で受け取って、VPCID
をExport
で出力して他テンプレートから使用できるようにします。
テンプレートは個々に実行するため、入力用jsonファイルも作ります。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
VPCRange:
Type: String
Resources:
EC2VPC1:
Type: 'AWS::EC2::VPC'
Properties:
CidrBlock: !Ref VPCRange
Tags:
- Key: "Name"
Value: "cf_VPC1"
Outputs:
EC2VPC1:
Value: !Ref EC2VPC1
Export:
Name: CrossStackVpcId
[
{ "ParameterKey" : "VPCRange", "ParameterValue" : "172.24.0.0/16" }
]
Subnet1スタック用テンプレートの作成
Subnet1
用のレンジを入力で受け取って、SubnetID
をExport
で出力して他テンプレートから使用できるようにします。
サブネット作成で必要なVPCID
はImportValue
関数で先ほどVPC作成でExport
した名前を指定して取得します。
また、上記VPC
と同様、入力用jsonファイルも作ります。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetRange1:
Type: String
Resources:
EC2Subnet1:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !ImportValue CrossStackVpcId
CidrBlock: !Ref SubnetRange1
Tags:
- Key: "Name"
Value: "cf_Subnet1"
Outputs:
EC2Subnet1:
Value: !Ref EC2Subnet1
Export:
Name: CrossStackSubnet1Id
[
{ "ParameterKey" : "SubnetRange1", "ParameterValue" : "172.24.0.0/24" }
]
Subnet2スタック用テンプレートの作成
パラメータ名の違いだけでSubnet1
と同じなので説明割愛。
AWSTemplateFormatVersion: 2010-09-09
Parameters:
SubnetRange2:
Type: String
Resources:
EC2Subnet2:
Type: 'AWS::EC2::Subnet'
Properties:
VpcId: !ImportValue CrossStackVpcId
CidrBlock: !Ref SubnetRange2
Tags:
- Key: "Name"
Value: "cf_Subnet2"
Outputs:
EC2Subnet2:
Value: !Ref EC2Subnet2
Export:
Name: CrossStackSubnet2Id
[
{ "ParameterKey" : "SubnetRange2", "ParameterValue" : "172.24.1.0/24" }
]
EC2スタック用テンプレートの作成
ImportValue
関数でSubnet1のIDを取得します。
AWSTemplateFormatVersion: 2010-09-09
Resources:
EC2Instance:
Type: 'AWS::EC2::Instance'
Properties:
ImageId: ami-0cc75a8978fbbc969
InstanceType: t2.micro
KeyName: staging_key
NetworkInterfaces:
- AssociatePublicIpAddress: "true"
SubnetId: !ImportValue CrossStackSubnet1Id
DeviceIndex: 0
Tags:
- Key: "Name"
Value: "cf_EC2"
スタックの作成
作成したテンプレートをいつも通り実行してスタックを作成すれば完成です。
但し、今回の場合、Export
値を参照するので、Export
対象のスタックが先に完成していなければ、値が引けずに失敗します。
そのため、一斉にcreate-stack
で実行するのではなく、スタック作成の成功を待ってから順に作成するようにしましょう。
aws cloudformation create-stack --template-body file:///home/ec2-user/vpc.yaml --stack-name cross-stack-vpc --parameters file:///home/ec2-user/param1.json
aws cloudformation create-stack --template-body file:///home/ec2-user/subnet1.yaml --stack-name cross-stack-subnet1 --parameters file:///home/ec2-user/param2.json
aws cloudformation create-stack --template-body file:///home/ec2-user/subnet2.yaml --stack-name cross-stack-subnet2 --parameters file:///home/ec2-user/param3.json
aws cloudformation create-stack --template-body file:///home/ec2-user/ec2.yaml --stack-name cross-stack-ec2
削除について
ネスト
構成の時と異なり、個々にスタック作成しているので、削除する場合も個々に削除する必要があります。
但し、Exportしている値は依存関係があるため、もし他のスタックでExportしている値を使用していた場合は削除できません。
例えば、「vpc.yaml」を削除しようとすると「Export CrossStackVpcId cannot be deleted as it is in use by cross-stack-subnet1 and cross-stack-subnet2」といった理由により削除ができません。
aws cloudformation delete-stack --stack-name cross-stack-vpc
aws cloudformation describe-stacks --stack-name cross-stack-vpc
{
"Stacks": [
{
"StackId": "arn:aws:cloudformation:ap-northeast-1:xxxxxxxxxxxx:stack/cross-stack-vpc/xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx",
"EnableTerminationProtection": false,
"DriftInformation": {
"StackDriftStatus": "NOT_CHECKED"
},
"Parameters": [
{
"ParameterValue": "172.24.0.0/16",
"ParameterKey": "VPCRange"
}
],
"Tags": [],
"Outputs": [
{
"ExportName": "CrossStackVpcId",
"OutputKey": "EC2VPC1",
"OutputValue": "vpc-xxxxxxxxxxxxxxxxx"
}
],
"StackStatusReason": "Export CrossStackVpcId cannot be deleted as it is in use by cross-stack-subnet1 and cross-stack-subnet2",
"CreationTime": "YYYY-MM-DDThh:mm:ss.xxxZ",
"StackName": "cross-stack-vpc",
"NotificationARNs": [],
"StackStatus": "CREATE_COMPLETE",
"DisableRollback": false,
"RollbackConfiguration": {}
}
]
}
もし全てを削除したい場合は、以下の順番で削除するようにしましょう。
aws cloudformation delete-stack --stack-name cross-stack-ec2
aws cloudformation delete-stack --stack-name cross-stack-subnet2
aws cloudformation delete-stack --stack-name cross-stack-subnet1
aws cloudformation delete-stack --stack-name cross-stack-vpc
おわりに
今回のクロススタックリファレンス
は前回のネスト
によるテンプレート呼び出しと比較し、簡単に値の共有ができると感じました。
ネスト
は多段構成になると、各スタックごとの繋がりを意識して作成する必要がありましたが、クロススタックリファレンス
ではスタックは個々に分離されているので、連携するテンプレート数が多くなっても書式があまり変わらずに書けるのは良いですね。
次回は今までやってきたTransform
、ネスト
、クロススタックリファレンス
の使い分けについて私なりに考察してみようと思います。