使用云服务器ECS连接云数据库RDS完成数据初始化

更新时间:
复制 MD 格式

本文介绍如何使用阿里云资源编排服务 ROS 通过 YAML 模板,一次性自动创建完整的云基础设施并完成数据库初始化。适用于需要快速、可重复地搭建 ECS+RDS 环境的场景。

方案概述

业务场景

在阿里云专有网络(VPC)中创建一台 ECS 云服务器和一个 RDS MySQL 数据库实例,ECS 通过 VPC 内网连接 RDS,并利用云助手(RunCommand)在 ECS 上自动执行 SQL 脚本完成数据库数据初始化。

创建的资源清单

序号

资源名称

ROS 资源类型

用途说明

1

专有网络 VPC

ALIYUN::ECS::VPC

提供隔离的网络环境,所有资源部署在同一 VPC 内。

2

交换机 VSwitch

ALIYUN::ECS::VSwitch

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

3

安全组 SecurityGroup

ALIYUN::ECS::SecurityGroup

控制 ECS 的网络访问规则(入站/出站)。

4

ECS 云服务器实例

ALIYUN::ECS::Instance

运行数据初始化脚本的计算节点。

5

RDS MySQL 实例

ALIYUN::RDS::DBInstance

目标数据库,存储初始化数据。

6

数据库账号

ALIYUN::RDS::Account

RDS 登录账号,供 ECS 连接数据库使用。

7

云助手命令

ALIYUN::ECS::RunCommand

在 ECS 上远程执行 Shell 脚本,完成数据导入。

部署完成后获得的结果

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

  • 一个完整的 VPC 网络环境(包含 VPC、交换机、安全组)。

  • 一台 ECS 云服务器实例(已配置网络和安全组)。

  • 一个 RDS MySQL 8.0 数据库实例(已创建数据库和超级账号)。

  • 数据库中已自动导入 MySQL 官方 employees 测试数据集(约 30 万条记录)。

架构图

image

前提条件

在使用本方案前,请确认以下条件:

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

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

模板编写教程

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

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

  • 阶段二(进阶版):参数化所有可变配置,添加动态参数筛选和参数分组。

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

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

网络资源是所有其他资源的基础,需要最先创建。以下示例定义了 VpcVSwitchEcsSecurityGroup 三个基础网络资源:

Resources:
  Vpc:
    Type: ALIYUN::ECS::VPC  # 创建专有网络
    Properties:
      CidrBlock: 192.168.0.0/16  # VPC 地址段,可容纳 65534 个内网 IP
      VpcName:
        Ref: ALIYUN::StackName  # 伪参数:使用资源栈名称作为 VPC 名称

  VSwitch:
    Type: ALIYUN::ECS::VSwitch  # 在 VPC 中创建交换机(子网)
    Properties:
      VSwitchName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc  # Ref 引用资源:返回 Vpc 的 VpcId(隐式依赖,ROS 会先创建 Vpc)
      ZoneId: cn-beijing-h  # 此场景以北京 H可用区为示例
      CidrBlock: 192.168.0.0/24  # 子网地址段,必须是 VPC 地址段的子集

  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup  # 创建安全组
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc  # 安全组绑定到 VPC
      SecurityGroupIngress:  # 入站规则:允许所有入站流量,可根据业务实际需求调整
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          SourceCidrIp: 0.0.0.0/0
          NicType: intranet

关键知识点:

  • VpcNameVSwitchNameSecurityGroupName 等自定义名称使用伪参数 ALIYUN::StackName,部署后可通过资源栈名称快速识别相关资源。

  • 安全组的访问规则可按业务需求自定义,如:

    • 需要在外部访问 Web 服务,可开启入方向 HTTP 80/8080 端口。

    • 需要通过 SSH 登录服务器,可开启入方向 SSH 22 端口。

Step 2:定义数据库资源(RDS 实例 + 数据库账号

以下示例定义 DBInstanceAccount

Resources:
  DBInstance:
    Type: ALIYUN::RDS::DBInstance  # 创建 RDS MYSQL 数据库实例
    Properties:
      ZoneId: cn-beijing-h
      VpcId:
        Ref: Vpc  # 将 RDS 部署在同一 VPC 中(与 ECS 内网互通的关键)
      VSwitchId:
        Ref: VSwitch # 指定交换机,确保与 ECS 在同一子网
      Engine: MySQL  # 数据库引擎类型
      EngineVersion: '8.0'  # MYSQL版本
      DBInstanceClass: mysql.n2e.medium.1  # 实例规格(2 核 4 GB)
      DBInstanceStorage: 10  # 存储空间 10 GB
      MultiAZ: false
      DBInstanceNetType: Intranet  # 内网类型(VPC 网络)
      DBMappings:  # 创建初始数据库
        - CharacterSetName: utf8  # 字符集
          DBName: employees  # 数据库名称
      SecurityIPList: 0.0.0.0/0  # RDS 白名单(允许 VPC 内所有 IP 连接)

  Account:
    Type: ALIYUN::RDS::Account  # 创建 RDS 数据库账号
    DependsOn:
      - DBInstance
    Properties:
      DBInstanceId:
        # Fn::GetAtt 获取资源的输出属性(非主标识符的其他属性)
        Fn::GetAtt:
          - DBInstance  # 资源逻辑名
          - DBInstanceId  # 要获取的属性名
      AccountPassword: Admin@2791
      AccountType: Super  # 超级账号(拥有所有数据库权限)
      AccountName: rdsuser  # 账号名称

关键知识点:

  • RefFn::GetAtt 的区别:

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

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

Step 3:定义 ECS 实例 相关资源

以下示例定义 EcsInstanceInstanceRunCommand

Resources:
  EcsInstance:
    Type: ALIYUN::ECS::Instance  # 创建 ECS 云服务器
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitch  # 与 RDS 部署在同一交换机,确保内网互通
      ImageId: centos_7  # 操作系统镜像: CentOS 7
      AllocatePublicIP: true  # 开启公网 IP
      InstanceType: ecs.c5.large 
      SystemDiskSize: 40
      SystemDiskCategory: cloud_essd  # ESSD 云盘
      Password: ******

  InstanceRunCommand:
    Type: ALIYUN::ECS::RunCommand  # 云助手: 在 ECS 上远程执行命令
    DependsOn:
      - Account  # 显式依赖:等数据库账号创建完毕后再连接
    Properties:
      CommandContent:
        # Fn::Sub 函数:字符串变量替换
        # 语法:Fn::Sub: [模板字符串, {变量名: 变量值}]
        # 模板字符串中使用 ${变量名} 引用变量
        Fn::Sub:
          - |
            #!/bin/bash
            # 1. 安装 MYSQL 客服端和解压工具
            yum -y install holland-mysqldump.noarch unzip
            # 2. 从 OSS 下载 MYSQL 官方测试数据集
            wget -P /tmp https://ros-userdata-resources.oss-cn-beijing.aliyuncs.com/MySQL/test_db-master.zip
            # 3. 解压数据文件
            unzip /tmp/test_db-master.zip -d /tmp/
            # 4. 通过 RDS 内网地址连接数据库并执行 SQL 导入
            mysql -h${DBConnectString} -p3306 -urdsuser -pAdmin@2791 < /tmp/test_db-master/employees.sql
          - DBConnectString:
              # 获取RDS实例的内网连接地址(如:rm-xxx.mysql.rds.aliyuncs.com)
              Fn::GetAtt:
                - DBInstance
                - InnerConnectionString  # RDS 实例创建后自动生成的 VPC 内网连接域名
      Type: RunShellScript  # 命令类型: Shell 脚本
      InstanceIds:  # 目标 ECS 实例列表
        - Fn::GetAtt:
            - EcsInstance
            - InstanceId
      Timeout: '500'  # 命令执行超市时间:500 秒

关键知识点:

  • InnerConnectionString 是 RDS 实例创建后自动生成的 VPC 内网连接域名。

  • AllocatePublicIP: false 时 ECS 无公网 IP,如需从公网下载文件,需确保 VPC 配置了 NAT 网关或将其改为 true

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

说明

本示例中的初始化数据来自 MySQL 官方提供的 employees 测试数据集。为保证下载稳定性,建议将数据文件提前存放至 OSS Bucket 中,并替换 wget 的 URL 地址。

基础版完整模板

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

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 创建VPC网络环境,部署ECS和RDS MySQL实例,通过云助手自动连接RDS并导入测试数据
  en: Create VPC network, deploy ECS and RDS MySQL instances, auto-initialize database via RunCommand
Parameters:
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: '-1/-1'
          Priority: 1
          IpProtocol: all
          SourceCidrIp: 0.0.0.0/0
          NicType: intranet

  # === 数据库层 ===
  DBInstance:
    Type: ALIYUN::RDS::DBInstance
    Properties:
      ZoneId: cn-beijing-h
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch
      Engine: MySQL
      EngineVersion: '8.0'
      DBInstanceClass: mysql.n2e.medium.1
      DBInstanceStorage: 200
      MultiAZ: false
      DBInstanceNetType: Intranet
      DBMappings:
        - CharacterSetName: utf8
          DBName: employees
      SecurityIPList: 0.0.0.0/0

  Account:
    Type: ALIYUN::RDS::Account
    DependsOn:
      - DBInstance
    Properties:
      DBInstanceId:
        Fn::GetAtt:
          - DBInstance
          - DBInstanceId
      AccountPassword: Admin@2791
      AccountType: Super
      AccountName: rdsuser

  # === 计算层 + 初始化 ===
  EcsInstance:
    Type: ALIYUN::ECS::Instance
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitch
      ImageId: centos_7
      AllocatePublicIP: true
      InternetMaxBandwidthOut: 5
      InternetChargeType: PayByTraffic
      InstanceType: ecs.c5.large
      SystemDiskSize: 40
      SystemDiskCategory: cloud_essd
      Password: ******

  InstanceRunCommand:
    Type: ALIYUN::ECS::RunCommand
    DependsOn:
      - Account
    Properties:
      CommandContent:
        Fn::Sub:
          - |
            #!/bin/bash
            yum -y install holland-mysqldump.noarch unzip
            wget -P /tmp https://ros-userdata-resources.oss-cn-beijing.aliyuncs.com/MySQL/test_db-master.zip
            unzip /tmp/test_db-master.zip -d /tmp/
            mysql -h${DBConnectString} -p3306 -urdsuser -pAdmin@2791 < /tmp/test_db-master/employees.sql
          - DBConnectString:
              Fn::GetAtt:
                - DBInstance
                - InnerConnectionString
      Type: RunShellScript
      Sync: true
      InstanceIds:
        - Fn::GetAtt:
            - EcsInstance
            - InstanceId
      Timeout: '500'

Outputs:
  RDSInnerConnectionString:
    Description: RDS 内网连接地址
    Label: RDS 内网连接地址
    Value:
      Fn::GetAtt:
        - DBInstance
        - InnerConnectionString
  RDSPort:
    Description: RDS 端口
    Label: RDS 端口
    Value:
      Fn::GetAtt:
        - DBInstance
        - InnerPort
  ECSPrivateIp:
    Description: ECS 内网 IP
    Label: ECS 内网 IP
    Value:
      Fn::GetAtt:
        - EcsInstance
        - PrivateIp
  ECSPublicIp:
    Description: ECS 公网 IP
    Label: ECS 公网 IP
    Value:
      Fn::GetAtt:
        - EcsInstance
        - PublicIp

关键知识点与思考:

  • 模板创建完资源后,可通过 Outputs 直接查询资源的内部属性,例如 RDS 内网连接地址、RDS 端口、ECS 内网 IP、ECS 公网 IP 等。

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

基础版模板中,ECS 的 InstanceTypeSystemDiskCategory 和 RDS 的 DBInstanceClass 等属性使用了固定值。当需要在不同地域或不同规格下复用模板时,需要多次修改模板内容。而模板中多个参数之间往往存在依赖关系:ECS 实例规格受限于可用区(不同可用区有不同规格库存),系统盘类型又同时受限于可用区和实例规格。如果手动填写这些参数,很容易选到不可用的组合,导致部署失败。

通过以下优化,可以大幅提高模板的灵活性和可复用性:

  1. 参数化(Parameters:将可变配置抽取为参数,部署时动态填写。

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

  3. 参数分组(Metadata:在控制台上按逻辑分组展示参数,提升填写体验。

参数依赖关系

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

VSwitchZoneId(可用区)  ← 基础参数,无前置依赖
    │
    ├──→ ECSInstanceType(ECS实例规格)
    │        │             依赖:ZoneId
    │        │
    │        └──→ ECSDiskCategory(系统盘类型)
    │                           依赖:ZoneId + InstanceType
    │
    └──→ DBInstanceClass(RDS实例规格)
                     依赖:ZoneId + Engine(固定值)

核心思路:先选可用区,再据此筛选 ECS 规格和 RDS 规格,最后根据可用区 + ECS 规格筛选磁盘类型。每一步都只展示当前条件下可用的选项,避免无效组合。

AssociationProperty 详解

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

AssociationProperty 设为 ALIYUN::ECS::ZoneId时,控制台将自动列出当前地域下所有可用区。选择后,其他参数的选项列表会随之更新。

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

2. ECSInstanceType — ECS 实例规格

AssociationProperty 设为 ALIYUN::ECS::Instance::InstanceType,并通过 AssociationPropertyMetadata.ZoneId 关联 ${VSwitchZoneId},筛选对应可用区下可用的规格。不同可用区的实例规格库存不同,不过滤则可能选到无货规格导致部署失败。

ECSInstanceType:
  Type: String
  Label:
    zh-cn: ECS实例规格
    en: ECS Instance Type
  Description:
    zh-cn: 选择ECS实例规格。列表已根据可用区自动过滤可用规格。
    en: Select ECS instance type. List is filtered by selected availability zone.
  AssociationProperty: ALIYUN::ECS::Instance::InstanceType
  AssociationPropertyMetadata:
    ZoneId: ${VSwitchZoneId}

3. ECSDiskCategory — 系统盘类型

AssociationProperty 设为 ALIYUN::ECS::Disk::SystemDiskCategory,同时关联 ${VSwitchZoneId}${ECSInstanceType},过滤出对应可用区与实例规格共同支持的磁盘类型。系统盘类型的可用性同时取决于可用区(某些可用区不支持 ESSD)和实例规格(某些规格仅支持特定磁盘类型)。

ECSDiskCategory:
  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: ${VSwitchZoneId}
    InstanceType: ${ECSInstanceType}

4. DBInstanceClass — RDS 实例规格

AssociationProperty 设为 ALIYUN::RDS::Instance::InstanceType,关联 ${VSwitchZoneId} 和固定引擎类型 MySQL,过滤出对应可用区下支持 MySQL 的 RDS 实例规格。如果需要用户自选引擎,可新增 Engine 参数(AssociationProperty: ALIYUN::RDS::Engine::EngineId)再在此引用 ${Engine}

DBInstanceClass:
  Type: String
  Label:
    zh-cn: RDS实例规格
    en: RDS Instance Class
  Description:
    zh-cn: 选择RDS实例规格。列表已根据数据库引擎和可用区自动过滤。
    en: Select RDS instance class, filtered by engine type and zone.
  AssociationProperty: ALIYUN::RDS::Instance::InstanceType
  AssociationPropertyMetadata:
    Engine: MySQL
    ZoneId: ${VSwitchZoneId}
    EngineVersion: '8.0'
    Category: Basic
    InstanceChargeType: Postpaid

动态参数筛选模板示例:

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

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

  ECSDiskCategory:
    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: ${VSwitchZoneId}
      InstanceType: ${ECSInstanceType}

  DBInstanceClass:
    Type: String
    Label:
      zh-cn: RDS实例规格
      en: RDS Instance Class
    Description:
      zh-cn: 选择RDS实例规格。列表已根据数据库引擎和可用区自动过滤。
      en: Select RDS instance class, filtered by engine type and zone.
    AssociationProperty: ALIYUN::RDS::Instance::InstanceType
    AssociationPropertyMetadata:
      Engine: MySQL
      ZoneId: ${VSwitchZoneId}

AssociationProperty 工作原理总结

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

  1. 选择可用区(VSwitchZoneId)。

  2. ECS 实例规格下拉框自动刷新,仅显示该可用区有库存的规格。

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

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

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

Metadata 参数分组

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

Metadata 语法结构:

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

语法规则:

  • ParameterGroupsParametersLabel 都是必填项。

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

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

本方案的分组设计:

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

分组

包含参数

基础网络配置

交换机可用区 VSwitchZoneId、VPC 网段 VpcCidrBlock、交换机网段 VSwitchCidrBlock

ECS 实例配置

ECS 实例规格 ECSInstanceType、系统盘大小 ECSDiskSize、系统盘类型 ECSDiskCategory、ECS 实例密码EcsInstancePassword

数据库配置

RDS 实例规格DBInstanceClass、RDS 存储空间 DBInstanceStorage、数据库名称 DBName、数据库账号名称 DBUsername、数据库密码 DBPassword

MetaData分组模板示例:

Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - VSwitchZoneId
          - VpcCidrBlock
          - VSwitchCidrBlock
        Label:
          default:
            zh-cn: 基础网络配置
            en: Network Configuration
      - Parameters:
          - ECSInstanceType
          - ECSDiskSize
          - ECSDiskCategory
          - EcsInstancePassword
        Label:
          default:
            zh-cn: ECS实例配置
            en: ECS Instance Configuration
      - Parameters:
          - DBInstanceClass
          - DBInstanceStorage
          - DBName
          - DBUsername
          - DBPassword
        Label:
          default:
            zh-cn: 数据库配置
            en: Database Configuration

进阶版完整模板

ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: >-
    参数化模板:在VPC中创建ECS和RDS MySQL实例,通过云助手自动导入数据库测试数据。
    支持动态选择可用区、实例规格、磁盘类型,适用于多地域复用。
  en: >-
    Parameterized template: Create ECS and RDS MySQL in VPC, auto-import test data via RunCommand.
    Supports dynamic selection of zone, instance type, and disk category.

Parameters:
  # ─── 基础网络参数 ───
  VSwitchZoneId:
    Type: String
    Label:
      zh-cn: 交换机可用区
      en: VSwitch Availability Zone
    Description:
      zh-cn: 选择交换机所在的可用区,ECS和RDS将部署在此可用区
      en: Select the availability zone for VSwitch, ECS and RDS will be deployed here
    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. Recommended 10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16
    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 and not overlap with other VSwitches
    Default: 192.168.0.0/24

  # ─── ECS实例参数 ───
  ECSInstanceType:
    Type: String
    Label:
      zh-cn: ECS实例规格
      en: ECS Instance Type
    Description:
      zh-cn: 选择ECS实例规格。列表已根据可用区自动过滤可用规格。
      en: Select ECS instance type. List is filtered by selected availability zone.
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ${VSwitchZoneId}

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

  ECSDiskCategory:
    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: ${VSwitchZoneId}
      InstanceType: ${ECSInstanceType}

  EcsInstancePassword:
    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 of uppercase, lowercase, digits, special characters
    MinLength: 8
    MaxLength: 30

  # ─── 数据库参数 ───
  DBInstanceClass:
    Type: String
    Label:
      zh-cn: RDS实例规格
      en: RDS Instance Class
    Description:
      zh-cn: 选择RDS实例规格。列表已根据数据库引擎和可用区自动过滤。
      en: Select RDS instance class, filtered by engine type and zone.
    AssociationProperty: ALIYUN::RDS::Instance::InstanceType
    AssociationPropertyMetadata:
      Engine: MySQL
      ZoneId: ${VSwitchZoneId}
      EngineVersion: '8.0'
      Category: Basic
      InstanceChargeType: Postpaid
  DBInstanceStorage:
    Type: Number
    Label:
      zh-cn: RDS存储空间(GB)
      en: RDS Storage (GB)
    Description:
      zh-cn: RDS实例存储空间,范围20~2000 GB,步长为5
      en: RDS storage size, range 20-2000 GB, increment by 5
    Default: 200
    MinValue: 20
    MaxValue: 2000

  DBName:
    Type: String
    Label:
      zh-cn: 数据库名称
      en: Database Name
    Description:
      zh-cn: 初始创建的数据库名称,必须以字母开头,只包含字母和数字
      en: Initial database name, must start with letter, alphanumeric only
    Default: employees
    MinLength: 1
    MaxLength: 64

  DBUsername:
    Type: String
    Label:
      zh-cn: 数据库账号名称
      en: Database Username
    Description:
      zh-cn: RDS主账号名称,2-16个小写字母,必须以字母开头
      en: RDS primary account name, 2-16 lowercase letters, must start with letter
    Default: rdsuser
    MinLength: 2
    MaxLength: 16

  DBPassword:
    Type: String
    NoEcho: true
    Label:
      zh-cn: 数据库密码
      en: Database Password
    Description:
      zh-cn: RDS数据库用户的访问密码
      en: RDS database user password

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: VSwitchZoneId
      CidrBlock:
        Ref: VSwitchCidrBlock

  EcsSecurityGroup:
    Type: ALIYUN::ECS::SecurityGroup
    Properties:
      SecurityGroupName:
        Ref: ALIYUN::StackName
      VpcId:
        Ref: Vpc
      SecurityGroupIngress:
        - PortRange: '-1/-1'
          Priority: 1
          IpProtocol: all
          NicType: intranet
          SourceCidrIp: '0.0.0.0/0'

  # === 数据库层 ===
  DBInstance:
    Type: ALIYUN::RDS::DBInstance
    Properties:
      VpcId:
        Ref: Vpc
      VSwitchId:
        Ref: VSwitch
      Engine: MySQL
      EngineVersion: '8.0'
      DBInstanceClass:
        Ref: DBInstanceClass
      DBInstanceStorage:
        Ref: DBInstanceStorage
      DBInstanceNetType: Intranet
      DBMappings:
        - CharacterSetName: utf8
          DBName:
            Ref: DBName
      SecurityIPList: 0.0.0.0/0

  DBAccount:
    Type: ALIYUN::RDS::Account
    DependsOn:
      - DBInstance
    Properties:
      DBInstanceId:
        Fn::GetAtt:
          - DBInstance
          - DBInstanceId
      AccountPassword:
        Ref: DBPassword
      AccountType: Super
      AccountName:
        Ref: DBUsername

  # === 计算层 + 数据初始化 ===
  EcsInstance:
    Type: ALIYUN::ECS::Instance
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupId:
        Ref: EcsSecurityGroup
      VSwitchId:
        Ref: VSwitch
      ImageId: centos_7
      AllocatePublicIP: true  # 需要公网IP从OSS下载数据文件
      InstanceType:
        Ref: ECSInstanceType
      SystemDiskSize:
        Ref: ECSDiskSize
      SystemDiskCategory:
        Ref: ECSDiskCategory
      Password:
        Ref: EcsInstancePassword

  InstanceRunCommand:
    Type: ALIYUN::ECS::RunCommand
    DependsOn:
      - DBAccount  # 等待数据库账号就绪后再执行连接
    Properties:
      CommandContent:
        Fn::Sub:
          - |
            #!/bin/bash
            yum -y install holland-mysqldump.noarch unzip
            wget -P /tmp https://ros-userdata-resources.oss-cn-beijing.aliyuncs.com/MySQL/test_db-master.zip
            unzip /tmp/test_db-master.zip -d /tmp/
            mysql -h${DBConnectString} -p3306 -u${DBUsername} -p${DBPassword} < /tmp/test_db-master/employees.sql
          - DBConnectString:
              Fn::GetAtt:
                - DBInstance
                - InnerConnectionString
            DBUsername:
              Ref: DBUsername
            DBPassword:
              Ref: DBPassword
      Type: RunShellScript
      InstanceIds:
        - Fn::GetAtt:
            - EcsInstance
            - InstanceId
      Timeout: '500'
Outputs:
  RDSInnerConnectionString:
    Description: RDS 内网连接地址
    Label: RDS 内网连接地址
    Value:
      Fn::GetAtt:
        - DBInstance
        - InnerConnectionString
  RDSPort:
    Description: RDS 端口
    Label: RDS 端口
    Value:
      Fn::GetAtt:
        - DBInstance
        - InnerPort
  ECSPrivateIp:
    Description: ECS 内网 IP
    Label: ECS 内网 IP
    Value:
      Fn::GetAtt:
        - EcsInstance
        - PrivateIp
  ECSPublicIp:
    Description: ECS 公网 IP
    Label: ECS 公网 IP
    Value:
      Fn::GetAtt:
        - EcsInstance
        - PublicIp
# === 元数据:控制台参数分组配置 ===
Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - VSwitchZoneId
          - VpcCidrBlock
          - VSwitchCidrBlock
        Label:
          default:
            zh-cn: 基础网络配置
            en: Network Configuration
      - Parameters:
          - ECSInstanceType
          - ECSDiskSize
          - ECSDiskCategory
          - EcsInstancePassword
        Label:
          default:
            zh-cn: ECS实例配置
            en: ECS Instance Configuration
      - Parameters:
          - DBInstanceClass
          - DBInstanceStorage
          - DBName
          - DBUsername
          - DBPassword
        Label:
          default:
            zh-cn: 数据库配置
            en: Database Configuration

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

函数

语法示例

本模板中的用途

详细说明

Ref

Ref: MyVpc

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

引用 Parameter 返回参数值;引用 Resource 返回其主 ID。

Fn::GetAtt

Fn::GetAtt: [DBInstance, InnerConnectionString]

获取 RDS 内网连接地址。

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

Fn::Sub

Fn::Sub: [字符串, {变量映射}]

拼接 Shell 命令中的数据库连接信息。

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

部署环节

部署参数

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

参数名

类型

说明

约束

DBPassword

String

RDS 数据库用户密码。

按 RDS 密码策略设置。

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

参数名

默认值

说明

VpcCidrBlock

192.168.0.0/16

VPC 网段地址范围。

VSwitchCidrBlock

192.168.0.0/24

交换机子网网段。

VSwitchZoneId

可用区 ID(控制台动态选择)。

ECSInstanceType

ECS 实例规格(控制台动态筛选可用规格)。

ECSDiskCategory

cloud_essd

ECS 系统盘类型。

ECSDiskSize

40

ECS 系统盘大小(GiB),范围 40~500。

EcsInstancePassword

ECS 实例登录密码,长度 8~30,需包含大写字母、小写字母、数字、特殊字符中的至少三种。

DBInstanceClass

RDS 实例规格(控制台动态筛选)。

DBInstanceStorage

200

RDS 存储空间(GB),范围 20~2000。

DBName

employees

初始化的数据库名称。

DBUsername

rdsuser

数据库账号名(2~16 位小写字母)。

部署方式

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

  1. 登录资源编排控制台

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

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

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

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

方式二:通过 IaC Code 部署

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

帮我部署一台ECS和RDS MySQL,并且要求通过云助手命令进行RDS数据初始化,初始化数据的下载地址为:https://ros-userdata-resources.oss-cn-beijing.aliyuncs.com/MySQL/test_db-master.zip
要求:
1. ECS使用新建的VPC和VSwitch。
2. ECS安全组开放入方向22、3306端口。
3. 新建RDS超级账户,并使用该账户进行RDS数据初始化。
4. ECS需要开启公网IP。
5. VpcCidrBlock、VSwitchZoneId、VSwitchCidrBlock、ECSInstanceType、ECSDiskCategory都需要使用AssociationProperty和AssociationPropertyMetadata配置成控制台动态筛选方式。

常见问题

Q1:部署失败,报错 "The specified InstanceType is not available in the zone"

原因:所选 ECS 实例规格在指定可用区中没有库存。

解决方案

  • 在进阶版模板中,AssociationProperty 会自动过滤可用规格,避免此问题。

  • 如果使用基础版模板,请前往 云服务器ECS定价确认目标可用区的规格库存,或更换可用区。

Q2:云助手命令执行超时(RunCommand Timeout)

原因:数据文件下载慢或 SQL 导入时间超过设定的 Timeout 值。

解决方案

  1. 增大模板中 Timeout 的值(例如改为 '600' 或更大)。

  2. 确保 ECS 能访问公网下载文件(AllocatePublicIP: true 或配置 NAT 网关)。

  3. 将数据文件存放到与 ECS 同地域的 OSS Bucket 中,使用内网 endpoint 下载。

Q3:ECS 无法连接 RDS,报错 "Can't connect to MySQL server"

排查步骤

  1. 确认 ECS 和 RDS 是否在同一 VPC、同一交换机(模板中已确保)。

  2. 检查 RDS 白名单(SecurityIPList)是否包含 ECS 内网 IP 段或设置为 0.0.0.0/0

  3. 确认 RDS 实例状态为运行中(DependsOn: Account 已确保 RDS 就绪后再执行命令)。

  4. 检查安全组规则是否允许 3306 端口出站。

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

VPCVSwitchResources 中移除,改为通过 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}

Q5:如何将本模板改为使用 PostgreSQL?

改造要点:

  1. 修改 RDS 资源的 Engine: PostgreSQLEngineVersion: '16.0'

  2. DBInstanceClass 改为 PostgreSQL 对应的规格(如 pg.n4.medium.2c)。

  3. RunCommand 中的 mysql 命令替换为 psql 命令。

  4. 调整数据初始化 SQL 文件为 PostgreSQL 兼容格式。

想了解更多资源部署问题,请参见常见问题合集