サブスクリプション課金方法の ECS インスタンスにとって、ライフサイクルは重要です。 Alibaba Cloud は、ECS コンソールや ECS 購入ページに加え、有効期限の表示やインスタンス更新のAPIを提供します。

ここでは、以下のキー機能が関係しています。

  • 有効期限による ECS インスタンスの照会
  • インスタンスの更新
  • ECS インスタンスの自動更新時間の照会
  • ECS インスタンスの自動更新時間の設定

ライフサイクルはサブスクリプションモードの ECS インスタンスにとって重要です。 ECS インスタンスの更新が間に合わず、そのインスタンスがロックもしくはリリースされてしまうと、お客様のサービスの継続性に影響するかもしれません。 API を使用して、リソースの有効期限を表示したりインスタンスを更新したりすることができます。

ここでは、以下の API について説明します。

指定した期間内に有効期限が切れるインスタンスの照会

指定した期間内に有効期限が切れるインスタンスを照会するためには、"DescribeInstances" インターフェイスを使用して、フィルターパラメータである "ExpiredStartTime""ExpiredEndTime" を設定します。 これらのパラメーターは、 ISO8601 規格の UTC 時間で、フォーマットは "yyyy-MM-ddTHH:mmZ" を用います。 システムは指定した期間内に有効期限が切れるインスタンスのリストを返します。 セキュリティグループでフィルタする場合は、セキュリティグループ ID を追加します。

INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING = '2017-01-22T00:00Z'
INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING = '2017-01-28T00:00Z'
def describe_need_renew_instance(page_size=100, page_number=1, instance_id=None,
                                 check_need_renew=True, security_group_id=None):
    request = DescribeInstancesRequest()
    if check_need_renew is True:
        request.set_Filter3Key("ExpiredStartTime")
        request.set_Filter3Value(INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING)
        request.set_Filter4Key("ExpiredEndTime")
        request.set_Filter4Value(INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING)
    if instance_id is not None:
        request.set_InstanceIds(json.dumps([instance_id]))
    if security_group_id:
        request.set_SecurityGroupId(security_group_id)
    request.set_PageNumber(page_number)
    request.set_PageSize(page_size)
    return _send_request(request)

ECS インスタンスの更新

サブスクリプションモードの ECS インスタンスのみの更新が可能です。 従量課金のインスタンスの更新はできません。 更新にはアカウント残高もしくはクレジットでのお支払いが必要です。 API の実行と同時に、料金の引き落としと請求が行われます。 ご自身のアカウントに十分な残高があることをご確認ください。

def _renew_instance_action(instance_id, period='1'):
    request = RenewInstanceRequest()
    request.set_Period(period)
    request.set_InstanceId(instance_id)
    response = _send_request(request)
    logging.info('renew %s ready, output is %s ', instance_id, response)

インスタンスが更新された際に、料金は自動的に引き落とされます。 更新完了後、"InstanceId" に基づいてインスタンスの有効期限を照会することができます。 API が非同期的に実行されるため、有効期限の更新は 10 秒以内に行われます。

ECS インスタンスの自動更新の有効化

Alibaba Cloud は、期限切れリソースの管理費用の削減に寄与するために、サブスクリプションモードの ECS インスタンスで「自動更新機能」を提供しています。 自動更新の料金の引き落としは、有効期限より 9 日前の 08:00:00 に開始します。 初日に料金の引き落としに失敗した場合、引き落とし処理は料金が正常に引き落とされるまで毎日繰り返され、引き落としができずに 9 日後の期限を迎えた場合、リソースがロックされます。 アカウントに十分な残高とクレジットがあることをご確認ください。

  • 自動更新設定の照会

    "OpenAPI" を使用して自動更新の照会と設定が行えます。 この API はサブスクリプションモードの ECS インスタンスにのみ対応しています。 従量課金インスタンスにこの API を使用した場合は、エラーが返されます。 サブスクリプション課金方法である ECS インスタンスの自動更新ステータスを、一度に最大 100 個照会することができます。 複数のインスタンス ID はコンマで区切ります。

    "DescribeInstanceAutoRenewAttribut" の入力パラメータはインスタンス ID です。

    InstanceId: サブスクリプションモードの ECS インスタンスを 100 個まで一括で照会することができます。 複数のインスタンス ID はコンマで区切ります。

    # check the instances is renew or not
    def describe_auto_renew(instance_ids, expected_auto_renew=True):
        describe_request = DescribeInstanceAutoRenewAttributeRequest()
        describe_request.set_InstanceId(instance_ids)
        response_detail = _send_request(request=describe_request)
        failed_instance_ids = ''
        if response_detail is not None:
            attributes = response_detail.get('InstanceRenewAttributes').get('InstanceRenewAttribute')
            if attributes:
                for item in attributes:
                    auto_renew_status = item.get('AutoRenewEnabled')
                    if auto_renew_status ! = expected_auto_renew:
                        failed_instance_ids += item.get('InstanceId') + ','
    
    describe_auto_renew('i-1111,i-2222')

    以下の内容が返されます。

    {"InstanceRenewAttributes":{"InstanceRenewAttribute":[{"Duration":0,"InstanceId":"i-1111","AutoRenewEnabled":false},{"Duration":0,"InstanceId":"i-2222","AutoRenewEnabled":false}]},"RequestId":"71FBB7A5-C793-4A0D-B17E-D6B426EA746A"}

    自動更新が設定されている場合、返される属性 "AutoRenewEnabled" は "true" です。 自動更新が設定されていない場合、属性は "false" になります。

  • ECS インスタンスの自動更新の有効化とキャンセル

    ECS インスタンスの自動更新を有効にするには、3 つの入力パラメーターが必要です:

    • InstanceId: サブスクリプションモード中の ECS インスタンスを一括で 100 個まで照会することができます。 複数のインスタンス ID はコンマで区切ります。
    • Duration: 月単位で 1、2、3、6、または 12 を設定します。
    • AutoRenew: 自動更新を有効にするには "true" に設定します。 自動更新を無効にするには "false" に設定します。
    def setting_instance_auto_renew(instance_ids, auto_renew = True):
        logging.info('execute enable auto renew ' + instance_ids)
        request = ModifyInstanceAutoRenewAttributeRequest();
        request.set_Duration(1);
        request.set_AutoRenew(auto_renew);
        request.set_InstanceId(instance_ids)
        _send_request(request)

    操作が成功すると、以下のレスポンスが返されます:

    {"RequestId":"7DAC9984-AAB4-43EF-8FC7-7D74C57BE46D"}

    更新に成功すると、照会を実行することができます。 システムは更新時間と自動更新のステータス ( TRUE / FALSE ) を返します。

    {"InstanceRenewAttributes":{"InstanceRenewAttribute":[{"Duration":1,"InstanceId":"i-1111","AutoRenewEnabled":true},{"Duration":1,"InstanceId":"i-2222","AutoRenewEnabled":true}]},"RequestId":"7F4D14B0-D0D2-48C7-B310-B1DF713D4331"}

完全なサンプルコード

# coding=utf-8
# if the python sdk is not install using 'sudo pip install aliyun-python-sdk-ecs'
# if the python sdk is install using 'sudo pip install --upgrade aliyun-python-sdk-ecs'
# make sure the sdk version is 2.1.2, you can use command 'pip show aliyun-python-sdk-ecs' to check
import json
import logging
from aliyunsdkcore import client
from aliyunsdkecs.request.v20140526. DescribeInstanceAutoRenewAttributeRequest import \
    DescribeInstanceAutoRenewAttributeRequest
from aliyunsdkecs.request.v20140526. DescribeInstancesRequest import DescribeInstancesRequest
from aliyunsdkecs.request.v20140526. ModifyInstanceAutoRenewAttributeRequest import \
    ModifyInstanceAutoRenewAttributeRequest
from aliyunsdkecs.request.v20140526. RenewInstanceRequest import RenewInstanceRequest
logging.basicConfig(level=logging.INFO,
                    format='%(asctime)s %(filename)s[line:%(lineno)d] %(levelname)s %(message)s',
                    datefmt='%a, %d %b %Y %H:%M:%S')
clt = client.AcsClient('Your Access Key Id', 'Your Access Key Secrect', 'cn-beijing')
# data format in UTC, only support passed the value for minute, seconds is not support.
INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING = '2017-01-22T00:00Z'
INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING = '2017-01-28T00:00Z'
def renew_job(page_size=100, page_number=1, check_need_renew=True, security_group_id=None):
    response = describe_need_renew_instance(page_size=page_size, page_number=page_number,
                                            check_need_renew=check_need_renew,
                                            security_group_id=security_group_id)
    response_list = response.get('Instances').get('Instance')
    logging.info("%s instances need to renew", str(response.get('TotalCount')))
    if response_list > 0:
        instance_ids = ''
        for item in response_list:
            instance_id = item.get('InstanceId')
            instance_ids += instance_id + ','
            renew_instance(instance_id=instance_id)
        logging.info("%s execute renew action ready", instance_ids)
def describe_need_renew_instance(page_size=100, page_number=1, instance_id=None,
                                 check_need_renew=True, security_group_id=None):
    request = DescribeInstancesRequest()
    if check_need_renew is True:
        request.set_Filter3Key("ExpiredStartTime")
        request.set_Filter3Value(INSTANCE_EXPIRED_START_TIME_IN_UTC_STRING)
        request.set_Filter4Key("ExpiredEndTime")
        request.set_Filter4Value(INSTANCE_EXPIRE_END_TIME_IN_UTC_STRING)
    if instance_id is not None:
        request.set_InstanceIds(json.dumps([instance_id]))
    if security_group_id:
        request.set_SecurityGroupId(security_group_id)
    request.set_PageNumber(page_number)
    request.set_PageSize(page_size)
    return _send_request(request)
# check the instances is renew or not
def describe_instance_auto_renew_setting(instance_ids, expected_auto_renew=True):
    describe_request = DescribeInstanceAutoRenewAttributeRequest()
    describe_request.set_InstanceId(instance_ids)
    response_detail = _send_request(request=describe_request)
    failed_instance_ids = ''
    if response_detail is not None:
        attributes = response_detail.get('InstanceRenewAttributes').get('InstanceRenewAttribute')
        if attributes:
            for item in attributes:
                auto_renew_status = item.get('AutoRenewEnabled')
                if auto_renew_status ! = expected_auto_renew:
                    failed_instance_ids += item.get('InstanceId') + ','
    if len(failed_instance_ids) > 0:
        logging.error("instance %s auto renew not match expect %s.", failed_instance_ids,
                      expected_auto_renew)
def setting_instance_auto_renew(instance_ids, auto_renew=True):
    logging.info('execute enable auto renew ' + instance_ids)
    request = ModifyInstanceAutoRenewAttributeRequest();
    request.set_Duration(1);
    request.set_AutoRenew(auto_renew);
    request.set_InstanceId(instance_ids)
    _send_request(request)
    describe_instance_auto_renew_setting(instance_ids, auto_renew)
# if using the instance id can be found means the instance is not renew successfully.
def check_instance_need_renew(instance_id):
    response = describe_need_renew_instance(instance_id=instance_id)
    if response is not None:
        return response.get('TotalCount') == 1
    return False
# Renew an instance for a month
def renew_instance(instance_id, period='1'):
    need_renew = check_instance_need_renew(instance_id)
    if need_renew:
        _renew_instance_action(instance_id=instance_id, period=period)
        # describe_need_renew_instance(instance_id=instance_id, check_need_renew=False)
def _renew_instance_action(instance_id, period='1'):
    request = RenewInstanceRequest()
    request.set_Period(period)
    request.set_InstanceId(instance_id)
    response = _send_request(request)
    logging.info('renew %s ready, output is %s ', instance_id, response)
def _send_request(request):
    request.set_accept_format('json')
    try:
        response_str = clt.do_action(request)
        logging.info(response_str)
        response_detail = json.loads(response_str)
        return response_detail
    except Exception as e:
        logging.error(e)
if __name__ == '__main__':
    logging.info("Renew ECS Instance by OpenApi!")
    # Query whether there is any instance that needs to be renewed within the specified time range.
    describe_need_renew_instance()
    # Renew an instance by direct fee deduction
    renew_instance('i-1111')
    # Query the status of automatic renewal
    # describe_instance_auto_renew_setting('i-1111,i-2222')
    # Set automatic instance renewal
    # setting_instance_auto_renew('i-1111,i-2222')

ECS の他の API 操作については、「ECS API の操作」をご参照ください。