创建ECS实例组并挂载到CLB实例

更新时间:
复制 MD 格式

本文以创建ECS实例组并挂载到传统型负载均衡(CLB)实例为例,由简入难的向您介绍如何编辑ROS模板。

方案概述

本方案使用阿里云资源编排服务(ROS)通过 YAML 模板,一次性创建 VPC 网络、ECS 实例组并部署 Nginx 服务,然后创建传统型负载均衡(CLB)实例并将 ECS 实例组挂载为后端服务器,最后绑定弹性公网 IP(EIP)对外提供 HTTP 服务。适用于需要快速搭建高可用 Web 服务集群的场景。

业务场景

在阿里云专有网络(VPC)中批量创建 ECS 实例,通过 ECS 云助手自动安装并启动 Nginx 服务,等待服务初始化完成后将 ECS 实例挂载到 CLB 负载均衡器实现流量分发,并通过 EIP 对外暴露 HTTP 访问地址。

创建的资源清单

序号

资源名称

ROS 资源类型

用途说明

1

专有网络 VPC

ALIYUN::ECS::VPC

提供隔离的网络环境

2

交换机 VSwitch

ALIYUN::ECS::VSwitch

在 VPC 中划分子网网段,指定可用区

3

安全组 SecurityGroup

ALIYUN::ECS::SecurityGroup

开放 HTTP 80 端口入站,允许所有出站

4

ECS 实例组 InstanceGroup

ALIYUN::ECS::InstanceGroup

批量创建多台 ECS,通过 CommandContent 自动部署 Nginx

5

负载均衡 CLB

ALIYUN::SLB::LoadBalancer

传统型负载均衡实例,分发流量到后端 ECS

6

负载均衡监听 Listener

ALIYUN::SLB::Listener

配置 CLB 的 TCP/HTTP 监听端口和健康检查

7

后端服务器挂载

ALIYUN::SLB::BackendServerAttachment

将 ECS 实例组挂载到 CLB 作为后端服务器

8

弹性公网 IP EIP

ALIYUN::VPC::EIP

提供公网访问入口

9

EIP 绑定

ALIYUN::VPC::EIPAssociation

将 EIP 绑定到 CLB 实例

部署完成后获得的结果

模板成功执行后,您将获得:

  • 一个完整的 VPC 网络环境(包含 VPC、交换机、安全组,已开放 80 端口)。

  • 一组 ECS 实例(默认 2 台),已自动完成数据盘挂载和 Nginx 服务部署。

  • 一个 CLB 负载均衡实例,已配置 TCP 80 端口监听和健康检查。

  • 所有 ECS 实例已挂载到 CLB 后端服务器组,支持按权重分发流量。

  • 一个弹性公网 IP(EIP),已绑定到 CLB,可通过 http://<EIP地址> 访问 Nginx 服务。

架构图

image

前提条件

在使用本模板前,请确认以下条件:

  1. 账号权限:您的阿里云账号需要具有以下产品的创建权限:ECS、CLB、VPC、EIP。

  2. 基础知识:了解 ROS 模板的基本语法和结构,详情请参见模板快速入门

模板编写教程

本教程分两个阶段演示模板编写过程:

  • 阶段一(基础版):使用固定参数值,专注于理解资源定义和 CLB 挂载关系。

  • 阶段二(进阶版):参数化所有可变配置,添加动态参数筛选、付费类型条件显示和参数分组。

阶段一:基础模板——定义资源及其依赖关系

Step 1:定义基础网络资源(VPC + VSwitch + 安全组

网络资源是所有其他资源的基础,需要最先创建。安全组需开放 HTTP 80 端口入站以允许外部访问 Nginx。

Resources:
  # ============================================================
  # 基础网络层:VPC → VSwitch → SecurityGroup
  # ============================================================

  Vpc:
    Type: ALIYUN::ECS::VPC  # 创建专有网络
    Properties:
      CidrBlock: 192.168.0.0/16
      VpcName:
        Ref: ALIYUN::StackName  # 伪参数:使用资源栈名称作为VPC名称

  VSwitch:
    Type: ALIYUN::ECS::VSwitch  # 在VPC中创建交换机(子网)
    Properties:
      VSwitchName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc  # 隐式依赖:ROS会先创建Vpc
      ZoneId: cn-beijing-h # 此场景以北京H可用区为示例
      CidrBlock: 192.168.0.0/24

  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup  # 创建安全组
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc
      SecurityGroupIngress:  # 入站规则:开放HTTP 80端口(Nginx服务对外)
        - PortRange: 80/80
          Priority: 1
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
          NicType: internet

关键知识点与思考:

  • 类似 VpcName、VSwitchName、SecurityGroupName 这类自定义配置可以使用伪参数进行配置,这样可以让我们在部署资源后快速找到属于该资源栈部署相关的资源。

  • SecurityGroup 的访问规则可以根据业务需求自定义配置,例如:

    • 需要在外部访问 Web 服务,可配置开启安全组入方向的 HTTP 80 或 8080 端口访问。

    • 需要 SSH 登录服务器,可配置开启安全组入方向的 22 端口访问。

  • 生产环境建议限制 SourceCidrIp 为已知 IP 段,不建议使用 0.0.0.0/0

Step 2:定义CLB 负载均衡弹性公网 IP资源

CLB 负载均衡实例负责将外部流量分发到多台后端 ECS。EIP 提供公网入口地址。

Resources:
  # ============================================================
  # 负载均衡层:CLB + Listener + EIP
  # ============================================================

  Slb:
    Type: ALIYUN::SLB::LoadBalancer  # 创建传统型负载均衡实例
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch
      LoadBalancerName:
        Fn::Sub: slb-${ALIYUN::StackName}  # Fn::Sub拼接字符串
      AddressType: intranet  # 内网类型CLB(通过EIP提供公网访问)
      LoadBalancerSpec: slb.s1.small
      AutoPay: true

  SlbListener:
    Type: ALIYUN::SLB::Listener  # 配置CLB监听
    DependsOn:
      - Slb  # 显式依赖:CLB创建后才能添加监听
    Properties:
      LoadBalancerId:
        Ref: Slb
      ListenerPort: 80  # 前端监听端口
      BackendServerPort: 80  # 后端服务器端口(Nginx默认80)
      Protocol: tcp  # 四层TCP协议转发
      Bandwidth: -1  # -1表示不限带宽,具体取值请根据CLB实例规格调整
      Persistence:  # 会话保持配置
        StickySession: 'on'
        StickySessionType: insert  # 植入Cookie方式
        CookieTimeout: 60
        PersistenceTimeout: 180
      HealthCheck:  # 健康检查配置
        HealthCheckType: tcp  # TCP端口探测
        Port: 80
        Interval: 2  # 检查间隔2秒
        HealthyThreshold: 3  # 3次成功判定为健康
        UnhealthyThreshold: 3  # 3次失败判定为异常
        Timeout: 5  # 探测超时5秒

  EipSlbAddress:
    Type: ALIYUN::VPC::EIP  # 创建弹性公网IP
    Properties:
      Name:
        Ref: ALIYUN::StackName
      InternetChargeType: PayByTraffic  # 按流量计费
      Bandwidth: 10  # 带宽上限10Mbps

  EipSlbAddressAssociation:
    Type: ALIYUN::VPC::EIPAssociation  # 将EIP绑定到CLB
    Properties:
      InstanceId:
        Ref: Slb  # 绑定目标:CLB实例
      AllocationId:
        Ref: EipSlbAddress  # EIP资源ID

关键知识点与思考:

  • DependsOn 的隐式关联 vs 显式依赖关联

    • 当使用 RefFn::GetAtt 引用了某个资源,ROS 会自动判断依赖(隐式)。只有当两个资源之间没有直接引用关系,但业务上要求先后顺序时,才需要 DependsOn(显式)。

  • CLB 使用 AddressType: intranet(内网类型),再通过 ALIYUN::VPC::EIPAssociation 绑定 EIP 实现公网访问,这是推荐的架构模式。

Step 3:定义ECS 实例组云助手安装Nginx 脚本

ECS 实例通过云助手执行初始化脚本(数据盘挂载 + Nginx 安装)。

Resources:
  EcsInstanceGroup:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitch
      ZoneId: cn-beijing-h
      ImageId: centos_7
      InstanceType: ecs.c5.large
      MaxAmount: 2 # 创建2台ECS实例
      AllocatePublicIP: false # 不分配公网IP(通过CLB+EIP对外)
      IoOptimized: optimized
      SystemDiskCategory: cloud_essd
      SystemDiskSize: 40
      DiskMappings: # 数据盘配置
        - Category: cloud_essd
          Size: 100
      Password: <YourPassword>  # 部署时请替换为实际密码(需含大小写字母+数字+特殊字符)

  RunSetup:
    Type: ALIYUN::ECS::RunCommand
    DependsOn: EcsInstanceGroup
    Properties:
      InstanceIds:
        Fn::GetAtt:
          - EcsInstanceGroup
          - InstanceIds
      Type: RunShellScript
      Sync: true
      Timeout: 300
      ContentEncoding: PlainText
      CommandContent: |
        #!/bin/bash
        # === 数据盘初始化:分区、格式化、挂载到/disk1 ===
        cat >> /root/InitDataDisk.sh << 'EOF'
        #!/bin/bash
        echo "p
        n
        p
        w
        " |  fdisk -u /dev/vdb
        EOF
        /bin/bash /root/InitDataDisk.sh
        rm -f /root/InitDataDisk.sh
        mkfs -t ext4 /dev/vdb1
        cp /etc/fstab /etc/fstab.bak
        mkdir /disk1
        echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\"//g'` /disk1 ext4 defaults 0 0 >> /etc/fstab
        mount -a

        # === 安装并启动Nginx ===
        yum install -y nginx
        systemctl start nginx.service

关键知识点与思考:

  • RefFn::GetAtt 的区别:

    • Ref返回资源的主标识符(如 VPC 的 VpcId)。

    • Fn::GetAtt返回资源的相关属性(如 EcsInstanceGroupInstanceIds)。

Step 4:定义 CLB 后端服务器挂载——将 ECS 连接到 CLB

通过 ALIYUN::SLB::BackendServerAttachment 将 ECS 实例组挂载到 CLB 后端。

Resources:
  # ============================================================
  # 绑定层:将ECS实例组挂载到CLB后端服务器
  # ============================================================

  SlbBackendServerAttachment:
    Type: ALIYUN::SLB::BackendServerAttachment
    DependsOn:
      - EcsInstanceGroup  # 显式依赖:等待ECS创建完成
    Properties:
      LoadBalancerId:
        Ref: Slb
      BackendServerList:
        # 获取ECS实例组的所有实例ID列表
        Fn::GetAtt:
          - EcsInstanceGroup
          - InstanceIds
      BackendServerWeightList:  # 后端服务器权重列表
        - 100  # 第1台ECS权重100
        - 100  # 第2台ECS权重100

关键知识点:BackendServerWeightList 权重规则

  • 权重值范围 0~100,权重越高分配的流量越多。

  • 如果 BackendServerWeightList 长度小于 BackendServerList,剩余 ECS 实例使用列表中最后一个权重值。

基础版完整模板

以下是将上述步骤合并后的完整可用模板:

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 创建VPC网络,部署ECS实例组并安装Nginx,挂载到CLB负载均衡器,通过EIP对外提供HTTP服务
  en: Create VPC, deploy ECS group with Nginx, attach to CLB, expose via EIP

Resources:
  # === 基础网络层 ===
  Vpc:
    Type: ALIYUN::ECS::VPC
    Properties:
      CidrBlock: 192.168.0.0/16
      VpcName:
        Ref: ALIYUN::StackName
  VSwitch:
    Type: ALIYUN::ECS::VSwitch
    Properties:
      VSwitchName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc
      ZoneId: cn-beijing-h
      CidrBlock: 192.168.0.0/24
  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc
      SecurityGroupIngress:
        - PortRange: 80/80
          Priority: 1
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
          NicType: internet
      SecurityGroupEgress:
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: internet
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: intranet

  # === 计算层 ===
  EcsInstanceGroup:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitch
      ImageId: centos_7
      InstanceType: ecs.c5.large
      MaxAmount: 2
      AllocatePublicIP: false
      IoOptimized: optimized
      SystemDiskCategory: cloud_essd
      SystemDiskSize: 40
      DiskMappings:
        - Category: cloud_essd
          Size: 100
      Password: <YourPassword>  # 部署时请替换为实际密码
  RunSetup:
    Type: ALIYUN::ECS::RunCommand
    DependsOn: EcsInstanceGroup
    Properties:
      InstanceIds:
        Fn::GetAtt:
          - EcsInstanceGroup
          - InstanceIds
      Type: RunShellScript
      Sync: true
      Timeout: 300
      ContentEncoding: PlainText
      CommandContent: |
        #!/bin/bash
        # === 数据盘初始化:分区、格式化、挂载到/disk1 ===
        cat >> /root/InitDataDisk.sh << 'EOF'
        #!/bin/bash
        echo "p
        n
        p
        w
        " |  fdisk -u /dev/vdb
        EOF
        /bin/bash /root/InitDataDisk.sh
        rm -f /root/InitDataDisk.sh
        mkfs -t ext4 /dev/vdb1
        cp /etc/fstab /etc/fstab.bak
        mkdir /disk1
        echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\"//g'` /disk1 ext4 defaults 0 0 >> /etc/fstab
        mount -a

        # === 安装并启动Nginx ===
        yum install -y nginx
        systemctl start nginx.service

  # === 负载均衡层 ===
  Slb:
    Type: ALIYUN::SLB::LoadBalancer
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch
      LoadBalancerName:
        Fn::Sub: slb-${ALIYUN::StackName}
      AddressType: intranet
      LoadBalancerSpec: slb.s1.small
      AutoPay: true
  SlbListener:
    DependsOn:
      - Slb
    Type: ALIYUN::SLB::Listener
    Properties:
      LoadBalancerId:
        Ref: Slb
      ListenerPort: 80
      BackendServerPort: 80
      Protocol: tcp
      Bandwidth: -1
      Persistence:
        StickySession: 'on'
        StickySessionType: insert
        CookieTimeout: 60
        PersistenceTimeout: 180
      HealthCheck:
        HealthCheckType: tcp
        Port: 80
        Interval: 2
        HealthyThreshold: 3
        UnhealthyThreshold: 3
        Timeout: 5
  EipSlbAddress:
    Type: ALIYUN::VPC::EIP
    Properties:
      Name:
        Ref: ALIYUN::StackName
      InternetChargeType: PayByTraffic
      Bandwidth: 10
  EipSlbAddressAssociation:
    Type: ALIYUN::VPC::EIPAssociation
    Properties:
      InstanceId:
        Ref: Slb
      AllocationId:
        Ref: EipSlbAddress

  # === 绑定层 ===
  SlbBackendServerAttachment:
    DependsOn:
      - EcsInstanceGroup
    Type: ALIYUN::SLB::BackendServerAttachment
    Properties:
      BackendServerList:
        Fn::GetAtt:
          - EcsInstanceGroup
          - InstanceIds
      LoadBalancerId:
        Ref: Slb
      BackendServerWeightList:
        - 100
        - 100

Outputs:
  Endpoint:
    Description:
      zh-cn: 对外暴露的公网访问地址
      en: Public HTTP endpoint
    Value:
      Fn::Sub:
        - http://${ServerAddress}
        - ServerAddress:
            Fn::GetAtt:
              - EipSlbAddress
              - EipAddress

关键知识点与思考:模板创建完资源后,可以通过模板的 Outputs 信息直接查询对应资源内部属性信息,例如 CLB 实例绑定的公网 IP 等信息。

阶段二:进阶模板——参数化与动态配置

基础版模板中 ECS 的 InstanceTypeSystemDiskCategory 以及 CLB 的 LoadBalancerSpec 等属性使用了固定值。通过参数化可以大幅提高模板的灵活性。

本模板的进阶特性:

  1. 参数化(Parameters:将可变配置抽取为参数。

  2. 动态参数筛选(AssociationProperty:ROS 控制台根据已选参数自动过滤可用选项。

  3. 参数分组(Metadata:按逻辑分组展示参数。

参数依赖关系图

以下以 ECS 实例规格、系统盘类型和 CLB 实例规格为例,展示参数之间的依赖链路:

ZoneId(可用区,核心过滤参数)
  ├── EcsInstanceType(实例规格,按可用区+付费类型过滤)
  │     ├── SystemDiskCategory(系统盘类型,按可用区+实例规格过滤)
  │     └── DataDiskCategory(数据盘类型,按可用区+实例规格过滤)
  └── LoadBalancerSpec(CLB规格,按可用区过滤)

PayType(付费类型)
  ├── PayPeriodUnit(周期单位,仅PrePaid时显示)
  ├── PayPeriod(购买时长,仅PrePaid时显示)
  └── EcsInstanceType(实例规格,按可用区+付费类型过滤)

核心思路:先选可用区和 ECS 付费类型,再据此筛选 ECS 规格和 CLB 规格(当选择预付费类型时需要选择付费周期和购买时长),最后根据可用区 + ECS 规格筛选磁盘类型。每一步都只展示当前条件下可用的选项,避免无效组合。

参数 AssociationProperty 原理详解

1. ZoneId — 可用区(基础参数)

定义 AssociationPropertyALIYUN::ECS::ZoneId 列出当前地域下所有可用区。示例:

ZoneId:
    Type: String
    Label:
      zh-cn: 交换机可用区
      en: VSwitch Availability Zone
    Description:
      zh-cn: 选择交换机所在的可用区,ECS和CLB将部署在此可用区
      en: Select the availability zone for VSwitch, ECS and CLB will be deployed here
    AssociationProperty: ALIYUN::ECS::ZoneId

此参数是后续所有参数的筛选基础,用户选择后,其他参数的选项列表会随之更新。

2. PayType — ECS 付费类型

定义 PayType 参数,使用 AssociationPropertyMetadata.Visible.Condition 实现参数的条件动态切换——当用户选择包年包月(PrePaid)时才显示购买时长相关参数。示例:

Parameters:
  PayType:
    Type: String
    Label:
      zh-cn: 付费类型
      en: Charge Type
    Default: PostPaid
    AllowedValues:
      - PostPaid
      - PrePaid
    AssociationProperty: ChargeType
    AssociationPropertyMetadata:
      LocaleKey: InstanceChargeType
  PayPeriodUnit:
    Type: String
    Default: Month
    AssociationProperty: PayPeriodUnit
    AssociationPropertyMetadata:
      Visible:  # 条件显示:仅当PayType不是PostPaid时才显示此参数
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid
  PayPeriod:
    Type: Number
    Label:
      zh-cn: 购买资源时长
      en: Period
    Default: 1
    AllowedValues:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
    AssociationProperty: PayPeriod
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid

当在 ROS 控制台选择按量付费(PostPaid)时,购买时长相关参数自动隐藏;选择包年包月(PrePaid)时才显示这些参数。

3. EcsInstanceType — ECS 实例规格

定义 AssociationPropertyALIYUN::ECS::Instance::InstanceType 列出可用的 ECS 实例规格,并通过关联 ${ZoneId}${PayType} 筛选对应可用区下对应付费类型支持的可用实例规格。示例:

EcsInstanceType:
    Type: String
    Label:
      zh-cn: ECS实例规格
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceChargeType: ${PayType}

不同可用区的实例规格库存不同。如果不过滤,可能选到该可用区无货的规格,导致创建失败。

4. SystemDiskCategory — 系统盘类型

定义 AssociationPropertyALIYUN::ECS::Disk::SystemDiskCategory 列出可选的系统盘类型,并通过关联 ${ZoneId}${EcsInstanceType} 筛选对应可用区与 ECS 实例规格支持使用的 ECS 系统盘类型。示例:

SystemDiskCategory:
    Type: String
    Label:
      zh-cn: 系统盘类型
      en: System Disk Category
    Description:
      zh-cn: 选择系统盘类型。可选值:cloud_essd(ESSD云盘)、cloud_ssd(SSD云盘)、cloud_efficiency(高效云盘)
      en: "System disk type. Options: cloud_essd, cloud_ssd, cloud_efficiency"
    AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategory
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceType: ${EcsInstanceType}

系统盘类型的可用性同时取决于可用区(某些可用区不支持 ESSD)和实例规格(某些规格仅支持特定磁盘类型)。

5. LoadBalancerSpec — CLB 实例规格

定义 AssociationPropertyALIYUN::SLB::Instance::InstanceType 列出可用的 CLB 实例规格,并通过关联 ${ZoneId} 筛选对应可用区支持的 CLB 实例规格。示例:

LoadBalancerSpec:
    Type: String
    Label:
      zh-cn: CLB实例规格
      en: CLB Instance Spec
    Description:
      zh-cn: 选择CLB实例规格,根据可用区自动过滤
      en: Select CLB instance specification
    AssociationProperty: ALIYUN::SLB::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}

动态参数筛选模板示例

Parameters:
  ZoneId:
    Type: String
    Label:
      zh-cn: 交换机可用区
      en: VSwitch Availability Zone
    Description:
      zh-cn: 选择交换机所在的可用区,ECS和CLB将部署在此可用区
      en: Select the availability zone for deployment
    AssociationProperty: ALIYUN::ECS::ZoneId
  PayType:
    Type: String
    Label:
      zh-cn: 付费类型
      en: Charge Type
    Default: PostPaid
    AllowedValues:
      - PostPaid
      - PrePaid
    AssociationProperty: ChargeType
    AssociationPropertyMetadata:
      LocaleKey: InstanceChargeType
  PayPeriodUnit:
    Type: String
    Default: Month
    AssociationProperty: PayPeriodUnit
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid
  PayPeriod:
    Type: Number
    Label:
      zh-cn: 购买资源时长
      en: Period
    Default: 1
    AllowedValues:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
    AssociationProperty: PayPeriod
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid
  EcsInstanceType:
    Type: String
    Label:
      zh-cn: ECS实例规格
      en: ECS Instance Type
    Description:
      zh-cn: 选择ECS实例规格。列表已根据可用区和付费类型自动过滤。
      en: Select ECS instance type, filtered by zone and charge type.
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceChargeType: ${PayType}
  SystemDiskCategory:
    Type: String
    Label:
      zh-cn: 系统盘类型
      en: System Disk Category
    Description:
      zh-cn: 选择系统盘类型。可选值:cloud_essd(ESSD云盘)、cloud_ssd(SSD云盘)、cloud_efficiency(高效云盘)
      en: System disk type
    AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategory
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceType: ${EcsInstanceType}
  DataDiskCategory:
    Type: String
    Label:
      zh-cn: 数据盘类型
      en: Data Disk Category
    Description:
      zh-cn: 选择数据盘类型。可选值:cloud_essd、cloud_ssd、cloud_efficiency
      en: Data disk type
    AssociationProperty: ALIYUN::ECS::Disk::DataDiskCategory
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceType: ${EcsInstanceType}
  LoadBalancerSpec:
    Type: String
    Label:
      zh-cn: CLB实例规格
      en: CLB Instance Spec
    Description:
      zh-cn: 选择CLB实例规格,根据可用区自动过滤
      en: Select CLB instance specification
    AssociationProperty: ALIYUN::SLB::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}

参数 AssociationProperty 工作原理总结

用户在 ROS 控制台创建资源栈时,参数的选择过程是级联触发的:

  1. 选择可用区(ZoneId)。

  2. 选择 ECS 付费类型(PayType)。

  3. ECS 实例规格下拉框自动刷新,仅显示该可用区下所支持对应付费类型且具备库存的规格。

  4. CLB 实例规格下拉框自动刷新,仅显示该可用区支持的规格。

  5. 选择 ECS 实例规格后,系统盘类型和数据盘类型下拉框自动刷新,仅显示该可用区 + 该规格共同支持的磁盘类型。

这样,每一步选择都只展示当前条件下可用的选项,从源头避免因参数组合无效导致的部署失败。

Metadata 参数分组

通过 Metadata 中的 ALIYUN::ROS::Interface 配置,可以将参数按逻辑分成多个组,每组带一个标题,控制台上会分组展示,填写体验大幅提升。

Metadata 语法结构

Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:           # 参数分组列表(必填)
      - Parameters:            # 该组包含的参数名列表(必填)
          - 参数名1
          - 参数名2
        Label:                 # 分组标题(必填)
          default:
            zh-cn: 中文标题
            en: English Title

Metadata 语法规则

  • ParameterGroupsParametersLabel 都是必填项。

  • Metadata.ALIYUN::ROS::Interface.ParameterGroups.Parameters 中列出的参数名必须与模板 Parameters 段中定义的参数名完全一致。

  • 未出现在任何分组中的参数,会在控制台显示在未分组区域。

本场景的分组设计

本模板将 14 个参数按资源类型分成 4 个组:

┌─────────────────────────────────────────────┐
│  基础网络配置                                │
│  ├── 交换机可用区 (ZoneId)                   │
│  ├── VPC网段 (VpcCidrBlock)                 │
│  └── 交换机网段 (VSwitchCidrBlock)           │
├─────────────────────────────────────────────┤
│  付费模式配置                                │
│  ├── ECS实例付费类型 (PayType)               │
│  ├── ECS预付费购买资源周期 (PayPeriodUnit)    │
│  └── ECS预付费购买资源时长 (PayPeriod)        │
├─────────────────────────────────────────────┤
│  ECS实例配置                                 │
│  ├── ECS实例规格 (EcsInstanceType)           │
│  ├── 系统盘类型 (SystemDiskCategory)         │
│  ├── 系统盘大小 (SystemDiskSize)             │
│  ├── 数据盘类型 (DataDiskCategory)           │
│  ├── 数据盘大小 (DataDiskSize)               │
│  └── ECS实例密码 (InstancePassword)          │
├─────────────────────────────────────────────┤
│  CLB负载均衡配置                              │
│  ├── CLB实例规格 (LoadBalancerSpec)          │
│  └── CLB绑定的EIP带宽 (Bandwidth)            │
└─────────────────────────────────────────────┘

Metadata 分组模板示例

Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - ZoneId
          - VpcCidrBlock
          - VSwitchCidrBlock
        Label:
          default:
            zh-cn: 基础网络配置
            en: Network Configuration
      - Parameters:
          - PayType
          - PayPeriodUnit
          - PayPeriod
        Label:
          default:
            zh-cn: 付费类型
            en: Billing Configuration
      - Parameters:
          - EcsInstanceType
          - SystemDiskCategory
          - SystemDiskSize
          - DataDiskCategory
          - DataDiskSize
          - InstancePassword
        Label:
          default:
            zh-cn: ECS实例配置
            en: ECS Instance Configuration
      - Parameters:
          - LoadBalancerSpec
          - Bandwidth
        Label:
          default:
            zh-cn: 负载均衡配置
            en: CLB Configuration

进阶版完整模板

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: >-
    参数化模板:创建ECS实例组部署Nginx服务,挂载到CLB负载均衡器,通过EIP对外提供HTTP服务。
    支持动态选择可用区、实例规格、磁盘类型和CLB规格,支持按量/包年包月付费模式切换。
  en: >-
    Parameterized template: Create ECS group with Nginx, attach to CLB, expose via EIP.
    Supports dynamic selection and PayAsYouGo/Subscription billing switch.

Parameters:
  # ─── 基础网络参数 ───
  ZoneId:
    Type: String
    Label:
      zh-cn: 交换机可用区
      en: VSwitch Availability Zone
    Description:
      zh-cn: 选择交换机所在的可用区,ECS和CLB将部署在此可用区
      en: Select the availability zone for deployment
    AssociationProperty: ALIYUN::ECS::ZoneId

  VpcCidrBlock:
    Type: String
    Label:
      zh-cn: VPC网段
      en: VPC CIDR Block
    Description:
      zh-cn: VPC的IP地址段范围。推荐使用 10.0.0.0/8、172.16.0.0/12 或 192.168.0.0/16
      en: VPC IP address range
    Default: 192.168.0.0/16

  VSwitchCidrBlock:
    Type: String
    Label:
      zh-cn: 交换机网段
      en: VSwitch CIDR Block
    Description:
      zh-cn: 必须是VPC网段的子网段,且不能与同VPC下其他交换机网段重叠
      en: Must be a subnet of VPC CIDR
    Default: 192.168.0.0/24

  # ─── 付费类型参数 ───
  PayType:
    Type: String
    Label:
      zh-cn: 付费类型
      en: Charge Type
    Default: PostPaid
    AllowedValues:
      - PostPaid
      - PrePaid
    AssociationProperty: ChargeType
    AssociationPropertyMetadata:
      LocaleKey: InstanceChargeType

  PayPeriodUnit:
    Type: String
    Label:
      zh-cn: 购买资源时长周期
      en: Pay Period Unit
    Description:
      zh-cn: 包年包月的周期单位。Month为月,Year为年。仅包年包月时有效。
      en: Subscription period unit. Only valid for PrePaid.
    Default: Month
    AllowedValues:
      - Month
      - Year
    AssociationProperty: PayPeriodUnit
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid

  PayPeriod:
    Type: Number
    Label:
      zh-cn: 购买资源时长
      en: Period
    Default: 1
    AllowedValues:
      - 1
      - 2
      - 3
      - 4
      - 5
      - 6
      - 7
      - 8
      - 9
    AssociationProperty: PayPeriod
    AssociationPropertyMetadata:
      Visible:
        Condition:
          Fn::Not:
            Fn::Equals:
              - ${PayType}
              - PostPaid

  # ─── ECS实例参数 ───
  EcsInstanceType:
    Type: String
    Label:
      zh-cn: ECS实例规格
      en: ECS Instance Type
    Description:
      zh-cn: 选择ECS实例规格。列表已根据可用区和付费类型自动过滤。
      en: Select ECS instance type, filtered by zone and charge type.
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceChargeType: ${PayType}

  SystemDiskCategory:
    Type: String
    Label:
      zh-cn: 系统盘类型
      en: System Disk Category
    Description:
      zh-cn: 选择系统盘类型。可选值:cloud_essd(ESSD云盘)、cloud_ssd(SSD云盘)、cloud_efficiency(高效云盘)
      en: System disk type
    AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategory
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceType: ${EcsInstanceType}

  SystemDiskSize:
    Type: Number
    Label:
      zh-cn: 系统盘大小(GB)
      en: System Disk Size (GB)
    Description:
      zh-cn: 系统盘大小,取值范围40~500 GB
      en: System disk size, range 40-500 GB
    Default: 40
    MinValue: 40
    MaxValue: 500

  DataDiskCategory:
    Type: String
    Label:
      zh-cn: 数据盘类型
      en: Data Disk Category
    Description:
      zh-cn: 选择数据盘类型。可选值:cloud_essd、cloud_ssd、cloud_efficiency
      en: Data disk type
    AssociationProperty: ALIYUN::ECS::Disk::DataDiskCategory
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}
      InstanceType: ${EcsInstanceType}

  DataDiskSize:
    Type: Number
    Label:
      zh-cn: 数据盘大小(GB)
      en: Data Disk Size (GB)
    Description:
      zh-cn: ECS数据盘大小,取值范围20~32768 GB
      en: Data disk size, range 20-32768 GB
    Default: 100
    MinValue: 20
    MaxValue: 32768

  InstancePassword:
    Type: String
    NoEcho: true
    Label:
      zh-cn: ECS实例密码
      en: ECS Instance Password
    Description:
      zh-cn: 长度8-30位,需包含大写字母、小写字母、数字、特殊字符中的至少三种
      en: Length 8-30, must contain at least three character types
    MinLength: 8
    MaxLength: 30
    AssociationProperty: ALIYUN::ECS::Instance::Password

  # ─── 负载均衡参数 ───
  LoadBalancerSpec:
    Type: String
    Label:
      zh-cn: CLB实例规格
      en: CLB Instance Spec
    Description:
      zh-cn: 选择CLB实例规格,根据可用区自动过滤
      en: Select CLB instance specification
    AssociationProperty: ALIYUN::SLB::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${ZoneId}

  Bandwidth:
    Type: Number
    Label:
      zh-cn: EIP带宽(Mbps)
      en: EIP Bandwidth (Mbps)
    Description:
      zh-cn: 弹性公网IP的带宽上限,取值范围1~1000 Mbps
      en: EIP bandwidth cap, range 1-1000 Mbps
    Default: 10
    MinValue: 1
    MaxValue: 1000

Resources:
  # === 基础网络层 ===
  Vpc:
    Type: ALIYUN::ECS::VPC
    Properties:
      CidrBlock:
        Ref: VpcCidrBlock
      VpcName:
        Ref: ALIYUN::StackName
  VSwitch:
    Type: ALIYUN::ECS::VSwitch
    Properties:
      VSwitchName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc
      ZoneId:
        Ref: ZoneId
      CidrBlock:
        Ref: VSwitchCidrBlock
  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc
      SecurityGroupIngress:
        - PortRange: 80/80
          Priority: 1
          SourceCidrIp: 0.0.0.0/0
          IpProtocol: tcp
          NicType: internet
      SecurityGroupEgress:
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: internet
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          DestCidrIp: 0.0.0.0/0
          NicType: intranet

  # === 计算层 ===
  EcsInstanceGroup:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      InstanceChargeType:
        Ref: PayType
      PeriodUnit:
        Ref: PayPeriodUnit
      Period:
        Ref: PayPeriod
      IoOptimized: optimized
      SystemDiskCategory:
        Ref: SystemDiskCategory
      SystemDiskSize:
        Ref: SystemDiskSize
      DiskMappings:
        - Category:
            Ref: DataDiskCategory
          Size:
            Ref: DataDiskSize
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitch
      MaxAmount: 2
      ImageId: centos_7
      InstanceType:
        Ref: EcsInstanceType
      Password:
        Ref: InstancePassword
      AllocatePublicIP: false
  RunSetup:
    Type: ALIYUN::ECS::RunCommand
    DependsOn: EcsInstanceGroup
    Properties:
      InstanceIds:
        Fn::GetAtt:
          - EcsInstanceGroup
          - InstanceIds
      Type: RunShellScript
      Sync: true
      Timeout: 300
      ContentEncoding: PlainText
      CommandContent: |
        #!/bin/bash
        # === 数据盘初始化:分区、格式化、挂载到/disk1 ===
        cat >> /root/InitDataDisk.sh << 'EOF'
        #!/bin/bash
        echo "p
        n
        p
        w
        " |  fdisk -u /dev/vdb
        EOF
        /bin/bash /root/InitDataDisk.sh
        rm -f /root/InitDataDisk.sh
        mkfs -t ext4 /dev/vdb1
        cp /etc/fstab /etc/fstab.bak
        mkdir /disk1
        echo `blkid /dev/vdb1 | awk '{print $2}' | sed 's/\"//g'` /disk1 ext4 defaults 0 0 >> /etc/fstab
        mount -a

        # === 安装并启动Nginx ===
        yum install -y nginx
        systemctl start nginx.service

  # === 负载均衡层 ===
  Slb:
    Type: ALIYUN::SLB::LoadBalancer
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch
      LoadBalancerName:
        Fn::Sub: slb-${ALIYUN::StackName}
      PayType:
        Ref: PayType
      PricingCycle:
        Ref: PayPeriodUnit
      Duration:
        Ref: PayPeriod
      AddressType: intranet
      LoadBalancerSpec:
        Ref: LoadBalancerSpec
      AutoPay: true
  EipSlbAddress:
    Type: ALIYUN::VPC::EIP
    Properties:
      Name:
        Ref: ALIYUN::StackName
      InternetChargeType: PayByTraffic
      Bandwidth:
        Ref: Bandwidth
  EipSlbAddressAssociation:
    Type: ALIYUN::VPC::EIPAssociation
    Properties:
      InstanceId:
        Ref: Slb
      AllocationId:
        Ref: EipSlbAddress
  SlbBackendServerAttachment:
    DependsOn:
      - EcsInstanceGroup
    Type: ALIYUN::SLB::BackendServerAttachment
    Properties:
      BackendServerList:
        Fn::GetAtt:
          - EcsInstanceGroup
          - InstanceIds
      LoadBalancerId:
        Ref: Slb
      BackendServerWeightList:
        - 100
        - 100
  SlbListener:
    DependsOn:
      - Slb
    Type: ALIYUN::SLB::Listener
    Properties:
      LoadBalancerId:
        Ref: Slb
      ListenerPort: 80
      BackendServerPort: 80
      Protocol: tcp
      Bandwidth: -1
      Persistence:
        StickySession: 'on'
        StickySessionType: insert
        CookieTimeout: 60
        PersistenceTimeout: 180
      HealthCheck:
        HealthCheckType: tcp
        Port: 80
        Interval: 2
        HealthyThreshold: 3
        UnhealthyThreshold: 3
        Timeout: 5

Outputs:
  Endpoint:
    Description:
      zh-cn: 对外暴露的公网访问地址
      en: Public HTTP endpoint
    Value:
      Fn::Sub:
        - http://${ServerAddress}
        - ServerAddress:
            Fn::GetAtt:
              - EipSlbAddress
              - EipAddress

# === 元数据:控制台参数分组配置 ===
Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - ZoneId
          - VpcCidrBlock
          - VSwitchCidrBlock
        Label:
          default:
            zh-cn: 基础网络配置
            en: Network Configuration
      - Parameters:
          - PayType
          - PayPeriodUnit
          - PayPeriod
        Label:
          default:
            zh-cn: 付费类型
            en: Billing Configuration
      - Parameters:
          - EcsInstanceType
          - SystemDiskCategory
          - SystemDiskSize
          - DataDiskCategory
          - DataDiskSize
          - InstancePassword
        Label:
          default:
            zh-cn: ECS实例配置
            en: ECS Instance Configuration
      - Parameters:
          - LoadBalancerSpec
          - Bandwidth
        Label:
          default:
            zh-cn: 负载均衡配置
            en: CLB Configuration

本模板使用的 ROS 内置函数速查

函数

语法示例

本模板中的用途

详细说明

Ref

Ref: MyVpc

引用参数值或资源主标识符

引用 Parameter 返回参数值;引用 Resource 返回其主标识符

Fn::GetAtt

Fn::GetAtt: [EcsInstanceGroup, InstanceIds]

获取 ECS 实例组的实例 ID 列表

获取资源创建后的输出属性(非主标识符)

Fn::Sub

Fn::Sub: slb-${ALIYUN::StackName}

拼接 CLB 名称

模板字符串中用 ${Var} 引用变量

Fn::Not + Fn::Equals

Fn::Not: Fn::Equals: [${PayType}, PostPaid]

条件判断:付费参数的条件显示

逻辑取反 + 相等比较,用于 Visible 条件

部署环节

部署参数

必需输入参数(部署时需填写)

参数名

类型

说明

约束

ZoneId

String

可用区 ID

控制台动态选择

EcsInstanceType

String

ECS 实例规格

根据可用区+付费类型自动过滤

SystemDiskCategory

String

系统盘类型

根据可用区+规格自动过滤

DataDiskCategory

String

数据盘类型

根据可用区+规格自动过滤

LoadBalancerSpec

String

CLB 实例规格

根据可用区自动过滤

可选配置参数(有默认值,可不填)

参数名

默认值

说明

VpcCidrBlock

192.168.0.0/16

VPC 网段地址范围

VSwitchCidrBlock

192.168.0.0/24

交换机子网网段

PayType

PostPaid

付费类型(按量/包年包月)

PayPeriodUnit

Month

购买时长单位(仅 PrePaid 时显示)

PayPeriod

1

购买时长(仅 PrePaid 时显示)

SystemDiskSize

40

系统盘大小(GB),范围 40~500

DataDiskSize

100

数据盘大小(GB),范围 20~32768

Bandwidth

10

EIP 带宽上限(Mbps),范围 1~1000

InstancePassword

ECS 实例登录密码,长度 8-30,需含大小写+数字+特殊字符中至少三种

部署方式

方式一:通过 ROS 控制台部署

  1. 登录资源编排控制台

  2. 在左侧导航栏选择资源栈 > 创建资源栈

  3. 选择选择已有模板 > 输入模板,将完整模板粘贴到编辑器中。

  4. 单击下一步,按参数分组填写各项配置参数。

  5. 确认配置后单击创建,等待资源栈状态变为 CREATE_COMPLETE

方式二:通过 ROS IaC Code 部署

IaC Code 是面向云基础设施的 AI 基础设施即代码助手,通过自然语言提示词生成、部署和管理基础设施模板。架构设计面向多云工作流。以下为本方案的参考提示词:

# Prompt
帮我部署一组ECS实例并挂载到CLB负载均衡器上,要求:
1.使用新建的VPC和VSwitch
2.创建2台ECS实例,通过CommandContent安装并启动Nginx
3.使用WaitCondition等待Nginx安装完成后再挂载到CLB
4.CLB配置TCP 80端口监听和健康检查
5.创建EIP绑定到CLB,对外提供HTTP访问
6.安全组开放入方向80端口
7.ECS配置100GB数据盘并在CommandContent中自动分区挂载
8.ZoneId、EcsInstanceType、SystemDiskCategory、DataDiskCategory、LoadBalancerSpec都使用AssociationProperty配置成控制台动态筛选
9.付费类型支持按量和包年包月切换,包年包月参数使用条件显示

常见问题

Q1:CLB 健康检查一直失败,后端 ECS 显示异常

原因:ECS 上的 Nginx 服务未正常启动,或安全组未开放 80 端口。

排查步骤

  1. 登录 ECS执行 systemctl status nginx 确认 Nginx 正在运行。

  2. 确认安全组入站规则已开放 80 端口(PortRange: 80/80)。

  3. 检查 CLB 健康检查配置的 Port 是否与 Nginx 监听端口一致。

  4. 适当增大 HealthyThreshold(健康阈值)和 Interval(检查间隔)。

Q2:如何调整后端服务器的流量分配比例?

方案:修改 SlbBackendServerAttachmentBackendServerWeightList

BackendServerWeightList:
  - 100  # 第1台ECS:接收约67%流量
  - 50   # 第2台ECS:接收约33%流量

权重比为 100:50,即第 1 台处理约 2/3 的请求。如果需要某台 ECS 暂停服务(灰度下线),将其权重设为 0 即可。

Q3:如何将 ECS::RunCommand 中的 Nginx 部署脚本替换为自定义应用?

方案:修改 CommandContent 脚本中"安装并启动"部分,保留数据盘初始化逻辑:

CommandContent:
  Fn::Sub:
    - |
      #!/bin/bash
      # ... 数据盘初始化代码(保持不变)...

      # === 替换为你的应用部署脚本 ===
      # 例如:部署Java SpringBoot应用
      yum install -y java-11-openjdk
      wget -P /disk1 https://your-oss-bucket.oss-cn-hangzhou.aliyuncs.com/app.jar
      nohup java -jar /disk1/app.jar --server.port=80

Q4:如何将 CLB 替换为 ALB(应用型负载均衡)?

改造要点

  1. ALIYUN::SLB::LoadBalancer 替换为 ALIYUN::ALB::LoadBalancer

  2. 使用 ALIYUN::ALB::ServerGroup 创建服务器组并添加后端 ECS。

  3. 使用 ALIYUN::ALB::Listener + ALIYUN::ALB::Rule 配置七层 HTTP/HTTPS 路由。

  4. ALB 原生支持公网,无需额外绑定 EIP。

Q5:如何使用已有 VPC 而非新建?

方案:将 VPC 和 VSwitch 从 Resources 中移除,改为Parameters传入:

Parameters:
  ExistingVpcId:
    Type: String
    Label:
      zh-cn: 已有VPC ID
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
  ExistingVSwitchId:
    Type: String
    Label:
      zh-cn: 已有交换机ID
    AssociationProperty: ALIYUN::VPC::VSwitch::VSwitchId
    AssociationPropertyMetadata:
      VpcId: ${ExistingVpcId}

了解更多资源部署问题,可以查询常见问题合集