CloudFormationテンプレート間でリソースIDなどを渡す方法について紹介します。
簡単のため、2つのテンプレートで以下を実施する例で示します。
- VPCを作りVpcIdを渡す
- 渡されたVpcId内にSubnetを作る
1. AWS::CloudFormation::Stack を使って !GetAtt *.Outputs.* で受け取る
親となるテンプレート(base.yml)を用意して、2つのテンプレートを呼び出す形になります。
値を渡すテンプレート(vpc.yaml)ではOutputsに値を出力し、
親テンプレートのParametersで!GetAtt
ResourceName.Outputs.
_OutputName_を使って渡します。
受け取るテンプレート(subnet.yaml)はParametersにパラメータを用意しておきます。
なお、vpc.yaml, subnet.yamlは事前にS3にアップしておき、base.yamlのみをCloudFormationで作成します。
(2, 3の方法はvpc.yaml, subnet.yamlをCFで作成します。)
AWSTemplateFormatVersion: '2010-09-09'
Resources:
VPC:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/***/vpc.yaml
Subnet:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: https://s3.amazonaws.com/***/subnet.yaml
Parameters:
VpcId: !GetAtt VPC.Outputs.VpcId # !GetAtt で受け渡す
AWSTemplateFormatVersion: '2010-09-09'
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.250.250.0/24
Outputs:
VpcId: # 渡す値を出力する
Value: !Ref VPC
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
VpcId: # 受け取る値を定義する
Type: AWS::EC2::VPC::Id
Resources:
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VpcId
CidrBlock: 10.250.250.0/28
参考: https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-stack.html
テンプレートを更新する場合は、S3にアップ、親テンプレートの更新、という流れになります。
この方法はここで使われています。
https://github.com/awslabs/ecs-refarch-continuous-deployment/blob/master/ecs-refarch-continuous-deployment.yaml
2. ImportValueを使う(cross reference)
値を渡すテンプレート(vpc.yaml)ではOutputsにExport属性付きで値を出力し、
受け取るテンプレート(subnet.yaml)は!ImportValue
で取得します。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.250.251.0/24
Outputs:
VpcId:
Value: !Ref VPC
Export: # 渡す値をExportで出力する
Name: VpcId
AWSTemplateFormatVersion: '2010-09-09'
Resources:
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !ImportValue VpcId
CidrBlock: 10.250.251.0/28
参考:
https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/walkthrough-crossstackref.html
この方法の注意点として、テンプレートを更新してExportする値が変わるような場合、更新する前にImportValueしたリソースを必ず削除する必要があります。
3. Parameter Storeを使う
値を渡すテンプレート(vpc.yaml)ではParamter Storeに値を保存し、
受け取るテンプレート(subnet.yaml)はParametersで取得します。
このとき、TypeはAWS::SSM::Parameter::Value、Value(テンプレート上はDefault)はParameter StoreのNameになります。
AWSTemplateFormatVersion: '2010-09-09'
Resources:
VPC:
Type: AWS::EC2::VPC
Properties:
CidrBlock: 10.250.252.0/24
SSMVpcId: # 渡す値をParameter Storeに保存する
Type: AWS::SSM::Parameter
Properties:
Name: /cf-values/VpcId
Type: String
Value: !Ref 'VPC'
AWSTemplateFormatVersion: '2010-09-09'
Parameters:
VpcId: # 受け取る値を定義する
Type: AWS::SSM::Parameter::Value<AWS::EC2::VPC::Id>
Default: /cf-values/VpcId # Parameter StoreのNameを指定
Resources:
Subnet:
Type: AWS::EC2::Subnet
Properties:
VpcId: !Ref VpcId
CidrBlock: 10.250.252.0/28
記述は多くなりますが、Parameter Storeをこのように使うこともできます。
まとめ
個人的な希望は、2の方法でExportする値を更新するとImportValueしたリソースも自動で更新するようになるとありがたいのですが。
是非、3の方法もお試しください。