CloudFormation のテンプレートを分割した際のスタック作成・管理方法には Cross Stack Reference と Nested Stack の2通りあります。 そのうちの Nested Stack は 以前の記事 で紹介しました。 今回は Cross Stack Reference の紹介です。
Cross Stack Reference とは
Cross Stack Reference を用いると、スタック作成時に必要な情報を他の既存スタックから取得することができます。
実際に Cross Stack Reference を用いて CloudFormation テンプレートからスタックを作成してみましょう。
テンプレート
VPC, Subnet リソースを作成するテンプレートを用います。
vpc.yml
AWSTemplateFormatVersion: "2010-09-09" Resources: VPC: Type: AWS::EC2::VPC Properties: EnableDnsSupport: true EnableDnsHostnames: true CidrBlock: 10.0.0.0/16 Outputs: VPCId: Description: VPC ID Value: !Ref VPC Export: Name: !Sub ${AWS::StackName}-VPCID
subnet.yml
AWSTemplateFormatVersion: "2010-09-09" Parameters: VPCStackName: Type: String Default: VPCCrossStackName Resources: PublicSubnet: Type: AWS::EC2::Subnet Properties: VpcId: !ImportValue Fn::Sub: ${VPCStackName}-VPCID CidrBlock: 10.0.0.0/24
便宜上 vpc.yml
, subnet.yml
をそれぞれ親テンプレート、子テンプレート、
同様にそれらのテンプレートを用いて作成されたスタックもそれぞれ親スタック、子スタックと呼ぶことにします。
これらのテンプレートでは
- 親テンプレート:
Outputs.Export.Name
で参照名を指定 - 子テンプレート:
Parameters
でスタック名を渡し、Fn::ImportValue
関数を用いてスタック名-VPCID
で VPC ID を取得
としています。 ここでは子テンプレートのパラメタにスタック名を指定していますが、 親テンプレートでの出力値で指定した参照名を子テンプレートでそのまま用いても構いません。
スタック作成
実際に Cross Stack Reference を用いたスタックを作成してみましょう。
. ├── subnet.yml └── vpc.yml
先と同じこれらのテンプレートを使います。
まずは親テンプレートから cross-stack-reference-vpc
という名前のスタックを作成します。
$ aws cloudformation deploy --stack-name cross-stack-reference-vpc --template-file ./vpc.yml Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - cross-stack-reference-vpc
作成できました。
マネコンからも cross-stack-reference-vpc-VPCID
という出力値でエクスポートされていることが確認できました。
子テンプレートから cross-stack-reference-subnet
という名前のスタックを作成します。
$ aws cloudformation deploy --stack-name cross-stack-reference-subnet --template-file ./subnet.yml --parameter-overrides VPCStackName=cross-stack-reference-vpc Waiting for changeset to be created.. Waiting for stack create/update to complete Successfully created/updated stack - cross-stack-reference-subnet
作成できました。
スタック更新
Cross Stack Reference を用いて作成されたスタックの更新にはいくつか注意が必要になります。
リソースを削除する必要のない更新は問題ありません。
diff --git a/vpc.yml b/vpc.yml index 24f7529..87dca49 100644 --- a/vpc.yml +++ b/vpc.yml @@ -4,7 +4,7 @@ Resources: Type: AWS::EC2::VPC Properties: EnableDnsSupport: true - EnableDnsHostnames: true + EnableDnsHostnames: false CidrBlock: 10.0.0.0/16 Outputs: VPCId:
このような親テンプレートは更新できます。
しかし、親テンプレートを更新時リソースを再作成する場合は他リソースが既に依存しているためエラーになります。 子スタックも自動で更新されることはありません。
今回では親テンプレートで VPC を削除し直す必要がある場合が当てはまります。
diff --git a/vpc.yml b/vpc.yml index 24f7529..8d0402c 100644 --- a/vpc.yml +++ b/vpc.yml @@ -5,7 +5,7 @@ Resources: Properties: EnableDnsSupport: true EnableDnsHostnames: true - CidrBlock: 10.0.0.0/16 + CidrBlock: 10.0.1.0/16 Outputs: VPCId: Description: VPC ID
このように VPC CIDR を変更するには VPC の再作成が必要となり、
10.0.0.0/16
の VPC に既に依存している子リソースがあるのでエラーになります。
実際に更新してみると
Export cross-stack-reference-vpc-VPCID cannot be updated as it is in use by cross-stack-reference-subnet
という理由によりスタック更新が失敗しました。
この他にも親スタック更新が失敗する場合があるかと思われますので、しっかりと検証したほうが良いでしょう。
さいごに
今回は Cross Stack Reference を用いたスタックの作成・更新の仕方を紹介しました。
Nested Stack では子スタックの Change Set が確認できませんでしたが、Cross Stack Reference であれば可能です。 しかしデプロイは Cross Stack Reference の方が手間が掛かります。
この状況ではこっちのほうがいいと断言することはできませんが、 どこからどこまでを妥協・許容するのかによるのではないでしょうか。