我正在制作一个CloudFormation模板的怪物,它使用AWS::CloudFormation::Stack
资源来生成其他嵌套堆栈。这样做的目的是经典的职责分离和管理。
总体目标是从头开始构建应用程序环境(从VPC开始到应用程序实例结束)。
到目前为止,大部分都有效。但是我参考了子网CF模板和安全组CF模板的输出,用于创建EC2实例。
它的工作原理如下:
主模板 - >构建VPC - >调用子模板来构建子网 - >调用子模板来构建安全组 - >调用子模板来构建EC2实例
我需要将子网和安全组模板的输出传递给EC2实例模板,以便可以将实例配置到架构的正确部分。 VPC ID ref和KeyPairs传递正常,但是subnetID和securitygroupID没有。
以下是调用安全组/子网模板的主模板部分:
"DevNetworkStack": {
"Type": "AWS::CloudFormation::Stack",
"DependsOn": [
"SNVPC",
"SNIGW"
],
"Properties": {
"TemplateURL": {
"Fn::FindInMap": [
"TemplateURLs",
"DevNetworkStack",
"URL"
]
},
"TimeoutInMinutes": "30",
"Parameters": {
"VPCID": {
"Ref": "SNVPC"
},
"SNIGW": {
"Ref": "SNIGW"
}
}
}
},
"DevSecurityGroupsStack": {
"Type": "AWS::CloudFormation::Stack",
"DependsOn": "DevNetworkStack",
"Properties": {
"TemplateURL": {
"Fn::FindInMap": [
"TemplateURLs",
"DevSecurityGroupsStack",
"URL"
]
},
"TimeoutInMinutes": "30",
"Parameters": {
"VPCID": {
"Ref": "SNVPC"
}
}
}
},
这些工作正常。他们创造,一切都很好。模板提供如下输出:
"Outputs": {
"DevAdminSubnetID": {
"Description": "DevAdminSubnetID",
"Value": {
"Ref": "DevAdminSubnet"
}
},
...
"Outputs": {
"DevAdminSecurityGroupID": {
"Description": "DevAdminSecurityGroupID",
"Value": {
"Ref": "DevAdminSecurityGroup"
}
},
我可以在CF控制台中看到输出。
现在,下一个模板正在尝试使用安全组ID和子网ID。但它不起作用。
主模板将下一个孩子称为:
"DevAdminStack": {
"Type": "AWS::CloudFormation::Stack",
"DependsOn": [
"DevNetworkStack",
"DevSecurityGroupsStack",
"EC2DevRoleInstanceProfile",
"S3DevUserDataBucket",
"S3DevHomeDirsDataBucket"
],
"Properties": {
"TemplateURL": {
"Fn::FindInMap": [
"TemplateURLs",
"DevAdminStack",
"URL"
]
},
"TimeoutInMinutes": "30",
"Parameters": {
"AdminKeyPair": {
"Ref": "AdminServersKeyPair"
},
"VPCID": {
"Ref": "SNVPC"
},
"DevAdminSecurityGroupID": [
{
"Fn::GetAtt": [
"DevSecurityGroupsStack",
"Outputs.DevAdminSecurityGroupID"
]
}
],
"DevAdminSubnetID": [
{
"Fn::GetAtt": [
"DevNetworkStack",
"Outputs.DevAdminSubnetID"
]
}
]
}
}
}
...并且子模板看起来像这样(为了简洁起见删除了一些部分,因为我现在只是测试)
{
"AWSTemplateFormatVersion": "2010-09-09",
"Description": "Dev-Admin",
"Mappings": {
"RegionMap": {
"DevAdminServer": {
"AMI": "ami-6fc9770e",
"InstanceType": "t2.micro"
}
}
},
"Parameters": {
"AdminKeyPair": {
"Type": "AWS::EC2::KeyPair::KeyName"
},
"VPCID": {
"Type": "AWS::EC2::VPC::Id"
},
"DevAdminSecurityGroupID": {
"Type": "AWS::EC2::SecurityGroup::Id"
},
"DevAdminSubnetID": {
"Type": "AWS::EC2::Subnet::Id"
}
},
"Resources": {
"DevAdminServer": {
"Type": "AWS::EC2::Instance",
"Metadata": {
"Comment": "Sets up administrative tools for the server",
"AWS::CloudFormation::Init": {
"config": {
"packages": {
"yum": {}
},
"files": {},
"services": {}
}
}
},
"Properties": {
"ImageId": {
"Fn::FindInMap": [
"RegionMap",
"DevAdminServer",
"AMI"
]
},
"SecurityGroupIds": [
{
"Ref": "DevAdminSecurityGroupID"
}
],
"SubnetId": {
"Ref": "DevAdminSubnetID"
},
"InstanceType": {
"Fn::FindInMap": [
"RegionMap",
"DevAdminServer",
"InstanceType"
]
},
"KeyName": {
"Ref": "AdminKeyPair"
},
"Tags": [
{
"Key": "Application",
"Value": {
"Ref": "AWS::StackId"
}
}
],
"UserData": {
"Fn::Base64": {
"Fn::Join": [
"",
[]
]
}
}
}
}
}
}
但是这个资源在创建时失败并出现错误:
属性值参数必须是具有String(或简单类型)属性的对象
我知道这是导致问题的最后两个变量(subnetID和securitygroupID),因为我删除了它们并且配置子模板工作得很好。
我做错了什么?
答案 0 :(得分:1)
DevAdminSecurityGroupID
和DevAdminSubnetID
的值在主模板中定义为JSON数组[]
,但它们应该是字符串(在Fn::GetAtt
内部函数扩展之后):
"DevAdminSecurityGroupID":
{
"Fn::GetAtt": [
"DevSecurityGroupsStack",
"Outputs.DevAdminSecurityGroupID"
]
},
"DevAdminSubnetID":
{
"Fn::GetAtt": [
"DevNetworkStack",
"Outputs.DevAdminSubnetID"
]
}