资源编排服务ROS支持ALIYUN::ROS::WaitCondition与ALIYUN::ROS::WaitConditionHandle资源,在创建ECS实例或执行云助手指令时运行UserData自定义脚本,通过信号通知完成对自定义脚本运行状态和执行结果的判断。

使用WaitCondition与WaitConditionHandle进行单次信号通知

当在ECS实例中安装Nginx服务时,您可以在ROS模板中定义ALIYUN::ECS::RunCommandALIYUN::ROS::WaitConditionALIYUN::ROS::WaitConditionHandle资源,实现单次发送并接收信号。

ROS模板
ROSTemplateFormatVersion: '2015-09-01'
Description: ''
Parameters: { }
Resources:
  InstallNginx:
    Type: ALIYUN::ECS::RunCommand
    Properties:
      Timeout: 60
      Name: InstallNginxScript
      CommandContent:
        Fn::Sub:
          - |
            #!/bin/sh
            yum install -y nginx
            systemctl restart nginx
            if [[ $? -eq 0 ]];
            then
                 ${ros-notify} -d "{\"status\" : \"SUCCESS\"}"
            else
                 ${ros-notify} -d "{\"status\" : \"FAILURE\"}"
            fi
          - ros-notify:
              Fn::GetAtt:
                - InstallNginxWaitConditionHandle
                - CurlCli
      Type: RunShellScript
      InstanceIds:
        - i-wz995r4yn8njthoq****
  InstallNginxWaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Handle:
        Ref: InstallNginxWaitConditionHandle
      Timeout: 60
  InstallNginxWaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
Outputs: { }
Metadata: { }
模板逻辑:
  1. 在ECS实例中运行安装Nginx服务的Shell脚本。
  2. 通过Fn::GetAtt获取ALIYUN::ROS::WaitConditionHandle中的返回值CurlCli作为发送信号的命令。
    说明 您可以通过添加-Body {"status": ""}指定信号类型,status取值包括SUCCESSFAILUREWARNING
    如果出现以下情况,则资源栈操作失败。
    • 收到FAILURE信号。
    • 在设定时间内,收到的信号数量未满足要求。
    • 收到的信号数量满足了要求,且所有信号均为WARNING
  3. 通过Fn::Replace将ALIYUN::ROS::WaitConditionHandle中的CurlCli替换为云助手执行的自定义脚本中发送信号的变量ros-notify

    您可以使用变量ros-notify简化自定义脚本代码,发送Nginx服务安装成功或失败的信号。

您可以通过ROS控制台查看当Nginx服务安装失败时,ECS实例发送的失败信号:Resource CREATE failed: WaitConditionFailure: resources.InstallNginxWaitCondition: Signal 1 received001

使用WaitCondition与WaitConditionHandle进行多次信号通知

当在ECS实例中下载jdkmaven文件时,您可以在ROS模板中定义ALIYUN::ECS::RunCommandALIYUN::ROS::WaitConditionALIYUN::ROS::WaitConditionHandle资源,实现多次发送并接收信号。

ROS模板
ROSTemplateFormatVersion: '2015-09-01'
Description: ''
Parameters: {}
Resources:
  DownloadPkg:
    Type: ALIYUN::ECS::RunCommand
    Properties:
      Timeout: 60
      Name: DownloadPkgScript
      CommandContent:
           Fn::Sub:
              - |
                #!/bin/sh
                mkdir -p /home/java
                wget -P /home/java http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa8****/jdk-8u131-linux-x64.tar.gz
                ls -l /home/java/jdk-8u131-linux-x64.tar.gz
                if [[ $? -eq 0 ]];
                then
                     ros-notify -d "{\"id\" : \"DownloadJdk\", \"status\" : \"SUCCESS\", \"Data\" : \"JDK package download success\"}"
                else
                     ros-notify -d "{\"id\" : \"DownloadJdk\", \"status\" : \"FAILURE\", \"Data\" : \"JDK package download success\"}"
                fi
                wget -P /home/java https://downloads.apache.org/maven/maven-3/3.6.3/binaries/apache-maven-3.6.3-bin.tar.gz
                ls -l /home/java/apache-maven-3.6.3-bin.tar.gz
                if [[ $? -eq 0 ]];
                then
                     ${ros-notify} -d "{\"id\" : \"DownloadMaven\", \"status\" : \"SUCCESS\", \"Data\" : \"Maven package download success\"}"
                else
                     ${ros-notify} -d "{\"id\" : \"DownloadMaven\", \"status\" : \"FAILURE\", \"Data\" : \"Maven package download success\"}"
                fi
              - ros-notify:
                  Fn::GetAtt:
                    - DownloadPkgWaitConditionHandle
                    - CurlCli
      Type: RunShellScript
      InstanceIds:
        - i-wz995r4yn8njthoq****
  DownloadPkgWaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Count: 2
      Handle:
        Ref: DownloadPkgWaitConditionHandle
      Timeout: 60
  DownloadPkgWaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
    Properties:
      Count: 2
Outputs:
  DownloadJDKResult:
    Value:
      Fn::GetJsonValue:
        - DownloadJdk
        - Fn::GetAtt:
            - DownloadPkgWaitCondition
            - Data
  DownloadMavenResult:
    Value:
      Fn::GetJsonValue:
        - DownloadMaven
        - Fn::GetAtt:
            - DownloadPkgWaitCondition
            - Data
Metadata: {}
模板逻辑:
  1. 在ECS实例中下载jdkmaven文件。
  2. 设置ALIYUN::ROS::WaitCondition与ALIYUN::ROS::WaitConditionHandle资源的Count属性值为2。
    说明
    • 如果ALIYUN::ROS::WaitConditionHandle没有指定ID,ROS会使用整数作为信号ID,整数=已有信号的数量+1。
    • ALIYUN::ROS::WaitConditionHandle设置相同ID的信号会被当作同一信号,后面收到的信号会覆盖前面收到的。
  3. 指定ros-notify的ID属性名称,通过不同的ID名称(DownloadJdk和DownloadMaven)判断两次下载安装包的最终结果,从而发送jdkmaven安装包下载成功或失败的信号。
您可以在ROS控制台对应资源栈的事件页签中查看ALIYUN::ROS::WaitConditionHandle资源一共接收了2次信号。002您可以在输出页签中查看模板输出的DownloadJDKResult和DownloadMavenResult的执行结果。003

WaitConditionHandle支持的两种模式

ALIYUN::ROS::WaitConditionHandle资源的Mode属性支持两种模式:Increment和Full。默认值:Full。

Mode取值为Full

方案示例:您可以批量创建ECS实例并安装应用,实现发送并接收信号。
说明 当ALIYUN::ROS::WaitConditionHandle中的Mode属性设置为Full时,更新过程中ALIYUN::ROS::WaitCondition等待的信号数量=ALIYUN::ROS::WaitCondition的Count属性取值-删除操作后剩余的旧信号的数量。
ROS模板
ROSTemplateFormatVersion: '2015-09-01'
Description: ''
Parameters:
  SystemDiskCategory:
    AssociationProperty: ALIYUN::ECS::Disk::SystemDiskCategory
    AssociationPropertyMetadata:
      InstanceType: InstanceType
      ZoneId: ZoneId
    Type: String
    Description:
      zh-cn: '<font color=''blue''><b>可选值:</b></font><br>[cloud_efficiency: <font color=''green''>高效云盘</font>]<br>[cloud_ssd: <font color=''green''>SSD云盘</font>]<br>[cloud_essd: <font color=''green''>ESSD云盘</font>]<br>[cloud: <font color=''green''>普通云盘</font>]'
      en: '<font color=''blue''><b>Optional values:</b></font><br>[cloud_efficiency: <font color=''green''>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color=''green''>SSD Cloud Disk</font>]<br>[cloud_essd: <font color=''green''>ESSD Cloud Disk</font>]<br>[cloud: <font color=''green''>Cloud Disk</font>]'
    Label:
      zh-cn: 系统盘类型
      en: System Disk Type
  SecurityGroupId:
    AssociationPropertyMetadata:
      VpcId: VpcId
    Description:
      zh-cn: 现有安全组的实例ID
      en: The instance ID of an existing security group.
    Default: Null
    Label:
      zh-cn: 安全组ID
      en: Security Group ID
    AssociationProperty: ALIYUN::ECS::SecurityGroup::SecurityGroupId
    Type: String
  SystemDiskSize:
    Default: 40
    Type: Number
    Description:
      zh-cn: 系统盘大小, 取值范围:[40, 500], 单位:GB。
      en: 'System disk size, range of values: 40-500, units: GB.'
    Label:
      zh-cn: 系统盘空间
      en: System Disk Space
  ZoneId:
    AssociationProperty: ALIYUN::ECS::Instance::ZoneId
    Type: String
    Description:
      zh-cn: 可用区配置决定了新建ECS实例的可用区。此外,如果您选择已有基础资源配置,仅能选到该可用区下的交换机。
      en: ECS VSwitch Zone ID defines the Availability Zone for creating ECS instance. If you choose existing Infrastructure Configuration,you can only find the VSwitch under the availability zone.
    Label:
      zh-cn: ECS交换机可用区
      en: ECS VSwitch Zone ID
  DataDiskCategory:
    AssociationProperty: ALIYUN::ECS::Disk::DataDiskCategory
    AssociationPropertyMetadata:
      InstanceType: InstanceType
      ZoneId: ZoneId
    Type: String
    Description:
      zh-cn: '<font color=''blue''><b>可选值:</b></font><br>[cloud_efficiency: <font color=''green''>高效云盘</font>]<br>[cloud_ssd: <font color=''green''>SSD云盘</font>]<br>[cloud_essd: <font color=''green''>ESSD云盘</font>]<br>[cloud: <font color=''green''>普通云盘</font>]'
      en: '<font color=''blue''><b>Optional values:</b></font><br>[cloud_efficiency: <font color=''green''>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color=''green''>SSD Cloud Disk</font>]<br>[cloud_essd: <font color=''green''>ESSD Cloud Disk</font>]<br>[cloud: <font color=''green''>Cloud Disk</font>]'
    Label:
      zh-cn: 数据盘类型
      en: Data Disk Type
  VpcId:
    Default: Null
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
    Type: String
    Description:
      zh-cn: 请选择已有的VPC<br><b><font color='blue'>如找不到VPC,请切换地域。</font></b>
      en: Please select the existing VPC. <br><b><font color='blue'>If you can't find the VPC, please switch Regions.</font></b>
    Label:
      zh-cn: 现有VPC的实例ID
      en: Existing VPC ID
  DataDiskSize:
    Description:
      zh-cn: ECS实例数据盘大小,单位为GiB。取值范围:20~32768
      en: 'ECS Instance disk size, range of values: 20-32768, units: GB'
    Default: 100
    MaxValue: 32768
    MinValue: 20
    Label:
      zh-cn: 数据盘空间
      en: Data Disk Space
    Type: Number
  VSwitchId:
    AssociationPropertyMetadata:
      VpcId: VpcId
      ZoneId: ZoneId
    Description:
      zh-cn: 现有网络交换机的实例ID
      en: The instance ID of an existing network switch.
    Default: Null
    Label:
      zh-cn: 网络交换机ID
      en: VSwitch ID
    AssociationProperty: ALIYUN::ECS::VSwitch::VSwitchId
    Type: String
  Password:
    ConstraintDescription:
      zh-cn: 长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。
      en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).
    Description:
      zh-cn: 服务器登录密码,长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。
      en: Server login password, Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).
    MinLength: 8
    Label:
      zh-cn: 实例密码
      en: Instance Password
    AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'
    NoEcho: true
    MaxLength: 30
    Type: String
  InstanceType:
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: ZoneId
    Type: String
    Label:
      zh-cn: 实例类型
      en: Instance Type
  InternetChargeType:
    Type: String
    Description:
      zh-cn: '<font color=''blue''><b>可选值:</b></font><br>[PayByBandwidth: <font color=''green''>按带宽付费。</font>]<br>[PayByTraffic: <font color=''green''>按流量付费。</font>],<br>默认为PayByTraffic'
      en: '<font color=''blue''><b>Optional values:</b></font><br>[PayByBandwidth: <font color=''green''>Pay by bandwidth. </font>]<br>[PayByTraffic: <font color=''green''>Pay by traffic. </font>],<br>The default is PayByTraffic'
    Label:
      en: InternetChargeType
      zh-cn: 流量付费类型
    AllowedValues:
      - PayByBandwidth
      - PayByTraffic
    Default: PayByTraffic
  InternetMaxBandwidthOut:
    Type: Number
    Description:
      en: 'ECS Internet Max Bandwidth Out. Value range: 0~100. Unit: Mbps. Default value: 0.'
      zh-cn: ECS最大出带宽。取值范围:0~100。单位:Mbps。默认值:0。
    Label:
      en: 'Internet Max BandwidthOut '
      zh-cn: 实例公网带宽
    Default: 0
    MaxValue: 100
    MinValue: 0
  EcsCount:
    Type: Number
    Default: 3
    Label:
      en: EcsCount
      zh-cn: ECS实例数量
Outputs:
  InstanceIds:
    Value:
      Fn::GetAtt:
        - ECSInstances
        - InstanceIds
Conditions: {}
Resources:
  RosWaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Timeout: 1800
      Count:
        Ref: EcsCount
      Handle:
        Ref: RosWaitConditionHandle
  RosWaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
    Properties:
      Count:
        Ref: EcsCount
      Mode: Full
  ECSInstances:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      SystemDiskCategory:
        Ref: SystemDiskCategory
      VpcId:
        Ref: VpcId
      InstanceChargeType: PostPaid
      AllocatePublicIP: true
      SecurityGroupId:
        Ref: SecurityGroupId
      InternetChargeType:
        Ref: InternetChargeType
      InternetMaxBandwidthOut:
        Ref: InternetMaxBandwidthOut
      DiskMappings:
        - Category:
            Ref: DataDiskCategory
          Size:
            Ref: DataDiskSize
      SystemDiskSize:
        Ref: SystemDiskSize
      ImageId: centos_7
      VSwitchId:
        Ref: VSwitchId
      Password:
        Ref: Password
      InstanceType:
        Ref: InstanceType
      ZoneId:
        Ref: ZoneId
      MaxAmount:
        Ref: EcsCount
      UserData:
        Fn::Sub:
          - |
            #!/bin/sh
            yum install tree -y
            tree --help
            if [[ $? -eq 0 ]];
            then
                 ${ros-notify} -d "{\"status\" : \"SUCCESS\", \"Data\" : \"Tree install success\"}"
            fi
          - ros-notify:
              Fn::GetAtt:
                - RosWaitConditionHandle
                - CurlCli
    Metadata:
      ALIYUN::ROS::Designer:
        id: 3d97f557-f6c2-475f-bdca-942c45e5****
Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - ZoneId
        Label:
          default:
            zh-cn: 配置可用区
            en: Zone Configuration
      - Parameters:
          - VpcId
          - VSwitchId
          - SecurityGroupId
        Label:
          default:
            zh-cn: 选择已有基础资源配置
            en: Choose existing Infrastructure Configuration
      - Parameters:
          - EcsCount
          - InstanceType
          - SystemDiskCategory
          - SystemDiskSize
          - DataDiskCategory
          - DataDiskSize
          - InternetChargeType
          - InternetMaxBandwidthOut
          - Password
        Label:
          default:
            zh-cn: 配置ECS(必填)
            en: ECS Configuration
    TemplateTags:
      - acs:example:批量创建云服务器ECS
                
模板逻辑:
  1. 通过ALIYUN::ECS::InstanceGroup资源批量创建3台ECS实例并安装应用。
  2. 将ROS模板中的参数EcsCount作为创建ECS实例数量、ALIYUN::ROS::WaitCondition与ALIYUN::ROS::WaitConditionHandle资源Count取值的输入。
您可以通过ROS控制台对应资源栈的事件页签查看一共创建了3台ECS实例,发送了3次ALIYUN::ROS::WaitCondition信号。004您可以通过更新资源栈在特定的场景下实现扩容或缩容。
  • 缩容场景:当需要减少创建ECS实例总数时,您可以选择更新资源栈。
    例如:将创建ECS实例总数由3台减少到2台,由此您会将ALIYUN::ROS::WaitCondition和ALIYUN::ROS::WaitConditionHandle资源的Count取值由3变成2,更新完成后ALIYUN::ROS::WaitCondition信号数变更为2。005
    您可以通过ROS控制台对应资源栈的事件页签发现删除1台ECS实例后不会收到新的ALIYUN::ROS::WaitConditionHandle信号。006
  • 扩容场景:在执行缩容场景后,当需要增加创建ECS实例总数时,您可以继续更新资源栈。
    例如:将创建ECS实例总数由2台增加到4台,由此您会将ALIYUN::ROS::WaitCondition和ALIYUN::ROS::WaitConditionHandle资源的Count数量由2变成4,更新完成后ALIYUN::ROS::WaitCondition的信号数变更为4。007
    您可以通过ROS控制台对应资源栈的事件页签发现新增2台ECS实例后会收到2条新的ALIYUN::ROS::WaitConditionHandle信号。008

Mode取值为Increment

方案示例:您可以完成etcd集群版部署,实现发送并接收信号。
说明 当ALIYUN::ROS::WaitConditionHandle的Mode属性设置为Increment时,更新过程中ALIYUN::ROS::WaitCondition等待的信号数量等于ALIYUN::ROS::WaitCondition的Count属性的取值。
ROS模板
ROSTemplateFormatVersion: '2015-09-01'
Description:
  zh-cn: 在Centos7下安装部署集群版etcd服务(静态发现从节点模式),etcd是一个用于服务注册与发现的键值存储组件, 其内部采用raft协议作为一致性算法保证数据统一性,集群安装完成后请使用etcdctl命令在云服务器中操作管理集群
  en: Installing the deployment cluster version of the Etcd service (static discovery from node mode) under centos7, Etcd is a key-value storage component for service registration and discovery, which internally uses the raft protocol as a consistency algorithm to ensure data consistency, Once the cluster is installed, use the etcdctl command line to operate the management cluster in the cloud server.
Parameters:
  SystemDiskCategory:
    Default: cloud_efficiency
    Label:
      zh-cn: 系统盘类型
      en: System Disk Type
    Type: String
    Description:
      en: '<font color=''blue''><b>Optional values:</b></font><br>[cloud_efficiency: <font color=''green''>Efficient Cloud Disk</font>]<br>[cloud_ssd: <font color=''green''>SSD Cloud Disk</font>]<br>[cloud_essd: <font color=''green''>ESSD Cloud Disk</font>]<br>[cloud: <font color=''green''>Cloud Disk</font>]<br>[ephemeral_ssd: <font color=''green''>Local SSD Cloud Disk</font>]'
      zh-cn: '<font color=''blue''><b>可选值:</b></font><br>[cloud_efficiency: <font color=''green''>高效云盘</font>]<br>[cloud_ssd: <font color=''green''>SSD云盘</font>]<br>[cloud_essd: <font color=''green''>ESSD云盘</font>]<br>[cloud: <font color=''green''>普通云盘</font>]<br>[ephemeral_ssd: <font color=''green''>本地SSD盘</font>]'
    AllowedValues:
      - cloud_efficiency
      - cloud_ssd
      - cloud
      - cloud_essd
      - ephemeral_ssd
  SystemDiskSize:
    Default: 40
    Type: Number
    Description:
      zh-cn: 系统盘大小, 取值范围:[40, 500], 单位:GB。
      en: 'System disk size, range of values: 40-500, units: GB.'
    Label:
      zh-cn: 系统盘空间
      en: System Disk Space
  SecurityGroup:
    AssociationProperty: ALIYUN::ECS::SecurityGroup::SecurityGroupId
    Type: String
    Description:
      zh-cn: 现有业务安全组的实例ID,控制台-ECS-网络与安全-安全组下查询
      en: Please search the business security group ID starting with(sg-xxx)from console-ECS-Network & Security
    Label:
      zh-cn: 业务安全组ID
      en: Business Security Group ID
    AssociationPropertyMetadata:
      VpcId: VPC
  VSwitchZoneId:
    AssociationProperty: ALIYUN::ECS::Instance:ZoneId
    Type: String
    Description:
      zh-cn: 可用区ID。<br><b>注: <font color='blue'>选择前请确认该可用区是否支持创建ECS资源的规格,建议与其他交换机可用区不同</font></b>
      en: Availability Zone ID.<br><b>note:<font color='blue'>before selecting, please confirm that the Availability Zone supports the specification of creating ECS resources,which is recommended to be different from other VSwitch Availability Zone</font></b>
    Label:
      zh-cn: 交换机可用区
      en: VSwitch Availability Zone
  VPC:
    AssociationProperty: ALIYUN::ECS::VPC::VPCId
    Type: String
    Description:
      zh-cn: 现有VPC的实例ID,控制台-VPC-专有网络下查询
      en: Please search the ID starts with (vpc-xxx)from console-Virtual Private Cloud
    Label:
      zh-cn: 现有VPC的实例ID
      en: Existing VPC Instance ID
  VSwitch:
    AssociationProperty: ALIYUN::ECS::VSwitch::VSwitchId
    Type: String
    Description:
      zh-cn: 现有业务网络交换机的实例ID,控制台-VPC-专有网络-交换机下查询
      en: Please search the business VSwitch ID starts with(vsw-xxx)from console-Virtual Private Cloud-VSwitches
    Label:
      zh-cn: 网络交换机ID
      en: Existing VSwitch ID
    AssociationPropertyMetadata:
      VpcId: VPC
      ZoneId: VSwitchZoneId
  Password:
    Type: String
    Description:
      zh-cn: 服务器登录密码,长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。
      en: Server login password, Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).
    MinLength: 8
    Label:
      zh-cn: 实例密码
      en: Instance Password
    AllowedPattern: '[0-9A-Za-z\_\-\&:;''<>,=%`~!@#\(\)\$\^\*\+\|\{\}\[\]\.\?\/]+$'
    NoEcho: true
    MaxLength: 30
    ConstraintDescription:
      zh-cn: 长度8~30,必须包含三项(大写字母、小写字母、数字、 ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ 中的特殊符号)。
      en: Length 8-30, must contain three(Capital letters, lowercase letters, numbers, ()`~!@#$%^&*_-+=|{}[]:;'<>,.?/ Special symbol in).
  InstanceType:
    AssociationProperty: ALIYUN::ECS::Instance::InstanceType
    AssociationPropertyMetadata:
      ZoneId: VSwitchZoneId
    Type: String
    Description:
      zh-cn: 填写交换机可用区下可使用的规格;<br>通用规格:<font color='red'><b>ecs.c5.large</b></font><br>注:可用区可能不支持通用规格<br>规格,请参见:<a href='https://help.aliyun.com/document_detail/25378.html' target='_blank'><b><font color='blue'>实例规格族</font></a></b>
      en: 'Fill in the specifications that can be used under the VSwitch availability zone;</b></font><br>general specifications:<font color=''red''><b>ecs.c5.large</b></font><br>note: a few zones do not support general specifications<br>see detail: <a href=''https://www.alibabacloud.com/help/en/doc-detail/25378.html'' target=''_blank''><b><font color=''blue''>Instance Specification Family</font></a></b>'
    Label:
      zh-cn: 实例规格
      en: Instance Type
  ClusterAmount:
    Description:
      zh-cn: 集群主机数量,取值范围:[3~10]
      en: 'Number of cluster hosts, value range: [3~10]'
    Default: 3
    MaxValue: 10
    MinValue: 3
    Label:
      zh-cn: 集群主机数
      en: Number of cluster hosts
    Type: Number
  EssWaitConditionCount:
    Default: 2
    Label:
      zh-cn: 弹性伸缩组自定义数据发送与接收信号的次数
      en: Ess Userdata WaitConditionHandle Count Number
    Type: Number
  ImageId:
    Default: centos_7_04_64_20G_alibase_20170****.vhd
    Type: String
    Description:
      zh-cn: 镜像ID, 请使用Centos7, 请参见:<b><a href='https://help.aliyun.com/document_detail/112977.html' target='_blank'><font color='blue'>查找镜像</font></a></b>
      en: Image ID,Please use Centos7, see detail:<b><a href='https://www.alibabacloud.com/help/en/doc-detail/112977.html' target='_blank'><font color='blue'>Find the mirror</font></a></b>
    Label:
      zh-cn: 镜像
      en: Image
Outputs:
  EtcdMasterServerConnectionAddress:
    Value:
      Fn::Join:
        - ''
        - - Fn::Select:
              - '0'
              - Fn::GetAtt:
                  - EtcdMasterServer
                  - PrivateIps
          - ':2379'
Resources:
  WaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Count: 1
      Handle:
        Ref: WaitConditionHandle
      Timeout: 1800
    Metadata:
      ALIYUN::ROS::Designer:
        id: 00310e6e-cbc4-433a-ac83-f9d58e6e****
  EtcdMasterServer:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      UserData:
        Fn::Sub:
          - |
            #!/bin/sh
            MasterEtcdIP=`ifconfig eth0 | awk '/inet /{print $2}'`
            MasterEtcdHostName=`hostname`
            InstallPackage() {
              yum install -y yum-utils
              yum install -y expect
            }
            InstallEtcd() {
              yum install etcd -y
              systemctl enable etcd
            }
            SSHConfig() {
              yum update -y
              yum install -y expect
              yum install -y jq
              echo '#!/usr/bin/expect' > /tmp/ssh_gen_key
              echo spawn ssh-keygen -t rsa >> /tmp/ssh_gen_key
              echo 'expect {' >> /tmp/ssh_gen_key
              echo '        "*(/root/.ssh/id_rsa)" {send "\n\r";exp_continue}' >> /tmp/ssh_gen_key
              echo '        "*(empty for no passphrase)" {send "\n\r";exp_continue}' >> /tmp/ssh_gen_key
              echo '        "*again" {send "\n\r"}' >> /tmp/ssh_gen_key
              echo '}' >> /tmp/ssh_gen_key
              echo 'expect eof' >> /tmp/ssh_gen_key
              /usr/bin/expect /tmp/ssh_gen_key
              pub_key=`cat /root/.ssh/id_rsa.pub`
              sed -i 's/#   StrictHostKeyChecking ask/StrictHostKeyChecking no/' /etc/ssh/ssh_config
              sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/ssh_config
              service sshd restart
            }
            SetMasterEtcdConfig() {
                sed -i 's%#ETCD_LISTEN_PEER_URLS=.*%ETCD_LISTEN_PEER_URLS="http://'${MasterEtcdIP}':2380"%g' /etc/etcd/etcd.conf
                sed -i 's%ETCD_LISTEN_CLIENT_URLS=.*%ETCD_LISTEN_CLIENT_URLS="http://'${MasterEtcdIP}':2379,http://127.0.0.1:2379"%g' /etc/etcd/etcd.conf
                sed -i 's%ETCD_NAME=.*%ETCD_NAME="'${MasterEtcdHostName}'"%g' /etc/etcd/etcd.conf
                sed -i 's%#ETCD_INITIAL_ADVERTISE_PEER_URLS=.*%ETCD_INITIAL_ADVERTISE_PEER_URLS="http://'${MasterEtcdIP}':2380"%g' /etc/etcd/etcd.conf
                sed -i 's%ETCD_ADVERTISE_CLIENT_URLS=.*%ETCD_ADVERTISE_CLIENT_URLS="http://'${MasterEtcdIP}':2379"%g' /etc/etcd/etcd.conf
                sed -i 's%#ETCD_INITIAL_CLUSTER=.*%ETCD_INITIAL_CLUSTER="'${MasterEtcdHostName}'=http://'${MasterEtcdIP}':2380"%g' /etc/etcd/etcd.conf
                sed -i 's%#ETCD_INITIAL_CLUSTER_TOKEN=.*%ETCD_INITIAL_CLUSTER_TOKEN="etcd-cluster"%g' /etc/etcd/etcd.conf
                sed -i 's%#ETCD_INITIAL_CLUSTER_STATE=.*%ETCD_INITIAL_CLUSTER_STATE="new"%g' /etc/etcd/etcd.conf
            }
            StartEtcdService() {
              systemctl start etcd
            }
            main() {
                  InstallPackage
                  InstallEtcd
                  SSHConfig
                  SetMasterEtcdConfig
                  StartEtcdService
            }
            main
            netstat -ntlp | grep 2380 >> /opt/access.log
            if [[ $? -eq 0 ]];
            then
                  cmd="${ros-notify} -d '{\"id\" : \"ssh_pub_key\", \"data\" : \"$pub_key\"}'"
                  eval $cmd
            fi
          - ros-notify:
              Fn::GetAtt:
                - WaitConditionHandle
                - CurlCli
      SystemDiskCategory:
        Ref: SystemDiskCategory
      VpcId:
        Ref: VPC
      SecurityGroupId:
        Ref: SecurityGroup
      SystemDiskSize:
        Ref: SystemDiskSize
      ImageId:
        Ref: ImageId
      AllocatePublicIP: true
      VSwitchId:
        Ref: VSwitch
      Password:
        Ref: Password
      InstanceName: EtcdMasterServer
      InstanceType:
        Ref: InstanceType
      ZoneId:
        Ref: VSwitchZoneId
      MaxAmount: 1
    Metadata:
      ALIYUN::ROS::Designer:
        id: b13a873e-1bb2-4729-b3c6-9fac8c35****
  EssScalingGroup:
    Type: ALIYUN::ESS::ScalingGroup
    Properties:
      MinSize:
        Fn::Calculate:
          - '{0}-1'
          - 1
          - - Ref: ClusterAmount
      MaxSize:
        Fn::Calculate:
          - '{0}-1'
          - 1
          - - Ref: ClusterAmount
      VpcId:
        Ref: VPC
      VSwitchId:
        Ref: VSwitch
    DependsOn:
      - WaitCondition
    Metadata:
      ALIYUN::ROS::Designer:
        id: a883cd62-e1a0-4742-b3ac-dd615adc****
  EssScalingConfiguration:
    Type: ALIYUN::ESS::ScalingConfiguration
    Properties:
      UserData:
        Fn::Sub:
          - |
            #!/bin/sh
            echo root:${master_password} | chpasswd
            HOST_IP=`ifconfig eth0 | awk '/inet /{print $2}'`
            ConfigSSH() {
                      echo $ssh_pub_key_json > /tmp/pubkey
                      new_hostname='etcd-follower'`tr -dc "0-9" < /dev/urandom | head -c 9`
                      hostnamectl set-hostname ${new_hostname}
                      su -
                      yum install -y jq
                      yum install -y expect
                      pub_key=`echo "$ssh_pub_key_json" | jq '.ssh_pub_key' | xargs echo `
                      echo "$pub_key" > /root/.ssh/authorized_keys
                      chmod 600 /root/.ssh/authorized_keys
                      sed -i 's/#   StrictHostKeyChecking ask/StrictHostKeyChecking no/' /etc/ssh/ssh_config
                      sed -i 's/GSSAPIAuthentication yes/GSSAPIAuthentication no/' /etc/ssh/ssh_config
                      service sshd restart
                      echo $pub_key > /tmp/real_pub_key
                      echo '[ ! -f /root/.ssh/id_rsa.pub ] && ssh-keygen -t rsa -P "" -f ~/.ssh/id_rsa &>/dev/null' >> /tmp/auto_ssh.sh
                      echo 'while read line;do' >> /tmp/auto_ssh.sh
                      echo '        ip=`echo $line | cut -d " " -f1`' >> /tmp/auto_ssh.sh
                      echo '        user_name=`echo $line | cut -d " " -f2`' >> /tmp/auto_ssh.sh
                      echo '        pass_word="'${master_password//$/\\\\\\$}'"' >> /tmp/auto_ssh.sh
                      echo 'expect <<EOF' >> /tmp/auto_ssh.sh
                      echo '        spawn ssh-copy-id -i /root/.ssh/id_rsa.pub $user_name@$ip' >> /tmp/auto_ssh.sh
                      echo '        expect {' >> /tmp/auto_ssh.sh
                      echo '                  "yes/no" { send "yes\n";exp_continue}' >> /tmp/auto_ssh.sh
                      echo '                  "password" { send "$pass_word\n"}' >> /tmp/auto_ssh.sh
                      echo '        }' >> /tmp/auto_ssh.sh
                      echo '        expect eof' >> /tmp/auto_ssh.sh
                      echo 'EOF' >> /tmp/auto_ssh.sh
                      echo 'done < /opt/host_ip.txt' >> /tmp/auto_ssh.sh
            }
            SetHostsConfig() {
                      echo "${master_ip} root ${master_password}" >> /opt/host_ip.txt
                      sh /tmp/auto_ssh.sh
            }
            InstallService() {
                      yum install etcd -y
                      systemctl enable etcd
            }
            JoinCluster() {
                      sleep_time=`tr -dc "0-9" < /dev/urandom | head -c 2`
                      HOSTNAME=`hostname`
                      join_res=`ssh ${master_ip} "etcdctl member add ${HOSTNAME} http://${HOST_IP}:2380"`
                      if [[ $? -ne 0 ]];
                      then
                           sleep ${sleep_time}
                           join_res=`ssh ${master_ip} "etcdctl member add ${HOSTNAME} http://${HOST_IP}:2380"`
                      fi
                      if [[ $? -ne 0 ]];
                      then
                           sleep ${sleep_time}
                           join_res=`ssh ${master_ip} "etcdctl member add ${HOSTNAME} http://${HOST_IP}:2380"`
                      fi
                      cluster_info=`echo ${join_res} | awk -F '"' '{print $4}'`
                      echo ${join_res} | awk -F 'ID' '{print $2}' | awk -F 'to' '{print $1}'| sed -e 's/^[ \t]*//g' -e 's/[ \t]*$//g' > /opt/cluster_info.txt
                      nohup etcd --name ${HOSTNAME} --listen-client-urls http://${HOST_IP}:2379,http://127.0.0.1:2379 --advertise-client-urls http://${HOST_IP}:2379 --listen-peer-urls http://${HOST_IP}:2380 --initial-advertise-peer-urls http://${HOST_IP}:2380 --initial-cluster-state existing --initial-cluster ${cluster_info} --initial-cluster-token etcd-cluster  >> /opt/add_cluster.log 2>&1 &
            }
            main() {
                      ConfigSSH
                      SetHostsConfig
                      InstallService
                      JoinCluster
            }
            main
            ${ros-notify} -d "{\"Data\" : \"Final Success\", \"Status\" : \"Success\"}"
          - ros-notify:
              Fn::GetAtt:
                - EssWaitConditionHandle
                - CurlCli
            ssh_pub_key_json:
              Fn::GetAtt:
                - WaitCondition
                - Data
            master_password:
              Ref: Password
            master_ip:
              Fn::Select:
                - 0
                - Fn::GetAtt:
                   - EtcdMasterServer
                   - PrivateIps
      SystemDiskCategory:
        Ref: SystemDiskCategory
      InstanceType:
        Ref: InstanceType
      SecurityGroupId:
        Ref: SecurityGroup
      SystemDiskSize:
        Ref: SystemDiskSize
      ImageId:
        Ref: ImageId
      InternetMaxBandwidthOut: 100
      ScalingGroupId:
        Ref: EssScalingGroup
      InternetChargeType: PayByTraffic
      InternetMaxBandwidthIn: 100
    Metadata:
      ALIYUN::ROS::Designer:
        id: f8981ced-4b91-4bdb-8d20-623e2521****
  EssScalingGroupEnable:
    Type: ALIYUN::ESS::ScalingGroupEnable
    Properties:
      ScalingConfigurationId:
        Fn::GetAtt:
          - EssScalingConfiguration
          - ScalingConfigurationId
      ScalingGroupId:
        Fn::GetAtt:
          - EssScalingGroup
          - ScalingGroupId
    DependsOn: WaitCondition
    Metadata:
      ALIYUN::ROS::Designer:
        id: 636c7b3b-ad93-42a2-8531-b08b7750****
  EssWaitCondition:
    Type: ALIYUN::ROS::WaitCondition
    Properties:
      Count:
        Ref: EssWaitConditionCount
      Handle:
        Ref: EssWaitConditionHandle
      Timeout: 1800
    DependsOn:
      - EssScalingConfiguration
    Metadata:
      ALIYUN::ROS::Designer:
        id: cbfe44ee-7844-44c0-805a-afefb200****
  EssWaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
    Metadata:
      ALIYUN::ROS::Designer:
        id: 75ee3af0-98e7-4c9d-aa7d-9c6eef24****
    Properties:
      Count:
        Ref: EssWaitConditionCount
      Mode: Increment
  EssLifecycleHook:
    Type: ALIYUN::ESS::LifecycleHook
    Properties:
      LifecycleHookName: etcd_scale_in_rule
      ScalingGroupId:
        Ref: EssScalingGroup
      NotificationArn:
        Fn::Join:
          - ''
          - - 'acs:ess:'
            - Ref: ALIYUN::Region
            - ':'
            - Ref: ALIYUN::TenantId
            - ':'
            - oos/ACS-ESS-LifeCycleRunCommand
      NotificationMetadata:
        Fn::Join:
          - ''
          - - |-
              {
                "commandContent": "node_id=`cat /opt/cluster_info.txt | sed '/^$/d'` && etcdctl member remove ${node_id}",
                "commandType": "RunShellScript",
                "OOSAssumeRole": "
            - Fn::GetAtt:
                - EssRole
                - RoleName
            - |-
              ",
                "regionId": "${regionId}",
                "instanceIds": "${instanceIds}",
                "lifecycleHookId": "${lifecycleHookId}",
                "rateControl": "{\"Mode\":\"Concurrency\",\"MaxErrors\":0,\"Concurrency\":10}",
                "lifecycleActionToken": "${lifecycleActionToken}"
              }
      LifecycleTransition: SCALE_IN
    DependsOn:
      - EssScalingGroup
    Metadata:
      ALIYUN::ROS::Designer:
        id: fac2a803-dfe0-436e-a751-c6386962****
  EssRole:
    Type: ALIYUN::RAM::Role
    Properties:
      RoleName:
        Fn::Sub: EssRamRoleRam-${ALIYUN::StackId}
      AssumeRolePolicyDocument:
        Statement:
          - Action: sts:AssumeRole
            Effect: Allow
            Principal:
              Service:
                - oos.aliyuncs.com
        Version: '1'
      Policies:
        - PolicyName:
            Fn::Sub: EssRamRolePolicy-${ALIYUN::StackId}
          PolicyDocument:
            Version: '1'
            Statement:
              - Action:
                  - ecs:*
                Resource:
                  - '*'
                Effect: Allow
              - Action:
                  - ess:*
                Resource:
                  - '*'
                Effect: Allow
    Metadata:
      ALIYUN::ROS::Designer:
        id: 6d794594-ed03-4c63-873b-67069e88****
  WaitConditionHandle:
    Type: ALIYUN::ROS::WaitConditionHandle
    Metadata:
      ALIYUN::ROS::Designer:
        id: 81a773e0-a626-4c93-b85e-0067c51f****
Metadata:
  ALIYUN::ROS::Interface:
    ParameterGroups:
      - Parameters:
          - VSwitchZoneId
          - VPC
          - VSwitch
          - SecurityGroup
        Label:
          default:
            zh-cn: 配置基础资源(必填)
            en: Infrastructure Configuration
      - Parameters:
          - InstanceType
          - ImageId
          - SystemDiskCategory
          - SystemDiskSize
          - ClusterAmount
          - EssWaitConditionCount
          - Password
        Label:
          default:
            zh-cn: 配置etcd
            en: Etcd Configuration
    TemplateTags:
      - acs:solution:容器:etcd集群版(已有VPC)
  ALIYUN::ROS::Designer:
    00310e6e-cbc4-433a-ac83-f9d58e6e****:
      size:
        width: 60
        height: 60
      position:
        x: 273
        'y': 203
      z: 0
    b13a873e-1bb2-4729-b3c6-9fac8c35****:
      size:
        width: 60
        height: 60
      position:
        x: 174
        'y': 139
      z: 0
    a883cd62-e1a0-4742-b3ac-dd615adc****:
      size:
        width: 60
        height: 60
      position:
        x: 38
        'y': 128
      z: 0
    f8981ced-4b91-4bdb-8d20-623e2521****:
      size:
        width: 60
        height: 60
      position:
        x: 38
        'y': 281
      z: 0
    636c7b3b-ad93-42a2-8531-b08b7750****:
      size:
        width: 60
        height: 60
      position:
        x: -147
        'y': 281
      z: 0
    cbfe44ee-7844-44c0-805a-afefb200****:
      size:
        width: 60
        height: 60
      position:
        x: 127
        'y': 359
      z: 0
    75ee3af0-98e7-4c9d-aa7d-9c6eef24****:
      size:
        width: 60
        height: 60
      position:
        x: -45
        'y': 359
      z: 0
    fac2a803-dfe0-436e-a751-c6386962****:
      size:
        width: 60
        height: 60
      position:
        x: 170
        'y': 282
      z: 0
    6d794594-ed03-4c63-873b-67069e88****:
      size:
        width: 60
        height: 60
      position:
        x: 311
        'y': 282
      z: 0
    81a773e0-a626-4c93-b85e-0067c51f****:
      size:
        width: 60
        height: 60
      position:
        x: 273
        'y': 72
      z: 0
    8e57888e-abdf-4469-825f-a4371538****:
      source:
        id: 00310e6e-cbc4-433a-ac83-f9d58e6e****
      target:
        id: 81a773e0-a626-4c93-b85e-0067c51f****
      z: 1
    e3866ff3-c87b-44a6-92f7-2381a37d****:
      source:
        id: f8981ced-4b91-4bdb-8d20-623e2521****
      target:
        id: a883cd62-e1a0-4742-b3ac-dd615adc****
      z: 1
    d542f1d3-4d46-4ec8-9ffe-37508968****:
      source:
        id: 636c7b3b-ad93-42a2-8531-b08b7750****
      target:
        id: f8981ced-4b91-4bdb-8d20-623e2521****
      z: 1
    38de5067-aed7-4496-a794-4c1876ef****:
      source:
        id: 636c7b3b-ad93-42a2-8531-b08b7750****
      target:
        id: a883cd62-e1a0-4742-b3ac-dd615adc****
      z: 1
    38798c97-11ed-4c5e-9c24-4a216ed5****:
      source:
        id: cbfe44ee-7844-44c0-805a-afefb200****
      target:
        id: 75ee3af0-98e7-4c9d-aa7d-9c6eef24****
      z: 1
    9fa81f0c-a653-418e-8a57-f10294ff****:
      source:
        id: fac2a803-dfe0-436e-a751-c6386962****
      target:
        id: a883cd62-e1a0-4742-b3ac-dd615adc****
      z: 1
    9796aacc-6761-4b00-97db-69c06424****:
      source:
        id: fac2a803-dfe0-436e-a751-c6386962****
      target:
        id: 6d794594-ed03-4c63-873b-67069e88****
      z: 1
                
模板逻辑:
  1. 通过ALIYUN::ECS::InstanceGroup资源创建1台ECS实例并安装etcd主节点服务。
  2. 通过ALIYUN::ESS::ScalingGroup资源创建2台ECS实例并安装etcd从节点服务,然后加入etcd集群。
  3. 创建资源栈时配置集群主机数为3,配置弹性伸缩组自定义数据发送与接收信号的次数为2。009
您可以通过ROS控制台的事件页签发现一共创建了3台ECS实例,接收了2次ALIYUN::ROS::WaitConditionHandle信号。010

如果您需要新增1台ECS实例时,可以将集群主机数调整为4,配置弹性伸缩组自定义数据发送与接收信号的次数为1,由此您会将ALIYUN::ROS::WaitCondition和ALIYUN::ROS::WaitConditionHandle资源的Count数量由2变成4。

您可以查看资源栈事件页签发现ALIYUN::ROS::WaitConditionHandle只接收了1次信号。011