资源编排之嵌套资源栈

背景

资源编排服务(Resource Orchestration Service, 简称ROS)是阿里云提供的一项简化云计算资源管理的服务。您可以遵循ROS定义的模板规范编写资源栈模板,在模板中定义所需的云计算资源(例如ECS实例、RDS数据库实例)、资源间的依赖关系等。ROS的编排引擎将根据模板自动完成所有资源的创建和配置,实现自动化部署及运维。

随着基础设施的发展,常见模板模式可合并,以便在多个模板中声明相同的组件。您可以分离这些常见组件并为其创建专用模板。然后使用模板中的资源来引用其他模板,也就是创建嵌套资源栈。通过使用嵌套资源栈可以对模板进行有效的复用,简化模板的编写。

例如,假如您拥有用于大多数资源栈的网络配置。您可以为网络创建专用模板,而不是将相同的配置复制并粘贴到您的模板中。然后,您只需使用资源从其他模板中引用该模板。

功能介绍

嵌套资源栈是作为其他资源栈的一部分来创建的资源栈。您可以在另一个资源栈中使用 ALIYUN::ROS::Stack 资源创建嵌套资源栈。

嵌套资源栈本身可以包含其他嵌套资源栈,构成一个资源栈层次结构,如下图所示。根资源栈是所有嵌套资源栈最终归属的*资源栈。此外,每个嵌套资源栈都有一个直属父资源栈。对于第一级的嵌套资源栈而言,根资源栈也是父资源栈。以下图为例:

  • 资源栈 A 是该层次结构中所有其他嵌套资源栈的根资源栈。
  • 对于资源栈 B 来说,资源栈 A 既是父资源栈,也是根资源栈。
  • 对于资源栈 D,资源栈 C 是父资源栈;而对于资源栈 C 来说,资源栈 B 是父资源栈。

资源编排之嵌套资源栈

使用嵌套资源栈来声明常见组件被视为最佳做法。

某些资源栈操作 (如资源栈更新等) 应从根资源栈启动,而不是直接在嵌套资源栈上执行。此外,在某些情况下,嵌套资源栈会影响资源栈操作的执行。

更多信息,参考ALIYUN::ROS::Stack使用嵌套资源栈

资源属性

ALIYUN::ROS::Stack资源包含如下3个参数:

  • TemplateURL:
    • String类型。
    • 模板主体的文件的位置。模板主体的文件最大为524288个字节。URL必须指向位于Web服务器(http、https)或阿里云OSS存储空间(例如oss://ros/template/demo、oss://ros/template/demo?RegionId=cn-hangzhou。OSS地域如未指定,默认与资源栈RegionId相同。)中的模板。
    • URL的最大长度为1024个字节。
  • Parameters:
    • Map类型。
    • 一组值对,表示在创建此嵌套资源栈时传递给 ROS 的参数。每个参数都具有对应于该嵌入式模板中定义的参数的名称,以及表示要为该参数设置的值。如果嵌套堆栈需要输入参数,则必需传递。
  • TimeoutMins:
    • Number类型:
    • 创建或更新资源栈的超时时间。
    • 单位:分,默认值:60。

资源输出

  • 通过Fn::GetAtt获取嵌套资源栈的输出:
{
  "Fn::GetAtt": [
    "<nested_stack>",
    "Outputs.<nested_stack_output_name>"
  ]
}
  • 通过Ref获取嵌套资源栈的ARN。例如,arn:acs:ros::cn-hangzhou:123456789:stacks/test-nested-stack-Demo-jzkyq7mn2ykj/e71c1e04-1a57-46fc-b9a4-cf7ce0d32955。

示例

我们通过一个示例来演示一下嵌套资源栈的使用。

示例中包含两个资源栈:

  • 嵌套资源栈:创建网络相关配置。
  • 父资源栈:基于上述网络配置,提供Web服务。

嵌套资源栈模板

如下所示,嵌套资源栈包含3个资源:

  • Vpc:虚拟专有网络。
  • VSwitch:虚拟交换机。
  • SecurityGroup:安全组,放通22和Port指定端口。

这几个网络相关的资源很常见,在创建其他资源的时候,经常会用到。我们把它们提取到单独的模板当中,上传到OSS中便于复用。OSS Bucket为ros-demo,OSS Object为network_config.yml,地域为cn-hangzhou,所以其地址定义为 oss://ros-demo/network_config.yml?RegionId=cn-hangzhou。可能通过这个地址下载该模板。

ROSTemplateFormatVersion: '2015-09-01'
Parameters:
  NamePrefix:
    Type: String
    Default: 'test'
    MinLength: 1
  ZoneId:
    Type: String
    Default: ''
  VpcCidrBlock:
    Type: String
    Default: 10.0.0.0/8
    AllowedValues:
      - 192.168.0.0/16
      - 172.16.0.0/12
      - 10.0.0.0/8
  VSwitchCidrBlock:
    Type: String
    Default: 10.0.1.0/24
  Port:
    Type: Number
    Default: 8080
Conditions:
  AutoZoneId:
    Fn::Equals: [{"Ref": "ZoneId"}, ""]
Resources:
  Vpc:
    Type: 'ALIYUN::ECS::VPC'
    Properties:
      VpcName:
        Fn::Join: ['-', [{"Ref": "NamePrefix"}, "vpc", {"Ref": "ALIYUN::StackId"}]]
      CidrBlock:
        Ref: VpcCidrBlock
  VSwitch:
    Type: 'ALIYUN::ECS::VSwitch'
    Properties:
      VSwitchName:
        Fn::Join: ['-', [{"Ref": "NamePrefix"}, "vsw", {"Ref": "ALIYUN::StackId"}]]
      VpcId:
        Ref: Vpc
      CidrBlock:
        Ref: VSwitchCidrBlock
      ZoneId:
        Fn::If:
          - AutoZoneId
          - {"Fn::Select": ["0", {"Fn::GetAZs": {"Ref": "ALIYUN::Region"}}]}
          - Ref: ZoneId
  SecurityGroup:
    Type: 'ALIYUN::ECS::SecurityGroup'
    Properties:
      VpcId:
        Ref: Vpc
      SecurityGroupName:
        Fn::Join: ['-', [{"Ref": "NamePrefix"}, "sg", {"Ref": "ALIYUN::StackId"}]]
      SecurityGroupIngress:
        -
          IpProtocol: tcp
          Policy: accept
          PortRange:
            Fn::Replace: [{"port": {"Ref": "Port"}}, "port/port"]
          SourceCidrIp: "0.0.0.0/0"
        - 
          IpProtocol: tcp
          Policy: accept
          PortRange: "22/22"
          SourceCidrIp: "0.0.0.0/0"
Outputs:
  VpcId:
    Value:
      Ref: Vpc
  VSwitchId:
    Value:
      Ref: VSwitch
  SecurityGroupId:
    Value:
      Ref: SecurityGroup

父资源栈模板

如下所示,父资源栈包含2个资源:

  • NetworkConfig:嵌套资源栈。使用上述嵌套资源栈模板,配置网络。
  • WebServers:ECS虚拟机。NetworkConfig提供的网络配置创建,通过CloudInit提供Web服务。

NetworkConfig中TemplateURL的取值为 oss://ros-demo/network_config.yml?RegionId=cn-hangzhou,是因为已经按照上述方式上传到OSS当中了。如果没有上述到OSS,也可以直接使用地址 https://ros-demo.oss-cn-hangzhou.aliyuncs.com/network_config.yml

资源栈创建成功后,可以通过WebsiteUrl访问相关的Web服务。

ROSTemplateFormatVersion: '2015-09-01'
Parameters:
  ZoneId:
    Type: String
  ImageId:
    Type: String
    Default: centos_7
  InstanceType:
    Type: String
    Default: ecs.c6.large
  Password:
    Type: String
    Default: Abc12345
    NoEcho: true
  Port:
    Type: Number
    Default: 8081
Resources:
  NetworkConfig:
    Type: 'ALIYUN::ROS::Stack'
    Properties:
      TemplateURL: 'oss://ros-demo/network_config.yml?RegionId=cn-hangzhou'
      TimeoutMins: 5
      Parameters:
        NamePrefix: WebServer
        Port:
          Ref: Port
        ZoneId:
          Ref: ZoneId
  WebServers:
    Type: ALIYUN::ECS::InstanceGroup
    Properties:
      MaxAmount: 1
      MinAmount: 1
      ImageId:
        Ref: ImageId
      InstanceType:
        Ref: InstanceType
      Password:
        Ref: Password
      InstanceChargeType: PostPaid
      SecurityGroupId:
        Fn::GetAtt:
          - NetworkConfig
          - Outputs.SecurityGroupId
      VpcId:
        Fn::GetAtt:
          - NetworkConfig
          - Outputs.VpcId
      VSwitchId:
        Fn::GetAtt:
          - NetworkConfig
          - Outputs.VSwitchId
      UserData:
        Fn::Replace:
          -
            ${PORT}:
              Ref: Port
          - |
            #!/bin/sh

            cd ~

            pip install web.py==0.39
            
            cat >>website.py<<EOF
            import web

            urls = (
                '/', 'Index'
            )

            class Index:

                def GET(self):
                    return 'Hello, world!'

            if __name__ == '__main__':
                app = web.application(urls, globals())
                app.run()
            EOF

            nohup python website.py ${PORT} >> website.log 2>&1 &
Outputs:
  VpcId:
    Value:
      Fn::GetAtt:
        - NetworkConfig
        - Outputs.VpcId
  VSwitchId:
    Value:
      Fn::GetAtt:
        - NetworkConfig
        - Outputs.VSwitchId
  SecurityGroupId:
    Value:
      Fn::GetAtt:
        - NetworkConfig
        - Outputs.SecurityGroupId
  InstanceId:
    Value:
      Fn::Select:
        - 0
        -
          Fn::GetAtt:
            - WebServers
            - InstanceIds
  WebsiteUrl:
    Value:
      Fn::Replace:
        -
          ${IP}:
            Fn::Select:
              - 0
              - 
                Fn::GetAtt:
                  - WebServers
                  - PublicIps
          ${PORT}:
            Ref: Port
        - "http://${IP}:${PORT}"

测试验证

在ROS控制台,使用父资源栈模板创建资源栈。

资源编排之嵌套资源栈

资源栈创建成功后,观察资源列表。

资源编排之嵌套资源栈

观察输出列表,获取网站地址。

资源编排之嵌套资源栈

成功访问网站。

资源编排之嵌套资源栈

上一篇:阿里云新用户云服务器选购【参考指南】


下一篇:兹事体大,DataWorsk消息中心发布啦!