背景
资源编排服务(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控制台,使用父资源栈模板创建资源栈。
资源栈创建成功后,观察资源列表。
观察输出列表,获取网站地址。
成功访问网站。