У меня есть сервис с тремя слоями, каждый из которых имеет группу автоматического масштабирования с некоторыми экземплярами. Слои различаются (конфигурацией запуска, количеством экземпляров и т. д.) способом, который контролируется одним параметром («роль»). Таким образом, я вызываю шаблон с параметром следующим образом:
{
...
"Parameters": {
...
"Role": {
"AllowedValues": [
"inbound",
"filter",
"outbound"
],
...
},
},
"Conditions" : {
"IsStaging" : { "Fn::Equals" : [ { "Ref": "Environment" }, "eu-staging"] },
"IsInbound" : { "Fn::Equals" : [ { "Ref": "Role" }, "inbound"] },
"IsFilter" : { "Fn::Equals" : [ { "Ref": "Role" }, "filter"] },
"IsOutbound" : { "Fn::Equals" : [ { "Ref": "Role" }, "outbound"] }
},
"Resources": {
...
"SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
...
"SecurityGroupEgress": [
{"Fn::If": ["IsFilter", { "CidrIp": "10.243.74.0/24", "IpProtocol": "tcp", "FromPort": "9094", "ToPort": "9094" }, { "Ref": "AWS::NoValue" } ]}
],
"Tags": [
{
"Key": "Name",
"Value": { "Fn::Join" : [ "-", [ "smtp-service-security-group", {"Ref": "Role"} ] ] }
},
...
],
}
},
}
}
Теперь я хотел бы объявить эти три уровня в одном и том же шаблоне CloudFormation (чтобы он прозрачно интегрировался с существующим заданием конвейера и извлекал выгоду из функций CloudFormation, например отката). Кроме того, я хотел бы избежать трехкратного переписывания ресурсов, по одному разу для каждого слоя, следующим образом:
{
...
"Parameters": {
...
"Role": {
"AllowedValues": [
"inbound",
"filter",
"outbound"
],
...
},
},
"Conditions" : {
"IsStaging" : { "Fn::Equals" : [ { "Ref": "Environment" }, "eu-staging"] },
"IsInbound" : { "Fn::Equals" : [ { "Ref": "Role" }, "inbound"] },
"IsFilter" : { "Fn::Equals" : [ { "Ref": "Role" }, "filter"] },
"IsOutbound" : { "Fn::Equals" : [ { "Ref": "Role" }, "outbound"] }
},
"Resources": {
...
"SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
...
"SecurityGroupEgress": [
{"Fn::If": ["IsInbound", { "CidrIp": "10.243.74.0/24", "IpProtocol": "tcp", "FromPort": "9094", "ToPort": "9094" }, { "Ref": "AWS::NoValue" } ]}
],
"Tags": [
{
"Key": "Name",
"Value": { "Fn::Join" : [ "-", [ "smtp-service-security-group", {"Ref": "Role"} ] ] }
},
...
],
}
},
...
"SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
...
"SecurityGroupEgress": [
{"Fn::If": ["IsFilter", { "CidrIp": "10.243.74.0/24", "IpProtocol": "tcp", "FromPort": "9094", "ToPort": "9094" }, { "Ref": "AWS::NoValue" } ]}
],
"Tags": [
{
"Key": "Name",
"Value": { "Fn::Join" : [ "-", [ "smtp-service-security-group", {"Ref": "Role"} ] ] }
},
...
],
}
},
...
"SecurityGroup": {
"Type": "AWS::EC2::SecurityGroup",
"Properties": {
...
"SecurityGroupEgress": [
{"Fn::If": ["IsOutbound", { "CidrIp": "10.243.74.0/24", "IpProtocol": "tcp", "FromPort": "9094", "ToPort": "9094" }, { "Ref": "AWS::NoValue" } ]}
],
"Tags": [
{
"Key": "Name",
"Value": { "Fn::Join" : [ "-", [ "smtp-service-security-group", {"Ref": "Role"} ] ] }
},
...
],
}
},
}
}
Как я могу сделать это таким образом, чтобы мне не пришлось переписывать один и тот же код для трех слоев?
@Marcin спасибо за отзыв. Я отредактировал вопрос, и, надеюсь, теперь он более ясен.
Вы не можете сделать это без Макросы CloudFormation (CFN), если хотите использовать только один шаблон.
Обычный способ борьбы с повторением — использование вложенные стеки. Для этого вам потребуется поместить общий код для трех служб в отдельный шаблон, а затем включить их трижды в родительский шаблон с их конкретными параметрами.
благодарю вас. Я исследую этот подход.
К сожалению, ваш вопрос не содержит деталей и неясен. Возможно, если бы вы предоставили настоящие шаблоны, было бы легче понять, что вы хотите сделать.