#templates #amazon-web-services #amazon-cloudformation
#шаблоны #amazon-веб-сервисы #aws-cloudformation
Вопрос:
Я создаю чудовищный шаблон CloudFormation, который использует AWS::CloudFormation::Stack
ресурс для создания других вложенных стеков. Целью этого является классическое разделение обязанностей и управления.
Общая цель состоит в том, чтобы создать среду приложения с нуля (начиная с VPC и заканчивая экземплярами приложений).
Пока что большая часть этого работает. Но я столкнулся с проблемой, связанной со ссылками на выходные данные шаблона CF подсети и шаблона CF securitygroup для использования при создании экземпляров EC2.
Это работает следующим образом:
Главный шаблон -> Создает VPC -> Вызывает дочерний шаблон для создания подсетей -> Вызывает дочерний шаблон для создания групп безопасности -> Вызывает дочерний шаблон для создания экземпляров EC2
Мне нужно передать выходные данные из шаблонов подсети и группы безопасности в шаблон экземпляра EC2, чтобы экземпляры могли быть подготовлены в правильной части архитектуры. Ссылка на идентификатор VPC и пары ключей передаются нормально, но идентификатор подсети и 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.
Теперь следующий шаблон пытается использовать идентификатор группы безопасности и идентификатор подсети. Но это не работает.
Главный шаблон вызывает следующий дочерний шаблон как:
"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), потому что я удалил их, и подготовка дочернего шаблона работает просто отлично.
Что я делаю не так?
Ответ №1:
Значения DevAdminSecurityGroupID
и DevAdminSubnetID
определены как массивы JSON []
в вашем главном шаблоне, но они должны быть строками (после Fn::GetAtt
расширения встроенной функции):
"DevAdminSecurityGroupID":
{
"Fn::GetAtt": [
"DevSecurityGroupsStack",
"Outputs.DevAdminSecurityGroupID"
]
},
"DevAdminSubnetID":
{
"Fn::GetAtt": [
"DevNetworkStack",
"Outputs.DevAdminSubnetID"
]
}