AWS Cloudformation – Cross Stack 学习总结

上一篇学习了 Nested Stack,现在看看别的一种方法来调用其他的stack。假设在一个大公司里边,有不同的部分,假如要装备一系列的服务,咱们需求装备一个很大的template 文件,可是咱们能够经过 cross stack的方法,把一个大的template分割为许多小的template,然后在对应的当地export/import 对应的值就好了。

下面经过一个实例来阐明,创立两个stack,第一个创立咱们的VPC,路由表,Internet网关,安全组等等;第二个stack会调用第一个stack的成果,然后在这个基础上创立一个新的web server

模板文件能够在这个链接下载
https://github.com/natonic/CloudFormation-Deep-Dive/tree/master/Labs/CrossStack

下面是咱们的第一个template 文件


{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Sample Template VPC_with_PublicIPs_And_DNS: Sample template that creates a VPC with DNS and public IPs enabled. Note that you are billed for the AWS resources that you use when you create a stack from this template.",
"Resources" : {
"VPC" : {
"Type" : "AWS::EC2::VPC",
"Properties" : {
"EnableDnsSupport" : "true",
"EnableDnsHostnames" : "true",
"CidrBlock" : "10.0.0.0/16"
}
},
"PublicSubnet" : {
"Type" : "AWS::EC2::Subnet",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"CidrBlock" : "10.0.0.0/24"
}
},
"InternetGateway" : {
"Type" : "AWS::EC2::InternetGateway"
},
"VPCGatewayAttachment" : {
"Type" : "AWS::EC2::VPCGatewayAttachment",
"Properties" : {
"VpcId" : { "Ref" : "VPC" },
"InternetGatewayId" : { "Ref" : "InternetGateway" }
}
},
"PublicRouteTable" : {
"Type" : "AWS::EC2::RouteTable",
"Properties" : {
"VpcId" : { "Ref" : "VPC" }
}
},
"PublicRoute" : {
"Type" : "AWS::EC2::Route",
"DependsOn" : "VPCGatewayAttachment",
"Properties" : {
"RouteTableId" : { "Ref" : "PublicRouteTable" },
"DestinationCidrBlock" : "0.0.0.0/0",
"GatewayId" : { "Ref" : "InternetGateway" }
}
},
"PublicSubnetRouteTableAssociation" : {
"Type" : "AWS::EC2::SubnetRouteTableAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet" },
"RouteTableId" : { "Ref" : "PublicRouteTable" }
}
},
"PublicSubnetNetworkAclAssociation" : {
"Type" : "AWS::EC2::SubnetNetworkAclAssociation",
"Properties" : {
"SubnetId" : { "Ref" : "PublicSubnet" },
"NetworkAclId" : { "Fn::GetAtt" : ["VPC", "DefaultNetworkAcl"] }
}
},
"WebServerSecurityGroup" : {
"Type" : "AWS::EC2::SecurityGroup",
"Properties" : {
"GroupDescription" : "Enable HTTP ingress",
"VpcId" : { "Ref" : "VPC" },
"SecurityGroupIngress" : [ {
"IpProtocol" : "tcp",
"FromPort" : "80",
"ToPort" : "80",
"CidrIp" : "0.0.0.0/0"},
{
"CidrIp": "0.0.0.0/0",
"FromPort": 443,
"IpProtocol": "tcp",
"ToPort": 443
},
{
"FromPort": 443,
"IpProtocol": "tcp",
"ToPort": 443
}
]
}
}
},
"Outputs" : {
"VPCId" : {
"Description" : "VPC ID",
"Value" :  { "Ref" : "VPC" },
"Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-VPCID" }}
},
"PublicSubnet" : {
"Description" : "The subnet ID to use for public web servers",
"Value" :  { "Ref" : "PublicSubnet" },
"Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-SubnetID" }}
},
"WebServerSecurityGroup" : {
"Description" : "The security group ID to use for public web servers",
"Value" :  { "Fn::GetAtt" : ["WebServerSecurityGroup", "GroupId"] },
"Export" : { "Name" : {"Fn::Sub": "${AWS::StackName}-SecurityGroupID" }}
}
}
}

下面是第二个template 文件

{
"AWSTemplateFormatVersion" : "2010-09-09",
"Description" : "AWS CloudFormation Cross-Stack Reference Sample Template: Demonstrates how to reference resources from a different stack. This template provisions an EC2 instance in an EC2 Security Group provisioned in a different stack. **WARNING** This template creates an Amazon EC2 instance. You will be billed for the AWS resources used if you create a stack from this template.",
"Parameters": {
"NetworkStackName": {
"Description": "Name of an active CloudFormation stack that contains the networking resources, such as the subnet and security group, that will be used in this stack.",
"Type": "String",
"MinLength" : 1,
"MaxLength" : 255,
"AllowedPattern" : "^[a-zA-Z][-a-zA-Z0-9]*$",
"Default" : "SampleNetworkCrossStack"
}
},
"Mappings" : {
"AWSRegionArch2AMI" : {
"us-east-1"        : {"PV64" : "ami-8ff710e2", "HVM64" : "ami-f5f41398", "HVMG2" : "ami-4afd1d27"},
"us-west-2"        : {"PV64" : "ami-eff1028f", "HVM64" : "ami-d0f506b0", "HVMG2" : "ami-ee897b8e"},
"us-west-1"        : {"PV64" : "ami-ac85fbcc", "HVM64" : "ami-6e84fa0e", "HVMG2" : "ami-69106909"},
"eu-west-1"        : {"PV64" : "ami-23ab2250", "HVM64" : "ami-b0ac25c3", "HVMG2" : "ami-936de5e0"},
"eu-central-1"     : {"PV64" : "ami-27c12348", "HVM64" : "ami-d3c022bc", "HVMG2" : "ami-8e7092e1"},
"ap-northeast-1"   : {"PV64" : "ami-26160d48", "HVM64" : "ami-29160d47", "HVMG2" : "ami-91809aff"},
"ap-northeast-2"   : {"PV64" : "NOT_SUPPORTED", "HVM64" : "ami-cf32faa1", "HVMG2" : "NOT_SUPPORTED"},
"ap-southeast-1"   : {"PV64" : "ami-f3dd0a90", "HVM64" : "ami-1ddc0b7e", "HVMG2" : "ami-3c30e75f"},
"ap-southeast-2"   : {"PV64" : "ami-8f94b9ec", "HVM64" : "ami-0c95b86f", "HVMG2" : "ami-543d1137"},
"sa-east-1"        : {"PV64" : "ami-e188018d", "HVM64" : "ami-fb890097", "HVMG2" : "NOT_SUPPORTED"},
"cn-north-1"       : {"PV64" : "ami-77a46e1a", "HVM64" : "ami-05a66c68", "HVMG2" : "NOT_SUPPORTED"}
}
},
"Resources" : {
"WebServerInstance": {
"Type": "AWS::EC2::Instance",
"Metadata" : {
"AWS::CloudFormation::Init" : {
"configSets" : {
"All" : [ "ConfigureSampleApp" ]
},
"ConfigureSampleApp" : {
"packages" : {
"yum" : {
"httpd" : []
}
},
"files" : {
"/var/www/html/index.html" : {
"content" : { "Fn::Join" : ["n", [
"<img src="https://s3.amazonaws.com/cloudformation-examples/cloudformation_graphic.png" alt="AWS Cloudformation - Cross Stack 学习总结" alt="AWS CloudFormation Logo"/>",
"<h1>Congratulations, you have successfully launched the AWS CloudFormation sample.</h1>"
]]},
"mode"    : "000644",
"owner"   : "root",
"group"   : "root"
}
},
"services" : {
"sysvinit" : {
"httpd"    : { "enabled" : "true", "ensureRunning" : "true" }
}
}
}
}
},
"Properties": {
"InstanceType"   : "t2.micro",
"ImageId": { "Fn::FindInMap": [ "AWSRegionArch2AMI", { "Ref": "AWS::Region" } , "HVM64" ] },
"NetworkInterfaces" : [{
"GroupSet"                 : [{ "Fn::ImportValue" :  {"Fn::Sub": "${NetworkStackName}-SecurityGroupID" } }],
"AssociatePublicIpAddress" : "true",
"DeviceIndex"              : "0",
"DeleteOnTermination"      : "true",
"SubnetId"                 : { "Fn::ImportValue" : {"Fn::Sub": "${NetworkStackName}-SubnetID" } }
}],
"UserData"       : { "Fn::Base64" : { "Fn::Join" : ["", [
"#!/bin/bash -xen",
"yum update -y aws-cfn-bootstrapn",
"# Install the files and packages from the metadatan",
"/opt/aws/bin/cfn-init -v ",
"         --stack ", { "Ref" : "AWS::StackName" },
"         --resource WebServerInstance ",
"         --configsets All ",
"         --region ", { "Ref" : "AWS::Region" }, "n",
"# Signal the status from cfn-initn",
"/opt/aws/bin/cfn-signal -e $? ",
"         --stack ", { "Ref" : "AWS::StackName" },
"         --resource WebServerInstance ",
"         --region ", { "Ref" : "AWS::Region" }, "n"
]]}}
},
"CreationPolicy" : {
"ResourceSignal" : {
"Timeout" : "PT5M"
}
}
}
},
"Outputs" : {
"URL" : {
"Description" : "URL of the sample website",
"Value" :  { "Fn::Join" : [ "", [ "http://", { "Fn::GetAtt" : [ "WebServerInstance", "PublicDnsName" ]}]]}
}
}
}

首要创立第一个stack

AWS Cloudformation - Cross Stack 学习总结

给一个姓名叫networkstack

AWS Cloudformation - Cross Stack 学习总结

创立成功

AWS Cloudformation - Cross Stack 学习总结

咱们创立了以下的资源

AWS Cloudformation - Cross Stack 学习总结

看看他的output

AWS Cloudformation - Cross Stack 学习总结

看看他的export
AWS Cloudformation - Cross Stack 学习总结

接下来创立第二个stack

AWS Cloudformation - Cross Stack 学习总结

他的参数指向第一个stack的姓名,这是为了import 数据

AWS Cloudformation - Cross Stack 学习总结

创立成功
AWS Cloudformation - Cross Stack 学习总结

看看output的URL

AWS Cloudformation - Cross Stack 学习总结

能够成功翻开这个测验网页

AWS Cloudformation - Cross Stack 学习总结

最终,再试试删去咱们的networkstack
AWS Cloudformation - Cross Stack 学习总结

删去失利,这是由于存在依靠联系,appstack需求import来自networkstack的vpc,sg等数据
AWS Cloudformation - Cross Stack 学习总结

假如咱们先删去appstack,然后再删去network stack,那就没有问题了

整个流程便是如上所示。最终再次着重一下要害点:

咱们在networkstack 的Output 进行export,这儿经过全局变量替换掉stackname
AWS Cloudformation - Cross Stack 学习总结

相同的,咱们在appstack 的 resource 部分 import 对应的值
AWS Cloudformation - Cross Stack 学习总结