CloudFormationのネストされたスタックで環境を構築する方法
CloudFormationにおけるネストされたスタックを検証します。
CloudFormationでは、スタックをネストすることが可能です。
ネストされたスタックは、他のスタックの一部として作成されたスタックです。ネストされたスタックは、AWS::CloudFormation::Stack リソースを使用して別のスタック内に作成します。
ネストされたスタックの操作
今回はネストされたスタックを使って、簡単な環境を構築してみて、動作を確認します。
構築する環境
上記の構成を以下の4つのスタックに分割して構築します。
- ルートスタック:配下の3スタックを生成するスタック
- VPCスタック:ルートスタックによって作成され、VPC関係のリソースを生成するスタック
- エンドポイントスタック:ルートスタックによって作成され、SSMエンドポイントを生成するスタック
- EC2スタック:ルートスタックによって作成され、EC2インスタンスを生成するスタック
今回はSSMエンドポイント経由で、プライベートサブネット内のインスタンスにアクセスすることを目的とします。
ただし本ページはネストされたスタックを確認することを目的としているため、構成自体の詳細は確認しません。本構成の詳細は以下のページをご確認ください。
環境構築用のCloudFormationテンプレートファイル
上記の構成をCloudFormationで構築します。
以下のURLにCloudFormationテンプレートを配置します。
https://github.com/awstut-an-r/awstut-fa/tree/main/013
テンプレートファイルのポイント解説
今回の環境を構成するための、各テンプレートファイルのポイントを取り上げます。
テンプレート内にネストするスタックを定義する
fa-013.yamlがルートスタック用テンプレートファイルです。
Resources:
VPCStack:
Type: AWS::CloudFormation::Stack
Properties:
TemplateURL: !Sub "https://${TemplateBucketName}.s3.${AWS::Region}.amazonaws.com/${Prefix}/${Prefix}-vpc.yaml"
Parameters:
AvailabilityZone: a
CidrIp: 10.0.1.0/24
HTTPSPort: 443
Prefix: !Ref Prefix
VPCCidrBlock: 10.0.0.0/16
Code language: YAML (yaml)
上記はVPCスタックを生成するコードです。
ネストされたスタックを定義するためには、Typeプロパティに「AWS::CloudFormation::Stack」を指定します。
TemplateURLプロパティで、作成するスタック用テンプレートファイルの設置先を指定します。テンプレートファイルはS3バケットに設置し、そのURLを指定する必要があります。
TemplateURL
Location of file containing the template body. The URL must point to a template (max size: 460,800 bytes) that’s located in an Amazon S3 bucket.
AWS::CloudFormation::Stack
Parametersプロパティを使用することで、生成するスタックに渡すパラメータを指定することができます。
ルートスタックからのパラメータをネストされたスタックで受け取る
fa-013-vpc.yamlがVPC関係のリソースを生成するネストされたスタック用テンプレートファイルです。
先ほど確認したパラメータの受け取り方法を確認します。
Parameters:
AvailabilityZone:
Type: String
CidrIp:
Type: String
HTTPSPort:
Type: Number
Prefix:
Type: String
VPCCidrBlock:
Type: String
Code language: YAML (yaml)
Parametersセクションで受け取るパラメータを記述します。
記述自体は通常のテンプレートファイルと同様ですが、これでルートスタックから渡されたパラメータを受け取ることができます。
ネストされたスタックの出力値を別スタックから参照する
続いてネストされたスタックで出力された値を、別のスタックで参照する方法を確認します。
ネストされたスタック側のテンプレートである、fa-013-vpc.yamlのOutputsセクションを確認します。
Outputs:
VPC:
Value: !Ref VPC
PrivateSubnet:
Value: !Ref PrivateSubnet
InstanceSecurityGroup:
Value: !Ref InstanceSecurityGroup
EndpointSecurityGroup:
Value: !Ref EndpointSecurityGroup
Code language: YAML (yaml)
こちらも記述自体は通常のテンプレートファイルと同様です。
論理IDと、Valueプロパティで値を定義します。
続いてルートスタック側であるfa-013.yamlを確認します。
Resources:
EndpointStack:
Type: AWS::CloudFormation::Stack
DependsOn:
- VPCStack
Properties:
TemplateURL: !Sub "https://${TemplateBucketName}.s3.${AWS::Region}.amazonaws.com/${Prefix}/${Prefix}-endpoint.yaml"
Parameters:
EndpointSecurityGroup: !GetAtt VPCStack.Outputs.EndpointSecurityGroup
Prefix: !Ref Prefix
PrivateSubnet: !GetAtt VPCStack.Outputs.PrivateSubnet
VPC: !GetAtt VPCStack.Outputs.VPC
Code language: YAML (yaml)
エンドポイントスタックを生成するためのコードです。
Parametersプロパティ内で、組み込み関数Fn ::GetAttを使用して、VPCスタック内の変数を参照することができます。今回は3つの値(EndpointSecurityGroup、PrivateSubnetおよびVPC)を参照します。
環境構築
本環境を構築し、実際の挙動を確認します。
AWS CLIを使用してCloudFormationスタックを作成する
ネストされたスタックの構築は、以下の手順で実施します。
- テンプレートファイルをS3バケットに設置する
- ルートスタックを作成する
まずテンプレートファイルをS3バケットに設置します。今回、ファイルを設置するバケットを「awstut-bucket」とし、さらに同バケット内のフォルダ名「fa-013」に配置することとします。
AWS CLIを使って今回の4ファイルを設置する場合、以下のコマンドを実行します。
$ aws s3 cp . s3://awstut-bucket/fa-013/ \
--recursive
upload: ./fa-013-ec2.yaml to s3://awstut-bucket/fa-013/fa-013-ec2.yaml
upload: ./fa-013-vpc.yaml to s3://awstut-bucket/fa-013/fa-013-vpc.yaml
upload: ./fa-013-endpoint.yaml to s3://awstut-bucket/fa-013/fa-013-endpoint.yaml
upload: ./fa-013.yaml to s3://awstut-bucket/fa-013/fa-013.yaml
Code language: Bash (bash)
recursiveオプションを使用することで、カレントディレクトリにあるファイルを、S3バケットに再帰的にコピーします。
次にルートスタックを作成します。ルートスタックの作成もAWS CLIを使って実行します。
$ aws cloudformation create-stack \
--stack-name fa-013 \
--template-url https://awstut-bucket.s3.ap-northeast-1.amazonaws.com/fa-013/fa-013.yaml \
--capabilities CAPABILITY_IAM
Code language: Bash (bash)
template-urlにルートスタックの設置先を指定します。先ほどファイルをアップロードしたS3バケットのURLを指定します。
作成されたスタックのリソースを確認する
作成されたCloudFormationスタック内のリソースを確認します。
まずルートスタックから作成されたリソースを確認します。
$ aws cloudformation list-stack-resources \
--stack-name fa-013
{
"StackResourceSummaries": [
{
"LogicalResourceId": "EC2Stack",
"PhysicalResourceId": "arn:aws:cloudformation:ap-northeast-1:[account-id]:stack/fa-013-EC2Stack-1SYPX7XNEXH5F/29310a50-6fbb-11ec-80e3-0e9006c2c991",
"ResourceType": "AWS::CloudFormation::Stack"
},
{
"LogicalResourceId": "EndpointStack",
"PhysicalResourceId": "arn:aws:cloudformation:ap-northeast-1:[account-id]:stack/fa-013-EndpointStack-HOAJG8XBN9R2/b9ce2da0-6fba-11ec-bdd0-0a8ae6b81257",
"ResourceType": "AWS::CloudFormation::Stack"
},
{
"LogicalResourceId": "VPCStack",
"PhysicalResourceId": "arn:aws:cloudformation:ap-northeast-1:[account-id]:stack/fa-013-VPCStack-1B2QC016MS825/9b9b01f0-6fba-11ec-8073-062bdbc94911",
"ResourceType": "AWS::CloudFormation::Stack" }
}
]
}
Code language: Bash (bash)
AWS Management Consoleでも、スタックの作成状況を確認します。
正常に3つのリソースが作成されていることが確認できます。ResourceTypeから、いずれもネストされたスタックであることがわかります。
ネストされたスタック内で生成されたリソースは、個別に各スタックを確認する必要があります。各スタックの名前はPhysicalResourceIdを参照します。
$ aws cloudformation list-stack-resources \
--stack-name fa-013-VPCStack-1B2QC016MS825
$ aws cloudformation list-stack-resources \
--stack-name fa-013-EndpointStack-HOAJG8XBN9R2
$ aws cloudformation list-stack-resources \
--stack-name fa-013-EC2Stack-1SYPX7XNEXH5F
Code language: Bash (bash)
AWS Management Consoleでも、EC2スタックの作成状況を確認します。
確かにネストされたスタック内にリソースが作成されていることがわかります。
各スタックのリソースを確認した結果、今回作成された主要リソースの情報は以下の通りです。
- インスタンスのID:i-030d6957bdb1cf7a7
動作確認
最後にネストされたスタックで構築された環境にアクセスします。
$ aws ssm start-session \
--target i-030d6957bdb1cf7a7
Starting session with SessionId: root-09c10692724f80cab
sh-4.2$
Code language: Bash (bash)
SSMエンドポイント経由で、プライベートサブネット内に配置されたインスタンスにアクセスすることができました。
このようにネストされたスタックでも、1つのテンプレートにまとめて記載した場合、またはAWSManagement ConsoleでGUIから作成した場合と同様に、環境を構築することができました。
まとめ
CloudFormationで、ネストされたスタックを使って環境を構築する方法を確認しました。