天天看點

通過ROS一鍵建立滿足多可用區需求的ECS、SLB、RDS、ESS<資源編排服務>

案例需求:

在多個可用區建立多個ECS執行個體,彈性伸縮SLB、RDS、ECS資源。

資源編排介紹:

簡單介紹下:ROS 

ROS詳細介紹

阿裡雲資源編排服務(ROS)可幫助使用者簡化雲計算資源管理和自動化運維的服務。

使用者遵循ROS定義的模闆規範,編寫模闆檔案,在模闆中定義所需雲計算資源的集合及資源間的依賴關系、資源配置細節等,ROS通過編排引擎自動完成所有資源的建立和配置,以達到自動化部署、運維的目的。

涉及資源類型簡介:

ALIYUN::ECS::InstanceGroup: 用于建立一組 ECS 執行個體;

詳細介紹

ALIYUN::ECS::VSwitch:用于建立交換機;

ALIYUN::ECS::VPC:用于建立專有網絡;

ALIYUN::ESS::ScalingGroup:用于建立伸縮組;

ALIYUN::RDS::DBInstance:用于建立資料庫執行個體;

ALIYUN::SLB::LoadBalancer:用于建立負載均衡;

ALIYUN::SLB::Listener:用于建立負載均衡監聽器;

ALIYUN::SLB::BackendServerAttachment:用于添加後端伺服器;

ALIYUN::ESS::ScalingConfiguration:用于建立伸縮配置;

ALIYUN::ESS::ScalingGroupEnable:用于啟用伸縮組;

方案介紹:

相信大家熟知傳統的交換網絡,下圖采用阿裡雲VPC産品的示意圖,可以看出如果需要在多個可用區域建立資源,可采取下面的方式,建立一個VPC(專有網絡),接下來建立多個VSwitch(虛拟交換機),可以完成将多個資源部署在多個可用區域内的:

通過ROS一鍵建立滿足多可用區需求的ECS、SLB、RDS、ESS<資源編排服務>

注意:

本文代碼示例完成雙可用區建立資源棧;__關于模版代碼中的參數具體含義就不一一介紹了, 詳情請參考<涉及資源類型簡介>。

資源棧感性了解:通過ROS模版的方式建立出一個或多個資源的集合。

需求拆分

  • 建立多個虛拟交換機完成多可用區需求,此處舉例建立一個VSwitch:
"VSwitch1": {
  "Type": "ALIYUN::ECS::VSwitch",
  "DependsOn": "Vpc",
  "Properties": {
    "VSwitchName": {
      "Ref": "VSwitch1Name"
    },
    "VpcId": {
      "Ref": "Vpc"
    },
    "CidrBlock": {
      "Ref": "VSW1CidrBlock"
    },
    "Description": {
      "Ref": "VSW1Description"
    },
    "ZoneId": {
      "Ref": "VSW1ZoneId"
    }
  }
}           
  • 建立多個ECS執行個體完成多ECS執行個體建立的需求,此處舉例建立一組ECS執行個體,并将其部署與一個可用區,同樣第二個可用區也建立一組ECS執行個體:
"EcsInstanceGroup1": {
  "Type": "ALIYUN::ECS::InstanceGroup",
  "DependsOn": "VSwitch1",
  "Properties": {
    "IoOptimized": "optimized",
    "ImageId": {
      "Ref": "EcsGroupImageId"
    },
    "SecurityGroupId": {
      "Ref": "SG"
    },
    "Password": {
      "Ref": "EcsPassword"
    },
    "MinAmount": {
      "Ref": "EcsGroup1MaxAmount"
    },
    "AllocatePublicIP": "false",
    "SystemDiskCategory": {
      "Ref": "EcsSystemDiskCategory"
    },
    "MaxAmount": {
      "Ref": "EcsGroup1MaxAmount"
    },
    "VSwitchId": {
      "Fn::GetAtt": [
        "VSwitch1",
        "VSwitchId"
      ]
    },
    "VpcId": {
      "Ref": "Vpc"
    },
    "InstanceType": {
      "Ref": "EcsGroupInstanceType"
    }
  }
}           
  • 建立彈性伸縮組完成,将RDS和SLB執行個體都加入到組内,代碼示例如下:
"ScalingGroup": {
  "Type": "ALIYUN::ESS::ScalingGroup",
  "DependsOn": "CreateListener",
  "Properties": {
    "DBInstanceIds": [
      {
        "Fn::GetAtt": [
          "Database",
          "DBInstanceId"
        ]
      }
    ],
    "DefaultCooldown": {
      "Ref": "EssDefaultCooldown"
    },
    "LoadBalancerIds": [
      {
        "Fn::GetAtt": [
          "LoadBalancer",
          "LoadBalancerId"
        ]
      }
    ],
    "MaxSize": {
      "Ref": "EssMaxSize"
    },
    "MinSize": {
      "Ref": "EssMinSize"
    },
    "VpcId": {
      "Ref": "Vpc"
    },
    "VSwitchIds": [
      {
        "Fn::GetAtt": [
          "VSwitch1",
          "VSwitchId"
        ]
      },
      {
        "Fn::GetAtt": [
          "VSwitch2",
          "VSwitchId"
        ]
      }
    ]
  }
}           
  • 将建立的所有ECS執行個體,在啟用伸縮組時候加入到伸縮組内,代碼示例如下:
"ScalingGroupEnable": {
  "Type": "ALIYUN::ESS::ScalingGroupEnable",
  "DependsOn": "ScalingGroup",
  "Properties": {
    "ScalingGroupId": {
      "Fn::GetAtt": [
        "ScalingGroup",
        "ScalingGroupId"
      ]
    },
    "ScalingConfigurationId": {
      "Fn::GetAtt": [
        "ScalingConfiguration",
        "ScalingConfigurationId"
      ]
    },
    "InstanceIds": {
      "Fn::ListMerge": [
        {
          "Fn::GetAtt": [
            "EcsInstanceGroup1",
            "InstanceIds"
          ]
        },
        {
          "Fn::GetAtt": [
            "EcsInstanceGroup2",
            "InstanceIds"
          ]
        }
      ]
    }
  }
}           
  • 建立需要的單個資源,如RDS、SLB資源,代碼詳見<相關模版>。

總結:

使用阿裡雲資源編排服務 ,不需要支付額外的費用。

傳統部署打造一個這樣的環境,還是需要一定物力、人力、時間的,利用本文中提供的ROS模闆,可以很好,很友善的幫你一鍵部署此類環境,讓你把更多的精力放在自己的業務上。

資源編排服務

相關模闆

{
  "ROSTemplateFormatVersion": "2015-09-01",
  "Description": "Create Multi-ECS And Scaling Group And Rds And Slb In Double Zone.",
  "Conditions": {
    "CreateInstacneGroup2": {
      "Fn::Not": {
        "Fn::Equals": [
          0,
          {
            "Ref": "EcsGroup2MaxAmount"
          }
        ]
      }
    }
  },
  "Resources": {
    "Vpc": {
      "Type": "ALIYUN::ECS::VPC",
      "Properties": {
        "VpcName": {
          "Ref": "VpcName"
        },
        "CidrBlock": {
          "Ref": "VPCCidrBlock"
        },
        "Description": {
          "Ref": "VPCDescription"
        }
      }
    },
    "VSwitch1": {
      "Type": "ALIYUN::ECS::VSwitch",
      "DependsOn": "Vpc",
      "Properties": {
        "VSwitchName": {
          "Ref": "VSwitch1Name"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "CidrBlock": {
          "Ref": "VSW1CidrBlock"
        },
        "Description": {
          "Ref": "VSW1Description"
        },
        "ZoneId": {
          "Ref": "VSW1ZoneId"
        }
      }
    },
    "VSwitch2": {
      "Type": "ALIYUN::ECS::VSwitch",
      "DependsOn": "Vpc",
      "Properties": {
        "VSwitchName": {
          "Ref": "VSwitch2Name"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "CidrBlock": {
          "Ref": "VSW2CidrBlock"
        },
        "Description": {
          "Ref": "VSW2Description"
        },
        "ZoneId": {
          "Ref": "VSW2ZoneId"
        }
      }
    },
    "SG": {
      "Type": "ALIYUN::ECS::SecurityGroup",
      "DependsOn": "Vpc",
      "Properties": {
        "VpcId": {
          "Ref": "Vpc"
        },
        "SecurityGroupName": "mysg",
        "SecurityGroupIngress": [
          {
            "PortRange": "-1/-1",
            "Priority": 1,
            "SourceCidrIp": "0.0.0.0/0",
            "IpProtocol": "all",
            "NicType": "intranet"
          }
        ],
        "SecurityGroupEgress": [
          {
            "PortRange": "-1/-1",
            "Priority": 1,
            "IpProtocol": "all",
            "DestCidrIp": "0.0.0.0/0",
            "NicType": "intranet"
          }
        ]
      }
    },
    "EcsInstanceGroup1": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "DependsOn": "VSwitch1",
      "Properties": {
        "IoOptimized": "optimized",
        "ImageId": {
          "Ref": "EcsGroupImageId"
        },
        "SecurityGroupId": {
          "Ref": "SG"
        },
        "Password": {
          "Ref": "EcsPassword"
        },
        "MinAmount": {
          "Ref": "EcsGroup1MaxAmount"
        },
        "AllocatePublicIP": "false",
        "SystemDiskCategory": {
          "Ref": "EcsSystemDiskCategory"
        },
        "MaxAmount": {
          "Ref": "EcsGroup1MaxAmount"
        },
        "VSwitchId": {
          "Fn::GetAtt": [
            "VSwitch1",
            "VSwitchId"
          ]
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "InstanceType": {
          "Ref": "EcsGroupInstanceType"
        }
      }
    },
    "EcsInstanceGroup2": {
      "Type": "ALIYUN::ECS::InstanceGroup",
      "DependsOn": "VSwitch2",
      "Condition": "CreateInstacneGroup2",
      "Properties": {
        "IoOptimized": "optimized",
        "ImageId": {
          "Ref": "EcsGroupImageId"
        },
        "SecurityGroupId": {
          "Ref": "SG"
        },
        "Password": {
          "Ref": "EcsPassword"
        },
        "MinAmount": {
          "Ref": "EcsGroup2MaxAmount"
        },
        "AllocatePublicIP": "false",
        "SystemDiskCategory": {
          "Ref": "EcsSystemDiskCategory"
        },
        "MaxAmount": {
          "Ref": "EcsGroup2MaxAmount"
        },
        "VSwitchId": {
          "Fn::GetAtt": [
            "VSwitch2",
            "VSwitchId"
          ]
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "InstanceType": {
          "Ref": "EcsGroupInstanceType"
        }
      }
    },
    "ScalingGroup": {
      "Type": "ALIYUN::ESS::ScalingGroup",
      "DependsOn": "CreateListener",
      "Properties": {
        "DBInstanceIds": [
          {
            "Fn::GetAtt": [
              "Database",
              "DBInstanceId"
            ]
          }
        ],
        "DefaultCooldown": {
          "Ref": "EssDefaultCooldown"
        },
        "LoadBalancerIds": [
          {
            "Fn::GetAtt": [
              "LoadBalancer",
              "LoadBalancerId"
            ]
          }
        ],
        "MaxSize": {
          "Ref": "EssMaxSize"
        },
        "MinSize": {
          "Ref": "EssMinSize"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchIds": [
          {
            "Fn::GetAtt": [
              "VSwitch1",
              "VSwitchId"
            ]
          },
          {
            "Fn::GetAtt": [
              "VSwitch2",
              "VSwitchId"
            ]
          }
        ]
      }
    },
    "Database": {
      "Type": "ALIYUN::RDS::DBInstance",
      "DependOn": "EcsInstanceGroup1",
      "Properties": {
        "DBInstanceClass": {
          "Ref": "RdsDBInstanceClass"
        },
        "DBInstanceNetType": {
          "Ref": "RdsDBInstanceNetType"
        },
        "DBInstanceStorage": {
          "Ref": "RdsDBInstanceStorage"
        },
        "Engine": {
          "Ref": "RdsEngine"
        },
        "EngineVersion": {
          "Ref": "RdsEngineVersion"
        },
        "SecurityIPList": {
          "Ref": "RdsSecurityIPList"
        },
        "VpcId": {
          "Ref": "Vpc"
        },
        "VSwitchId": {
          "Fn::GetAtt": [
            "VSwitch1",
            "VSwitchId"
          ]
        }
      }
    },
    "LoadBalancer": {
      "Type": "ALIYUN::SLB::LoadBalancer",
      "Properties": {
        "AddressType": "internet"
      }
    },
    "CreateListener": {
      "Type": "ALIYUN::SLB::Listener",
      "DependOn": "LoadBalancer",
      "Properties": {
        "BackendServerPort": 8080,
        "Bandwidth": 50,
        "ListenerPort": "80",
        "LoadBalancerId": {
          "Ref": "LoadBalancer"
        },
        "Protocol": "http",
        "Scheduler": "wrr"
      }
    },
    "Attachment": {
      "Type": "ALIYUN::SLB::BackendServerAttachment",
      "DependOn": "Database",
      "Properties": {
        "BackendServerList": {
          "Fn::ListMerge": [
            {
              "Fn::GetAtt": [
                "EcsInstanceGroup1",
                "InstanceIds"
              ]
            },
            {
              "Fn::GetAtt": [
                "EcsInstanceGroup2",
                "InstanceIds"
              ]
            }
          ]
        },
        "LoadBalancerId": {
          "Ref": "LoadBalancer"
        }
      }
    },
    "ScalingConfiguration": {
      "Type": "ALIYUN::ESS::ScalingConfiguration",
      "Properties": {
        "DiskMappings": [
          {
            "Category": "cloud_efficiency",
            "Device": "/dev/xvdb",
            "Size": 100
          }
        ],
        "SystemDisk_Category": "cloud_efficiency",
        "ScalingGroupId": {
          "Fn::GetAtt": [
            "ScalingGroup",
            "ScalingGroupId"
          ]
        },
        "SecurityGroupId": {
          "Fn::GetAtt": [
            "SG",
            "SecurityGroupId"
          ]
        },
        "UserData": {
          "Fn::Join": [
            "",
            [
              "#!/bin/sh\n",
              "echo \"nihao\" > /tmp/test_result.log\n"
            ]
          ]
        },
        "ImageId": {
          "Ref": "EcsGroupImageId"
        },
        "InstanceType": {
          "Ref": "EcsGroupInstanceType"
        }
      }
    },
    "ScalingGroupEnable": {
      "Type": "ALIYUN::ESS::ScalingGroupEnable",
      "DependsOn": "ScalingGroup",
      "Properties": {
        "ScalingGroupId": {
          "Fn::GetAtt": [
            "ScalingGroup",
            "ScalingGroupId"
          ]
        },
        "ScalingConfigurationId": {
          "Fn::GetAtt": [
            "ScalingConfiguration",
            "ScalingConfigurationId"
          ]
        },
        "InstanceIds": {
          "Fn::ListMerge": [
            {
              "Fn::GetAtt": [
                "EcsInstanceGroup1",
                "InstanceIds"
              ]
            },
            {
              "Fn::GetAtt": [
                "EcsInstanceGroup2",
                "InstanceIds"
              ]
            }
          ]
        }
      }
    }
  },
  "Parameters": {
    "VpcName": {
      "Type": "String",
      "Label": "Name For Create VPC",
      "Description": "Display name of the vpc instance, [2, 128] English or Chinese characters, must start with a letter or Chinese in size, can contain numbers, '_' or '.', '-'",
      "Default": "TwoAvailableZonesVPC"
    },
    "VPCCidrBlock": {
      "Type": "String",
      "Label": "The VPC Cidrblock",
      "Description": "The IP address range of the VPC in the CIDR block form. You can use the following IP address ranges and their subnets:\n10.0.0.0/8\n172.16.0.0/12 (Default)\n192.168.0.0/16",
      "Default": "192.168.0.0/16"
    },
    "VPCDescription": {
      "Type": "String",
      "Label": "The Description Of VPC",
      "Description": "Description of the vpc, [2, 256] characters. Do not fill or empty, the default is empty.",
      "Default": "Description of the two available zones VPC"
    },
    "VSwitch1Name": {
      "Type": "String",
      "Label": "Name For Create Zone 1 VSwitch",
      "Description": "Display name of the vSwitch instance, [2, 128] English or Chinese characters, must start with a letter or Chinese in size, can contain numbers, '_' or '.', '-'",
      "Default": "Zone1VSitchName"
    },
    "VSW1CidrBlock": {
      "Type": "String",
      "Label": "The VSwitch 1 Cidrblock",
      "Description": "CIDR Block of created VSwitch, It must belong to itself VPC CIDR block.",
      "Default": "192.168.1.0/24"
    },
    "VSW1Description": {
      "Type": "String",
      "Label": "The Description Of The Zone 1 VSwitch",
      "Description": "Description of the VSwitch, [2, 256] characters. Do not fill or empty, the default is empty.",
      "Default": "Description of the available zone 1 VSwitch"
    },
    "VSW1ZoneId": {
      "Type": "String",
      "Label": " The VSwitch 1 Available Zone ID",
      "Description": "VSwitch Available Zone ID, <a href='#/product/cn-beijing/list/zoneList' target='_blank'>View zoneid info</a>"
    },
    "VSwitch2Name": {
      "Type": "String",
      "Label": "Name For Create Zone 2 VSwitch",
      "Description": "Display name of the vSwitch instance, [2, 128] English or Chinese characters, must start with a letter or Chinese in size, can contain numbers, '_' or '.', '-'",
      "Default": "Zone2VSitchName"
    },
    "VSW2CidrBlock": {
      "Type": "String",
      "Label": "The VSwitch 2 Cidrblock",
      "Description": "CIDR Block of created VSwitch, It must belong to itself VPC CIDR block.",
      "Default": "192.168.2.0/24"
    },
    "VSW2Description": {
      "Type": "String",
      "Label": "The Description Of The Zone 2 VSwitch",
      "Description": "Description of the VSwitch, [2, 256] characters. Do not fill or empty, the default is empty.",
      "Default": "Description of the available zone 2 VSwitch"
    },
    "VSW2ZoneId": {
      "Type": "String",
      "Label": "The VSwitch 2 Available Zone ID",
      "Description": "VSwitch Available Zone ID, <a href='#/product/cn-beijing/list/zoneList' target='_blank'>View zoneid info</a>"
    },
    "EcsGroupImageId": {
      "Type": "String",
      "Label": "Ecs Image Id",
      "Description": "Image Id, represents the image resource to startup the ECS instance, <a href='#/product/cn-beijing/list/imageList' target='_blank'>View image resources</a>",
      "Default": "centos_7_04_64_20G_alibase_201701015.vhd"
    },
    "EcsGroupInstanceType": {
      "Type": "String",
      "Label": "Ecs Instance type",
      "Description": "The ECS instance type, <a href='#/product/cn-beijing/list/typeList' target='_blank'>View instance types</a>",
      "Default": "ecs.c5.large",
      "AllowedValues": [
        "ecs.c5.large",
        "ecs.c5.xlarge",
        "ecs.g5.large",
        "ecs.g5.xlarge"
      ]
    },
    "EcsPassword": {
      "Type": "String",
      "Label": "Ecs Password",
      "ConstraintDescription": "[8, 30] characters, consists of 3 types of uppercase letter, lowercase letter, number or special characters.",
      "Description": "The login password of ECS instance",
      "MaxLength": 30,
      "MinLength": 8,
      "NoEcho": true,
      "Confirm": true
    },
    "EcsSystemDiskCategory": {
      "Type": "String",
      "Label": "Ecs System Disk Category",
      "Description": "System disk category: efficient cloud disk(cloud_efficiency) or SSD cloud disk(cloud_ssd)",
      "Default": "cloud_ssd",
      "AllowedValues": [
        "cloud_efficiency",
        "cloud_ssd"
      ]
    },
    "EssDefaultCooldown": {
      "Type": "Number",
      "Label": "The Default Cooldown",
      "Description": "The Default cooldown in seconds",
      "Default": 300
    },
    "EcsGroup1MaxAmount": {
      "Type": "Number",
      "Description": "The number of Ecs Group1 instance.",
      "Label": "Number of Ecs Group1 instance",
      "Default": 2,
      "AllowedValues": [
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10
      ]
    },
    "EcsGroup2MaxAmount": {
      "Type": "Number",
      "Label": "Number of Ecs Group2 instance",
      "Description": "The number of Ecs Group2 iinstance.",
      "Default": 2,
      "AllowedValues": [
        0,
        1,
        2,
        3,
        4,
        5,
        6,
        7,
        8,
        9,
        10
      ]
    },
    "EssMaxSize": {
      "Type": "Number",
      "Label": "The Max Number Of ECS In Scaling Group",
      "Description": "The maximum of ECS instances in scaling group",
      "MaxValue": 100,
      "MinValue": 1,
      "Default": 20
    },
    "EssMinSize": {
      "Type": "Number",
      "Label": "The Min Number Of ECS In Scaling Group",
      "Description": "The minimum of ECS instances in scaling group",
      "MaxValue": 100,
      "MinValue": 1,
      "Default": 1
    },
    "RdsDBInstanceClass": {
      "Type": "String",
      "Label": "Rds Instance Class",
      "Description": "Database instance type. Refer the RDS database instance type,<a href='https://help.aliyun.com/document_detail/26312.html' target='_blank'>View RDS resources type</a>",
      "AllowedValues": [
        "rds.mysql.t1.small",
        "rds.mysql.s1.small",
        "rds.mysql.s2.large",
        "rds.mysql.s2.xlarge",
        "rds.mysql.s3.large",
        "rds.mysql.m1.medium",
        "rds.mysql.c1.large",
        "rds.mysql.c1.xlarge",
        "rds.mysql.c2.xlarge",
        "rds.mysql.c2.xlp2"
      ],
      "Default": "rds.mysql.t1.small"
    },
    "RdsDBInstanceNetType": {
      "Type": "String",
      "Label": "Database Instance Net Type",
      "Description": "Database instance net type, default is Intranet.Internet for public access, Intranet for private access.",
      "AllowedValues": [
        "Internet",
        "Intranet"
      ],
      "Default": "Intranet"
    },
    "RdsDBInstanceStorage": {
      "Type": "Number",
      "Label": "Database Instance Storage Size",
      "Description": "Incrementing in every 5G, unit: GB",
      "ConstraintDescription": "Incrementing in every 5G, unit: GB",
      "MaxValue": 2000,
      "MinValue": 5,
      "Default": 10
    },
    "RdsEngine": {
      "Type": "String",
      "Label": "Database Instance Engine Type",
      "Description": "Database instance engine type. Support MySQL/SQLServer/PostgreSQL/PPAS/MariaDB now.",
      "AllowedValues": [
        "MySQL",
        "SQLServer",
        "PostgreSQL",
        "PPAS"
      ],
      "Default": "MySQL"
    },
    "RdsEngineVersion": {
      "Type": "String",
      "Label": "Database Engine Version",
      "AllowedValues": [
        "5.5",
        "5.6",
        "2008r2",
        "9.4",
        "9.3"
      ],
      "Description": "MySQL:5.5/5.6; SQLServer:2008r2; PostgreSQL:9.4; PPAS:9.3",
      "Default": "5.6"
    },
    "RdsSecurityIPList": {
      "Type": "String",
      "Label": "Security Ip To access The Database",
      "Description": "The ECS instances IP list access database, separated by commas, do not be repeated",
      "Default": "0.0.0.0/0"
    }
  },
  "Outputs": {
    "RouteTableId": {
      "Description": "The router table id of created VPC.",
      "Value": {
        "Fn::GetAtt": [
          "Vpc",
          "RouteTableId"
        ]
      }
    },
    "VpcId": {
      "Description": "Id of created VPC.",
      "Value": {
        "Fn::GetAtt": [
          "Vpc",
          "VpcId"
        ]
      }
    },
    "VRouterId": {
      "Description": "Router id of created VPC.",
      "Value": {
        "Fn::GetAtt": [
          "Vpc",
          "VRouterId"
        ]
      }
    },
    "VSwitchId1": {
      "Description": "Id of created VSwitch1.",
      "Value": {
        "Fn::GetAtt": [
          "VSwitch1",
          "VSwitchId"
        ]
      }
    },
    "VSwitchId2": {
      "Description": "Id of created VSwitch2.",
      "Value": {
        "Fn::GetAtt": [
          "VSwitch2",
          "VSwitchId"
        ]
      }
    },
    "SecurityGroupId": {
      "Description": "The Security group id.",
      "Value": {
        "Fn::GetAtt": [
          "SG",
          "SecurityGroupId"
        ]
      }
    },
    "BackendServerList": {
      "Description": "Backend server list",
      "Value": {
        "Fn::ListMerge": [
          {
            "Fn::GetAtt": [
              "EcsInstanceGroup1",
              "InstanceIds"
            ]
          },
          {
            "Fn::GetAtt": [
              "EcsInstanceGroup2",
              "InstanceIds"
            ]
          }
        ]
      }
    }
  }
}           

繼續閱讀