1.背景
资源编排服务(Resource Orchestration Service, 简称ROS)是阿里云提供的一项简化云计算资源管理的服务。您可以遵循ROS定义的模板规范编写资源栈模板,在模板中定义所需的云计算资源(例如ECS实例、RDS数据库实例)、资源间的依赖关系等。ROS的编排引擎将根据模板自动完成所有资源的创建和配置,实现自动化部署及运维。
ROS资源编排接入了大量的阿里云资源,目前涉及38个服务,近200个资源,而且还在持续增长中。但用户有时候会需要使用一些非阿里云的资源,如跨云部署场景。甚至于非云资源,或是只是一段复杂的功能逻辑。这种情况下,ROS如何满足用户需求?
自定义资源为您提供了一种在 ROS 模板中编写自定义配置逻辑并使 ROS 在资源栈操作(如创建、更新或删除资源栈)期间运行该逻辑的方式。例如,您可能需要包含不可作为 阿里云 ROS 资源类型的资源。您可以使用自定义资源包含这些资源。这样,您仍然可以在一个资源栈中管理所有相关资源。
进阶篇:多云部署AWS篇,多云部署Terraform篇。
2. 功能介绍
2.1简单示例
首先通过一个简单的示例模板直观的感受一下。
模板中定义了一个自定义资源SimpleTest,类型为Custom::Add。该资源使用FC(函数计算)的函数,以X、Y作为输入参数,进行加法计算得到一个Z值作为输出。
ROSTemplateFormatVersion: '2015-09-01'
Resources:
SimpleTest:
Type: Custom::Add
Properties:
ServiceToken: acs:fc:cn-hangzhou:123456789:services/test-service/functions/test-function
Parameters: {X: 1, Y: 2}
Outputs:
SimpleTestOutputs:
Value:
Fn::GetAtt: [SimpleTest, Outputs]
Result:
Value:
Fn::GetAtt: [SimpleTest, Z]
2.2功能说明
2.2.1资源类型名称
对于自定义资源,您可以指定 ALIYUN::ROS::CustomResource 作为资源类型,也可以指定自己的资源类型名称。例如,您可以使用 ALIYUN::ROS::CustomResource,而不使用 Custom::MyCustomResourceTypeName。
自定义资源类型名称可包含字母数字字符和以下字符:_@-。您可指定最大长度为 68 个字符的自定义资源类型名称。在更新期间,不能更改类型。
使用自己的资源类型名称有助于快速区分堆栈中自定义资源的类型。例如,如果您有执行两种不同 ping 测试的两个自定义资源,则可以将其类型命名为 Custom::PingTester(而不使用 ALIYUN::ROS::CustomResource)以便方便地识别为 ping 测试器。
2.2.2资源属性
为了方便,我们称服务令牌的提供者为提供商。
自定义资源需包含三个属性:
- ServiceToken:服务令牌,它指定 阿里云 ROS 发送请求的目标,如 阿里云 MNS(消息服务) 主题&队列, 阿里云 FC(函数计算) 函数,或 HTTP&HTTPS 服务。
- Parameters:自定义资源的属性,会通过请求中传递给提供商。
- Timeout:等待提供商响应的超时时间。
2.2.3资源返回值
对于自定义资源,返回值是由自定义资源提供商定义的,并且可通过调用 Fn::GetAtt 在供应商提供的返回值中进行检索。
Outputs作为一个特殊的返回值,包含所有供应商提供的返回值。
2.3工作原理
对自定义资源执行的任何操作均涉及三方。
- template developer
- 创建包含自定义资源类型的模板。template developer在模板中指定服务令牌和所有输入数据。
- custom resource provider
- 上图中的“后端服务”。拥有自定义资源并确定如何处理和响应来自 阿里云 ROS 的请求。custom resource provider必须提供template developer使用的服务令牌。
- 阿里云 ROS
- 在资源栈操作期间,向模板中指定的服务令牌发送请求,然后等待响应,再继续资源栈操作。
- template developer在其模板中定义自定义资源,该模板包含服务令牌和任何输入数据参数。根据自定义资源,输入数据是可能必需的;但是,服务令牌是总是必需的。
服务令牌指定 阿里云 ROS 将请求发送到的位置,例如发送到 阿里云 MNS 主题 ARN 或 阿里云 FC 函数 ARN。有关更多信息,请参阅 ALIYUN::ROS::CustomResource。服务令牌和输入数据的结构由custom resource provider定义。
- 当任何人使用模板创建、更新或删除自定义资源时,阿里云 ROS 将向指定服务令牌发送请求。服务令牌无区域限制。
在请求中,阿里云 ROS 包含请求类型和自定义资源向其发送请求的预签名 URL 等信息。有关请求中包含的内容的更多信息,请参阅自定义资源请求对象。
在异步请求中(MNS、FC、异步HTTP&HTTPS),custom resource provider必须将响应发送到预签名的响应 URL。如果不能向 ROS 发送响应,阿里云 ROS 不会收到响应,资源栈操作就会失败。ResponseURL提供了公网响应的能力,InnerResponseURL提供了阿里云内网响应的能力。
以下示例数据显示 阿里云 ROS 在请求中包含哪些内容:
{ "RequestType" : "Create", "RequestId" : "unique id for this create request", "ResponseURL" : "pre-signed-url-for-create-response", "InnerResponseURL" : "pre-signed-inner-url-for-create-response", "ResourceType" : "Custom::MyCustomResourceType", "LogicalResourceId" : "name of resource in template", "StackId" : "stack id", "StackName" : "stack name", "ResourceOwnerId": "resource owner id", "CallerId": "caller id", "RegionId": "region id", "ResourceProperties" : { "key1" : "string", "key2" : [ "list" ], "key3" : { "key4" : "map" } } }
- custom resource provider处理 阿里云 ROS 请求并向预签名 URL 返回 SUCCESS 或 FAILED 响应。custom resource provider 提供采用 JSON 格式数据响应 URL。
在响应中,custom resource provider还可以包含template developer可以访问的名称-值对。例如,如果请求成功,响应可以包含输出数据,如果请求失败,可以包含错误消息。有关响应的更多信息,请参阅自定义资源响应对象。
custom resource provider负责侦听和响应请求。例如,对于 阿里云 MNS主题 通知,custom resource provider 必须侦听并响应发送到特定主题 ARN 的通知。阿里云 ROS 在预签名 URL 位置等待并侦听响应。
以下示例数据说明自定义资源在响应中可以包含的内容:
{ "Status" : "SUCCESS", "RequestId" : "unique id for this create request (copied from request)", "LogicalResourceId" : "name of resource in template (copied from request)", "StackId" : "stack id (copied from request)", "PhysicalResourceId" : "required vendor-defined physical id that is unique for that vendor", "Data" : { "keyThatCanBeUsedInGetAtt1" : "data for key 1", "keyThatCanBeUsedInGetAtt2" : "data for key 2" } }
- 获得 SUCCESS 响应后,阿里云ROS 继续堆栈操作。如果收到 FAILED 响应或未返回任何响应,则操作失败。来自自定义资源的所有输出数据都由预签名 URL 响应返回。template developer可使用 Fn::GetAtt 函数检索该数据。
3.实例测试
上述简单示例的完整模板。
ROSTemplateFormatVersion: '2015-09-01'
Parameters:
ServiceName:
Type: String
Default: test-service
FunctionName:
Type: String
Default: test-function
Timeout:
Type: Number
Default: 60
X:
Type: Number
Y:
Type: Number
Resources:
Service:
Type: ALIYUN::FC::Service
Properties:
ServiceName:
Ref: ServiceName
Function:
Type: ALIYUN::FC::Function
Properties:
ServiceName:
Fn::GetAtt: [Service, ServiceName]
FunctionName:
Ref: FunctionName
Handler: index.handler
Runtime: python2.7
Code:
SourceCode: |
import time
import json
import urllib2
import logging
def handler(event, context):
logger = logging.getLogger()
event = json.loads(event)
logger.info('receive request: %s', event)
res_props = event['ResourceProperties']
result = dict(
RequestId=event['RequestId'],
LogicalResourceId=event['LogicalResourceId'],
StackId=event['StackId'],
Status='SUCCESS',
PhysicalResourceId='dummy'
)
if event['RequestType'] != 'Delete':
result['Data'] = dict(z=res_props['X'] + res_props['Y'])
headers = {
'Content-type': 'application/json',
'Accept': 'application/json',
'Date': time.strftime('%a, %d %b %Y %X GMT', time.gmtime())
}
req = urllib2.Request(event['ResponseURL'], data=json.dumps(result), headers=headers)
resp = urllib2.urlopen(req)
resp_content = resp.read()
logger.info('response: %s', resp_content)
SimpleTest:
Type: Custom::Add
Properties:
ServiceToken:
Fn::GetAtt: [Function, ARN]
Parameters:
X:
Ref: X
Y:
Ref: Y
Timeout:
Ref: Timeout
Outputs:
SimpleTestOutputs:
Value:
Fn::GetAtt: [SimpleTest, Outputs]
Result:
Value:
Fn::GetAtt: [SimpleTest, Z]
在ROS控制台进行创建。
资源列表:
输出列表:
可以看到,这个模板虽然简单,但演示了如何把自定义资源与自定义后端服务关联,并传递输入和获取输出的完整流程。
有了这个功能,在ROS上实现多云管理或是其他复杂逻辑都成为了可能。