资源编排ROS之自定制资源(基础篇)

简介: 本文介绍资源编排ROS的基础知识配置。

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和custom resource provider可以是同一人员或实体,但过程相同。以下步骤介绍了一般过程:
  1. template developer在其模板中定义自定义资源,该模板包含服务令牌和任何输入数据参数。根据自定义资源,输入数据是可能必需的;但是,服务令牌是总是必需的。

    服务令牌指定 阿里云 ROS 将请求发送到的位置,例如发送到 阿里云 MNS 主题 ARN 或 阿里云 FC 函数 ARN。有关更多信息,请参阅 ALIYUN::ROS::CustomResource。服务令牌和输入数据的结构由custom resource provider定义。

  2. 当任何人使用模板创建、更新或删除自定义资源时,阿里云 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" }
       }
    }
    						
  3. 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"
       }
    }
  4. 获得 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上实现多云管理或是其他复杂逻辑都成为了可能。

作者介绍
目录