すべてのプロダクト
Search
ドキュメントセンター

Elastic Compute Service:再生するプリエンプティブルインスタンスからカスタムイメージを作成し、そのカスタムイメージから新しいインスタンスを作成してプリエンプティブルインスタンスのデータを復元します。

最終更新日:Aug 27, 2024

プリエンプティブルインスタンスは、価格の変動または市場の需要と供給の変化により、強制的に回収される可能性があります。 プリエンプティブルインスタンスに保存されているデータの損失を防ぐために、プリエンプティブルインスタンスからカスタムイメージを作成し、プリエンプティブルインスタンスの割り込みイベントに基づいてモニタリングメカニズムを設定できます。 プリエンプティブルインスタンスの中断イベントが受信された後、システムは、ソースプリエンプティブルインスタンスのデータを復元するためにカスタムイメージを使用することによって、新しいプリエンプティブルインスタンスを作成することができる。

働くメカニズム

プリエンプティブルインスタンスを使用すると、価格の変動や市場の需要と供給の変化により、インスタンスが強制的に回収されることがあります。 インスタンスが完全に再利用される前に、インスタンスはロック状態になり、インスタンスに対して割り込みイベントがトリガーされます。

中断イベントに基づいて監視メカニズムを設定できます。 プリエンプティブインスタンスの割り込みイベントを受信した後、システムは、コンパイルしたSDK for Java 2.0コードを使用して、プリエンプティブインスタンスからカスタムイメージを作成し、カスタムイメージから新しいプリエンプティブインスタンスを作成できます。 これにより、ソースプリエンプティブルインスタンスに保存されているデータを復元できます。

次の図は、上記のシナリオのO&Mワークフローを示しています。

image

前提条件

  • Alibaba Cloudアカウントが作成され、アカウントのAccessKeyペアが取得されます。

    Alibaba CloudアカウントのAccessKeyペアを設定して、Alibaba Cloud Elastic Compute Service (ECS) SDK for Javaを使用する必要があります。 AccessKeyペアの取得方法については、「AccessKeyペアの取得」をご参照ください。

  • 環境変数が設定されます。 詳細については、「Alibaba Cloud Darabonba SDK For Javaの使用を開始する」トピックの手順2: 環境変数の設定セクションをご参照ください。

  • 開発環境には、ECS SDK for Java 2.0がインストールされています。

    次の依存関係をMavenプロジェクトに追加する必要があります。 詳細については、「Alibaba Cloud SDK V2.0 For Javaの統合」をご参照ください。

    <dependencies>
        <dependency>
            <groupId>com.aliyun</groupId>
            <artifactId>ecs20140526</artifactId>
            <version>5.1.8</version>
        </dependency>
    
        <dependency>
            <groupId>com.google.guava</groupId>
            <artifactId>guava</artifactId>
            <version>20.0</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.4</version>
        </dependency>
    
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-lang3</artifactId>
            <version>3.5</version>
        </dependency>
    
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>fastjson</artifactId>
            <version>1.2.83</version>
        </dependency>
    
    </dependencies> 

注意事項

重要

このトピックのサンプルコードは、参照のみに使用されます。 カスタムイメージ作成プロセスとデータ復元プロセスは、完了するのに5分以上かかる場合があります。

プリエンプティブルインスタンスに対して割り込みイベントがトリガーされた後、インスタンスが完全に要求される少なくとも5分前に通知が送信されます。 ただし、データの復元に必要な時間は、インスタンスのイメージタイプとシステムディスクのサイズによって異なります。 システムディスクのサイズが大きいほど、データの復元に時間がかかります。 サンプルコードを使用する前に、データ復元の効果を評価して確認してください。

手順1: プリエンプティブルインスタンスの作成

このステップでは、CreateSpotInstance Javaクラスが使用されます。 次のサンプルコードは、RunInstances操作を呼び出してプリエンプティブルインスタンスを作成する方法の例を示しています。

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.RunInstancesRequest;
import com.aliyun.ecs20140526.models.RunInstancesResponse;

public class CreateSpotInstance {
    static Client client;
    // Specify the ID of the region in which to create the preemptible instance.  
    static String regionId = "cn-hangzhou";
    // Specify the ID of the zone in which to create the preemptible instance.  
    static String zoneId = "cn-hangzhou-i";
    // Specify the instance type of the preemptible instance. 
    static String instanceType = "ecs.e-c1m1.large";
    // Specify the ID of the image to use to create the preemptible instance. 
    static String imagesId = "aliyun_3_9_x64_20G_alibase_20231219.vhd";
    // Specify the ID of the vSwitch to which to connect the preemptible instance. 
    static String vSwitchId = "<your-vSwitchId>";
    // Specify the ID of the security group to which to assign the preemptible instance. 
    static String securityGroupId = "<your-securityGroupId>";
    // Specify a preemption policy. 
    static String spotStrategy = "SpotAsPriceGo";
    // Specify the protection period of the preemptible instance. If you cannot determine the protection period, set the value to 0. 
    static Integer spotDuration = 0;
    // Specify the logon password of the preemptible instance. 
    static String password = "<your-password>";

    public static void main(String[] args) throws Exception {
        client = createClient();
        createInstance();
    }

    private static Client createClient() throws Exception {
        // If the project code is leaked, the AccessKey pair may be leaked and the security of all resources in your account may be compromised. The following sample code is provided for reference only. 
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
            // Required. Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is configured in the code runtime environment. 
            .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
            // Required. Make sure that the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is configured in the code runtime environment. 
            .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        // Specify an endpoint. For information about endpoints, see the topic at the following URL: https://api.alibabacloud.com/product/Ecs.
        config.endpoint = "ecs-cn-hangzhou.aliyuncs.com";
        return new Client(config);
    }

    // Create a preemptible instance. 
    public static String createInstance() {
        try {
            // Configure the parameters of the RunInstances operation and send the request. 
            RunInstancesRequest request = new RunInstancesRequest();
            request.setRegionId(regionId);
            request.setZoneId(zoneId);
            request.setInstanceType(instanceType);
            request.setSpotDuration(spotDuration);
            request.setSpotStrategy(spotStrategy);
            request.setImageId(imagesId);
            request.setVSwitchId(vSwitchId);
            request.setSecurityGroupId(securityGroupId);
            // The preemption policy takes effect only when the InstanceChargeType parameter is set to PostPaid. 
            request.setInstanceChargeType("PostPaid");
            request.setPassword(password);
            request.setInternetMaxBandwidthOut(1);
            // Obtain the response and the instance ID. 
            RunInstancesResponse response = client.runInstances(request);
            if (null == response.getBody().getInstanceIdSets() || response.getBody().getInstanceIdSets().getInstanceIdSet().isEmpty()) {
                return null;
            }
            String instanceId = response.getBody().getInstanceIdSets().getInstanceIdSet().get(0);
            System.out.println("<Instance ID>:" + instanceId);
            return instanceId;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

ステップ2: 中断イベントが検出された後にカスタムイメージを自動的に作成する

このステップでは、CreateSpotImage Javaクラスが使用されます。 次の操作が順番に呼び出されます。

  • DescribeInstances操作を呼び出して、プリエンプティブルインスタンスのステータスを監視します。

  • プリエンプティブルインスタンスの中断イベントが検出されたら、CreateImage操作を呼び出して、プリエンプティブルインスタンスからカスタムイメージを作成します。

  • カスタムイメージを作成したら、DescribeImagesを呼び出して、カスタムイメージのステータスを監視します。 カスタムイメージが使用可能状態になると、メッセージが返されます。

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.CreateImageRequest;
import com.aliyun.ecs20140526.models.CreateImageResponse;
import com.aliyun.ecs20140526.models.DescribeImagesRequest;
import com.aliyun.ecs20140526.models.DescribeImagesResponse;
import com.aliyun.ecs20140526.models.DescribeImagesResponseBody.DescribeImagesResponseBodyImagesImage;
import com.aliyun.ecs20140526.models.DescribeInstancesRequest;
import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstanceOperationLocksLockReason;
import com.google.common.collect.Lists;
import org.apache.commons.collections4.CollectionUtils;

import java.util.List;

import com.alibaba.fastjson.JSON;

public class CreateSpotImage {
    static Client client;
    // Specify the region ID of the preemptible instance. 
    static String regionId = "cn-hangzhou";
    // Specify the ID of the preemptible instance. 
    static String instanceId = "<your-instanceId>";

    public static void main(String[] args) throws Exception {
        client = createClient();
        // Step 1: Wait for the preemptible instance to enter the To Be Released state and an interruption event to be generated. 
        waitForInstanceMarked();
        System.out.println("spot instance will be recycled immediately, instance id:" + instanceId);
        // Step 2: Create a custom image from the preemptible instance when an interruption event is triggered for the preemptible instance. 
        String image1 = createImage();
        // Step 3: Wait until the custom image is created. 
        waitCreateImageSuccess(image1);
    }

    private static Client createClient() throws Exception {
        // If the project code is leaked, the AccessKey pair may be leaked and the security of all resources in your account may be compromised. The following sample code is provided for reference only. 
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
            // Required. Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is configured in the code runtime environment. 
            .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
            // Required. Make sure that the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is configured in the code runtime environment. 
            .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        // Specify an endpoint. For information about endpoints, see the topic at the following URL: https://api.alibabacloud.com/product/Ecs.
        config.endpoint = "ecs-cn-hangzhou.aliyuncs.com";
        return new Client(config);
    }

    // Monitor the status of the preemptible instance and obtain the details of the instance when an interruption event occurs. 
    public static void waitForInstanceMarked() {
        // Convert the instance ID to a JSON string. 
        List<String> instanceIds = Lists.newArrayList();
        instanceIds.add(instanceId);
        String instanceIdStr = JSON.toJSONString(instanceIds);
        boolean isMarked = false;
        // Determine whether an interruption event occurs on the preemptible instance. 
        while (!isMarked) {
            try {
                // Configure the parameters of the DescribeInstances operation and send the request. 
                DescribeInstancesRequest request = new DescribeInstancesRequest();
                // Specify the region ID of the preemptible instance. 
                request.setRegionId(regionId);
                // Specify the ID of the preemptible instance to query the details of the instance. 
                request.setInstanceIds(instanceIdStr);
                // Obtain the response. 
                DescribeInstancesResponse response = client.describeInstances(request);
                // Obtain the response data of the preemptible instance. 
                DescribeInstancesResponseBodyInstances instances = response.getBody().getInstances();
                // If the details of the instance are not found, break out of the loop. 
                if (CollectionUtils.isEmpty(instances.getInstance())) {
                    break;
                }
                DescribeInstancesResponseBodyInstancesInstance instance = instances.getInstance().get(0);
                // If the instance is not interrupted, restart the loop. 
                if (instance.getOperationLocks() == null || instance.getOperationLocks().getLockReason().size() == 0) {
                    continue;
                }
                for (DescribeInstancesResponseBodyInstancesInstanceOperationLocksLockReason lockReason : instance
                    .getOperationLocks().getLockReason()) {
                    // If the instance is interrupted, the ID of the instance and the cause of the interruption are displayed. 
                    System.out.println("instance:" + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",vmStatus:" + instance.getStatus());
                    if ("Recycling".equals(lockReason.getLockReason())) {
                        isMarked = true;
                    }
                }

                Thread.sleep(2 * 1000);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // Create a custom image. 
    public static String createImage() {
        try {
            // Configure the parameters of the CreateImage operation and send the request. 
            CreateImageRequest request = new CreateImageRequest();
            request.setRegionId(regionId);
            request.setInstanceId(instanceId);
            // Obtain the response and the image ID. 
            CreateImageResponse response = client.createImage(request);
            System.out.println("imageID:" + response.getBody().getImageId());
            return response.getBody().getImageId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // Check whether the custom image is created. 
    public static void waitCreateImageSuccess(String imageId) {
        boolean isSuccess = false;
        while (!isSuccess) {
            DescribeImagesResponseBodyImagesImage image = describeImage(imageId);
            if (null == image) {
                System.err.println("image not exist. imageId: " + imageId);
                break;
            }
            if ("Available".equals(image.getStatus())) {
                System.out.println("Image created successfully.");
                isSuccess = true;
            }
        }
    }

    // Call the DescribeImages operation to query the status of the custom image. 
    public static DescribeImagesResponseBodyImagesImage describeImage(String imageId) {
        try {
            Thread.sleep(6 * 60 * 1000);
            DescribeImagesRequest imagesRequest = new DescribeImagesRequest();
            imagesRequest.setRegionId(regionId);
            imagesRequest.setImageId(imageId);
            imagesRequest.setPageSize(100);
            DescribeImagesResponse imagesResponse = client.describeImages(imagesRequest);
            if (null == imagesResponse.getBody().getImages() || CollectionUtils.isEmpty(imagesResponse.getBody().getImages().getImage())) {
                return null;
            }
            return imagesResponse.getBody().getImages().getImage().get(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

手順3: カスタムイメージを使用してプリエンプティブルインスタンスを作成し、データを復元する

このステップでは、CreateSpotInstanceFromImage Javaクラスが使用されます。 次のサンプルコードは、RunInstances操作を呼び出して、カスタムイメージを使用してプリエンプティブルインスタンスを作成する方法の例を示しています。

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.RunInstancesRequest;
import com.aliyun.ecs20140526.models.RunInstancesResponse;

public class CreateSpotInstanceFromImage {
    static Client client;
    // Specify the ID of the region in which to create the instance. We recommend that you create the instance in the same region as the source preemptible instance. 
    static String regionId = "cn-hangzhou";
    // Specify the ID of the zone in which to create the instance. We recommend that you create the instance in the same zone as the source preemptible instance. 
    static String zoneId = "cn-hangzhou-i";
    // Specify the instance type of the preemptible instance. 
    static String instanceType = "ecs.s6-c1m1.small";
    // Specify the ID of the custom image. 
    static String imagesId = "<your-imagesId>";
    // Specify the ID of the vSwitch to which to connect the preemptible instance. 
    static String vSwitchId = "<your-vSwitchId>";
    // Specify the ID of the security group to which to assign the preemptible instance. 
    static String securityGroupId = "<your-securityGroupId>";
    // Specify a preemption policy. 
    static String spotStrategy = "SpotAsPriceGo";
    // Specify the protection period of the preemptible instance. If you cannot determine the protection period, set the value to 0. 
    static Integer spotDuration = 0;
    // Specify the logon password of the preemptible instance. 
    static String password = "<your-password>";


    public static void main(String[] args) throws Exception {
        client = createClient();
        createInstance();
    }

    private static Client createClient() throws Exception {
        // If the project code is leaked, the AccessKey pair may be leaked and the security of all resources in your account may be compromised. The following sample code is provided for reference only. 
        com.aliyun.teaopenapi.models.Config config = new com.aliyun.teaopenapi.models.Config()
            // Required. Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is configured in the code runtime environment. 
            .setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
            // Required. Make sure that the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is configured in the code runtime environment. 
            .setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        // Specify an endpoint. For information about endpoints, see the topic at the following URL: https://api.alibabacloud.com/product/Ecs.
        config.endpoint = "ecs-cn-hangzhou.aliyuncs.com";
        return new Client(config);
    }

    //Call the RunInstances operation to create an instance. 
    public static String createInstance() {
        try {
            RunInstancesRequest request = new RunInstancesRequest();
            request.setRegionId(regionId);
            request.setZoneId(zoneId);
            request.setInstanceType(instanceType);
            request.setSpotDuration(spotDuration);
            request.setSpotStrategy(spotStrategy);
            request.setImageId(imagesId);
            request.setVSwitchId(vSwitchId);
            request.setSecurityGroupId(securityGroupId);
            request.setInstanceChargeType("PostPaid");
            request.setPassword(password);
            request.setInternetMaxBandwidthOut(1);
            RunInstancesResponse response = client.runInstances(request);
            if (null == response.getBody().getInstanceIdSets() || response.getBody().getInstanceIdSets().getInstanceIdSet().isEmpty()) {
                return null;
            }
            String instanceId = response.getBody().getInstanceIdSets().getInstanceIdSet().get(0);
            System.out.println("<Instance ID>: " + instanceId);;
            return instanceId;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}