使用标签基于私网网段实现ECS相关费用分账

通过创建和执行系统运维管理(OOS)自定义模板,您可以为某个网段中的ECS实例及相关资源(云盘、弹性网卡、弹性公网IP和快照)绑定标签,然后根据标签查看费用账单。

背景信息

企业需要统计每个项目组在每月使用的ECS实例及相关资源(云盘、弹性网卡、弹性公网IP和快照)的费用,已知现阶段每个项目组单独使用一个IP网段,希望可以基于IP网段维度去统计关联的ECS资源及其费用。

您可以为某个IP网段中的ECS实例及相关资源绑定标签,然后按照标签汇总某个IP网段中ECS资源的费用。该操作可以通过系统运维管理(OOS)快速完成。

使用限制

默认情况下,某地域的OOS负责管理本地域的资源。例如,华东1(杭州)的OOS默认管理华东1(杭州)的ECS实例。但是,作为例外,用户可以在模板ExecuteAPI里指定RegionId的值,来调用其他地域的OpenAPI(不建议这样做)。因此,此处OOS的地域需要与RocketMQ实例地域保持一致。关于OOS的使用限制,请参见使用限制

操作步骤

  1. 登录OOS控制台,创建自定义模板和执行。

    1. 在左侧导航栏,选择自动化任务>自定义任务模板

    2. 创建子模板ECS_TagEcsResourcesByInstanceAndIpCIDR。

      YAML格式模板示例,请参见子模板:ECS_TagEcsResourcesByInstanceAndIpCIDR。创建模板的具体操作,请参见创建模板

    3. 创建父模板ECS_TagEcsResourcesByIpCIDRs,父模板中会嵌套以上子模板。

      YAML格式模板示例,请参见父模板:ECS_TagEcsResourcesByIpCIDRs。创建模板的具体操作,请参见创建模板

    4. 对父模板ECS_TagEcsResourcesByIpCIDRs创建执行。

      您需要配置以下信息:

      • 选择地域。

      • 输入IP网段及其所需要绑定的标签。

      创建执行的具体操作,请参见执行概述

  2. 登录ECS控制台,选择对应地域,查看目标ECS实例及相关资源是否已成功绑定了对应标签。

  3. 登录费用与成本,以标签维度查看费用账单。

    具体操作,请参见查看标签分账账单

子模板:ECS_TagEcsResourcesByInstanceAndIpCIDR

模板名称:ECS_TagEcsResourcesByInstanceAndIpCIDR

模板说明:通过输入地域ID、实例ID、标签(支持多个)和IP网段,判断ECS实例ID是否在该IP网段内。如果在IP网段内,将为该ECS实例及相关资源(磁盘、快照、弹性网卡和弹性公网IP )绑定输入的标签。

模板内容:

FormatVersion: OOS-2019-06-01
Description: 按照输入网段和实例ID过滤ECS实例,并且给符合条件的实例以及其关联资源打上相应标签。
Parameters:
  regionId:
    Description:
      name-en: The id of region
      name-zh-cn: 地域ID
    Type: String
    AssociationProperty: RegionId
    Default: '{{ ACS::RegionId }}'
  OOSAssumeRole:
    Description: OOS扮演的RAM角色
    Type: String
    Default: OOSServiceRole
  tags:
    Type: Json
    AssociationProperty: Tags
    Description: 所需操作的标签
  ipCidr:
    Type: String
    Description: 网段
  instanceId:
    Type: String
    AssociationProperty: ALIYUN::ECS::Instance::InstanceId
    AssociationPropertyMetadata:
      RegionId: regionId
RamRole: '{{ OOSAssumeRole }}'
Tasks:
  - Name: getEcsInstance
    Action: ACS::ExecuteAPI
    Description: DescribeInstances
    Properties:
      Service: ECS
      API: DescribeInstances
      Parameters:
        RegionId: '{{ regionId }}'
        InstanceIds:
          - '{{instanceId}}'
    Outputs:
      getIpAddressAndInstanceId:
        Type: Json
        ValueSelector: '.Instances.Instance | map(select(.InstanceId=="{{instanceId}}") ) | .[] |  {"InstanceId": .InstanceId,"PrivateIpAddress": .NetworkInterfaces.NetworkInterface[].PrivateIpSets.PrivateIpSet[].PrivateIpAddress}'
  - Name: isIpInCidr
    Action: ACS::Choice
    Properties:
      DefaultTask: ACS::END
      Choices:
        - When:
            Fn::And:
              - Fn::Not:
                  Fn::Equals:
                    - Null
                    - '{{getEcsInstance.getIpAddressAndInstanceId}}'
              - Fn::IsIpInCIDR:
                  - Fn::Jq:
                      - First
                      - .PrivateIpAddress
                      - '{{getEcsInstance.getIpAddressAndInstanceId}}'
                  - '{{ipCidr}}'
          NextTask: tagEcsInstance
  - Name: tagEcsInstance
    Action: ACS::ExecuteAPI
    Description: Tag Ecs InstanceId
    Properties:
      Service: ECS
      API: TagResources
      Parameters:
        RegionId: '{{ regionId }}'
        ResourceIds:
          - '{{instanceId}}'
        Tags: '{{tags}}'
        ResourceType: Instance
    Outputs:
      reqResult:
        Type: Json
        ValueSelector: .RequestId
  - Name: tagDisk
    Action: ACS::Template
    Description:
      en: Update disk tags by ecs instance tags
      zh-cn: 通过云服务器标签同步更新磁盘标签
    Properties:
      TemplateName: ACS::ECS::UpdateDiskTagsByEcsInstanceTags
      Parameters:
        regionId: '{{ regionId }}'
        instanceId: '{{instanceId}}'
        tagKeys:
          Fn::Jq:
            - All
            - .[].Key
            - '{{tags}}'
        isUpdate: true
  - Name: tagSnapshot
    Action: ACS::Template
    Description:
      en: Update snapshot tags by ecs instance tags
      zh-cn: 通过云服务器标签同步更新快照标签
    Properties:
      TemplateName: ACS::ECS::UpdateSnapshotTagsByEcsInstanceTags
      Parameters:
        regionId: '{{ regionId }}'
        instanceId: '{{instanceId}}'
        tagKeys:
          Fn::Jq:
            - All
            - .[].Key
            - '{{tags}}'
        isUpdate: true
  - Name: tagENI
    Action: ACS::Template
    Description:
      en: Update eni tags by ecs instance tags
      zh-cn: 通过云服务器标签同步更新ENI标签
    OnSuccess: ACS::END
    Properties:
      TemplateName: ACS::ECS::UpdateEniTagsByEcsInstanceTags
      Parameters:
        regionId: '{{ regionId }}'
        instanceId: '{{instanceId}}'
        tagKeys:
          Fn::Jq:
            - All
            - .[].Key
            - '{{tags}}'
        isUpdate: true
  - Name: tagEIP
    Action: ACS::Template
    Description:
      en: Update eip tags By ecs instance tags
      zh-cn: 通过云服务器标签同步更新EIP标签
    Properties:
      TemplateName: ACS::ECS::UpdateEipTagsByEcsInstanceTags
      Parameters:
        regionId: '{{ regionId }}'
        instanceId: '{{instanceId}}'
        tagKeys:
          Fn::Jq:
            - All
            - .[].Key
            - '{{tags}}'
        isUpdate: true
Outputs:
  invocationOutputs:
    Type: Json
    Value: '{{ getEcsInstance.getIpAddressAndInstanceId }}'
  tags:
    Type: Json
    Value: '{{tags}}'

父模板:ECS_TagEcsResourcesByIpCIDRs

模板名称:ECS_TagEcsResourcesByIpCIDRs

模板说明:通过输入地域ID、IP网段、以及每个网段所需要绑定的标签,查询该地域的所有ECS实例。如果ECS实例包含输入的网段,则为ECS实例绑定相应的标签。

模板内容:

FormatVersion: OOS-2019-06-01
Description: 按照输入网段和网段资源对应标签,并且给符合该网段的实例以及其关联资源绑定相应标签。
Parameters:
  regionId:
    Description: 地域ID
    Type: String
    AssociationProperty: RegionId
    Default: '{{ ACS::RegionId }}'
  OOSAssumeRole:
    Description: OOS扮演的RAM角色
    Type: String
    Default: OOSServiceRole
  ipCidrAndTags:
    Type: Json
    Description: |-
      所需操作的标签 示例:[
        {
          "ipCidr": "192.168.0.0/16",
          "tags": [
            {
              "Value": "testALL",
              "Key": "project"
            }
          ]
        }
      ]
RamRole: '{{ OOSAssumeRole }}'
Tasks:
  - Name: getEcsInstance
    Description:
      en: Views the ECS instances.
      zh-cn: 获取ECS实例。
    Action: ACS::SelectTargets
    Properties:
      ResourceType: ALIYUN::ECS::Instance
      Filters:
        - Type: All
          RegionId: '{{regionId}}'
          Parameters:
            RegionId: '{{regionId}}'
    Outputs:
      desData:
        Type: Json
        ValueSelector: '.Instances.Instance | [.[].InstanceId] as $tmpData | {{ipCidrAndTags}} |[{"ipCidr":.[].ipCidr, "tags":.[].tags, "instanceId": $tmpData[] }]'
  - Name: tagByIpCidr
    Action: ACS::Template
    Description: Tag Instance and related Resources
    OnSuccess: ACS::END
    Properties:
      TemplateName: ECS_TagEcsResourcesByInstanceAndIpCIDR
      Parameters:
        regionId: '{{ regionId }}'
        tags:
          Fn::Jq:
            - All
            - .tags[]
            - '{{ACS::TaskLoopItem}}'
        ipCidr:
          Fn::Jq:
            - First
            - .ipCidr
            - '{{ACS::TaskLoopItem}}'
        instanceId:
          Fn::Jq:
            - First
            - .instanceId
            - '{{ACS::TaskLoopItem}}'
    Loop:
      RateControl:
        Mode: Concurrency
        MaxErrors: 100
        Concurrency: 1
      Items: '{{getEcsInstance.desData}}'
      Outputs:
        tagResult:
          AggregateType: Fn::ListJoin
          AggregateField: reqResult
Outputs:
  tags:
    Type: Json
    Value: '{{getEcsInstance.desData}}'