All Products
Search
Document Center

Elastic Compute Service:Create a custom image from a system disk snapshot of a reclaimed preemptible instance and then create a new instance from the custom image to restore the data of the reclaimed preemptible instance

Last Updated:Jul 05, 2024

Preemptible instances may be forcefully reclaimed due to price fluctuations or changes in market supply and demand. To prevent loss of data stored on a preemptible instance, you can create a snapshot for the system disk of the instance and then create a custom image from the snapshot. Then, you can create a preemptible instance from the custom image to restore the data stored on the source preemptible instance.

Working mechanism

When you use a preemptible instance, the instance may be forcefully reclaimed due to price fluctuations or changes in market supply and demand. Before the instance is fully reclaimed, it enters the Locked state and an interruption event is triggered for the instance.

You can configure a monitoring mechanism based on interruption events, and configure the system disk not to be released together with the instance when the instance runs as expected. After an interruption event of the preemptible instance is received, the system uses SDK for Java 2.0 code to create a snapshot for the system disk and create a custom image from the system disk snapshot. Then, you can create a preemptible instance from the custom image. This way, you can restore the data that is stored on the source preemptible instance.

Note

You can configure the system disk not to be released together with the preemptible instance. If the preemptible instance is released, the system disk snapshot and the custom image are not affected.

The following figure shows the O&M workflow in the preceding scenario.

image

Prerequisites

  • An Alibaba Cloud account is created and the AccessKey pair of the account is obtained.

    You must configure the AccessKey pair of your Alibaba Cloud account to use Alibaba Cloud Elastic Compute Service (ECS) SDK for Java. For information about how to obtain the AccessKey pair, see Create an AccessKey pair.

  • The ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables are configured. For more information, see the Step 2: Configure environment variables section of the "Get started with Alibaba Cloud Darabonba SDK for Java" topic.

  • ECS SDK for Java 2.0 is installed in the development environment.

    You must add the following dependencies to the Maven project. For more information, see Install and use ECS SDKs.

    <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>
    

Precautions

Important

The sample code in this topic is used for reference only. The custom image creation process and data restoration process may require more than 5 minutes to complete.

After an interruption event is triggered for a preemptible instance, notifications are sent at least 5 minutes before the instance is fully claimed. However, the amount of time required to restore data depends on the image type of the instance and the size of the system disk. The larger the size of the system disk, the longer it takes to restore data. Before you use the sample code, evaluate and verify the effect of data restoration.

Limits

The following limits apply when the data of a preemptible instance is restored before the instance is reclaimed:

  • To ensure that disk snapshots are not lost, we recommend that you disable the Delete Automatic Snapshots While Releasing Disk feature.

  • If the data disks of a preemptible instance contain important data, we recommend that you configure the data disks not to be released together with the instance.

  • If you call the ModifyDiskAttribute operation and set the DeleteWithInstance parameter to false for a disk and the instance to which the disk is attached is locked for security reasons, the DeleteWithInstance parameter is ignored and the disk will be released together with the instance. If the OperationLocks parameter in the DescribeInstances response contains "LockReason" : "security" for an instance, the instance is locked for security reasons.

    Note

    You can use the DiskIds.N parameter to modify the attributes of multiple block storage devices at a time. The attributes include the device names, device descriptions, and whether to release the devices together with the associated instances.

Step 1: Create a preemptible instance

In this step, the CreateSpotInstance Java class is used. The following sample code provides an example on how to create a preemptible instance by calling the RunInstances operation:

import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.ecs.model.v20140526.RunInstancesRequest;
import com.aliyuncs.ecs.model.v20140526.RunInstancesResponse;
import com.aliyuncs.profile.DefaultProfile;

/**
 * Call the RunInstances operation to create a preemptible instance. 
 */
public class CreateSpotInstance {

    static IAcsClient 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.s6-c1m1.small";
    // Specify the ID of the image to use to create the preemptible instance. 
    static String imagesId = "centos_7_6_x64_20G_alibase_20211130.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) {
        client = initialization();
        createInstance();
    }

    private static IAcsClient initialization() {
        /**
         * Initialize request parameters. 
         * Make sure that the ALIBABA_CLOUD_ACCESS_KEY_ID and ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variables are configured. 
         * 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 shows how to use environment variables to obtain an AccessKey pair and use the AccessKey pair to call API operations. We recommend that you use Security Token Service (STS) tokens, which provide higher security. 
         */
        DefaultProfile profile = DefaultProfile.getProfile(regionId, System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
        return new DefaultAcsClient(profile);
    }

    // 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 InstanceChargeType is set to PostPaid. 
            request.setInstanceChargeType("PostPaid");
            request.setPassword(password);
            request.setInternetMaxBandwidthOut(1);
            // Obtain the response and the instance ID. 
            RunInstancesResponse response = client.getAcsResponse(request);
            if (null == response.getInstanceIdSets() || response.getInstanceIdSets().isEmpty()) {
                return null;
            }
            String instanceId = response.getInstanceIdSets().get(0);
            System.out.println("Instance ID:" + instanceId);
            return instanceId;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }
}

Step 2: Configure the system disk not to be released together with the instance

In this step, the DiskRelated Java class is used. The following sample code provides an example on how to configure the system disk not to be released together with the instance by calling the ModifyDiskAttribute operation:

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.DescribeDisksRequest;
import com.aliyun.ecs20140526.models.DescribeDisksResponse;
import com.aliyun.ecs20140526.models.DescribeDisksResponseBody.DescribeDisksResponseBodyDisksDisk;
import com.aliyun.ecs20140526.models.ModifyDiskAttributeRequest;
import com.aliyun.ecs20140526.models.ModifyDiskAttributeResponse;
import org.apache.commons.collections4.CollectionUtils;

public class DiskRelated {
    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-instance-id>";
    static String instanceId = "i-bp18zj904wqnw5mc****";
    public static void main(String[] args) throws Exception {
        client = createClient();
        DescribeDisksResponseBodyDisksDisk disk = getDisks();
        if(null == disk){
            System.out.println("disk not exist");
            return;
        }
        String diskId = disk.getDiskId();
        modifyDiskAttribute(diskId);
        Boolean b = diskNotDeleteWithInstance();
        if(b){
            // Reconfigure the system disk not to be released together with the instance if the first-time configuration fails. 
            modifyDiskAttribute(diskId);
        }
    }

    /**
     * Query the details of the system disk. 
     */
    public static DescribeDisksResponseBodyDisksDisk getDisks(){
        DescribeDisksRequest request = new DescribeDisksRequest();
        request.setRegionId(regionId);
        request.setInstanceId(instanceId);
        request.setDiskType("system");
        try {
            DescribeDisksResponse response = client.describeDisks(request);

            if(CollectionUtils.isEmpty(response.getBody().getDisks().getDisk())){
                System.out.println(("disk not exist. instanceId: " + instanceId));
                return null;
            }
            DescribeDisksResponseBodyDisksDisk disk = response.getBody().getDisks()
                .getDisk().get(0);
            return disk;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Configure the system disk not to be released together with the instance. 
     */
    public static void modifyDiskAttribute(String diskId){
        ModifyDiskAttributeRequest request = new ModifyDiskAttributeRequest();
        request.setDeleteWithInstance(false);
        request.setRegionId(regionId);
        request.setDiskId(diskId);
        try {
            ModifyDiskAttributeResponse response = client.modifyDiskAttribute(request);
            System.out.println(response.getBody().getRequestId());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * Check whether the system disk is configured to be released together with the instance. 
     */
    public static Boolean diskNotDeleteWithInstance(){
        DescribeDisksResponseBodyDisksDisk disks = getDisks();
        if (disks.getDeleteWithInstance()){
            System.out.println(("disk is delete with instance"));
        }else {
            System.out.println(("disk not delete with instance"));
        }
        return disks.getDeleteWithInstance();
    }

    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. 
        // We recommend that you use Security Token Service (STS) tokens, which provide higher security. For information about credential-based authentication methods, see the topic at the following URL: https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-access-credentials?spm=a2c63.p38356.0.0.cc196072Z9j9AY. 
        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);
    }
}

Step 3: Configure a custom image to be automatically created when an interruption event is detected

After an interruption event of the preemptible instance is detected, the system uses Java code to create a snapshot for the system disk and create a custom image from the system disk snapshot.

In this step, the CreateSpotImage Java class is used. The following operations are called in sequence:

  • Call the DescribeInstances operation to query the status of the preemptible instance.

  • When an interruption event of the preemptible instance is detected, call the CreateSnapshot operation to create a snapshot for the system disk, and then call the DescribeSnapshots operation to query the status of the snapshot.

  • After the system disk snapshot is created, call the CreateImage operation to create a custom image from the snapshot.

  • After the custom image is created, call the DescribeImages operation to query the status of the custom image. When the custom image enters the Available state, a message is returned.

import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.CreateImageRequest;
import com.aliyun.ecs20140526.models.CreateImageResponse;
import com.aliyun.ecs20140526.models.CreateSnapshotRequest;
import com.aliyun.ecs20140526.models.CreateSnapshotResponse;
import com.aliyun.ecs20140526.models.DescribeDisksRequest;
import com.aliyun.ecs20140526.models.DescribeDisksResponse;
import com.aliyun.ecs20140526.models.DescribeDisksResponseBody.DescribeDisksResponseBodyDisksDisk;
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.aliyun.ecs20140526.models.DescribeSnapshotsRequest;
import com.aliyun.ecs20140526.models.DescribeSnapshotsResponse;
import com.aliyun.ecs20140526.models.DescribeSnapshotsResponseBody.DescribeSnapshotsResponseBodySnapshotsSnapshot;
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();
        String diskId = getDiskId();
        // Step 2: Create a snapshot for the system disk of the preemptible instance when an interruption event occurs on the preemptible instance. 
        String snapshotId = createSnapshot(diskId);
        // Step 3: Wait until the system disk snapshot is created. 
        waitCreateSnapshotSuccess(snapshotId);
        // Step 4: Create a custom image from the system disk snapshot. 
        String imageId = createImage(snapshotId);
        // Step 5: Wait until the custom image is created. 
        waitCreateImageSuccess(imageId);
    }

    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. 
        // We recommend that you use STS tokens, which provide higher security. For information about credential-based authentication methods, see the topic at the following URL: https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-access-credentials?spm=a2c63.p38356.0.0.cc196072Z9j9AY. 
        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, return the ID of the instance and the cause of the interruption. 
                    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();
            }
        }
    }

    public static String getDiskId(){
        String diskId = null;
        DescribeDisksRequest request = new DescribeDisksRequest();
        request.setRegionId(regionId);
        request.setInstanceId(instanceId);
        request.setDiskType("system");
        try {
            DescribeDisksResponse response = client.describeDisks(request);

            List<DescribeDisksResponseBodyDisksDisk> disks = response.getBody().getDisks().getDisk();
            if (CollectionUtils.isEmpty(disks) ){
                System.out.println("disk not exist. instance: " + instanceId);
                return null;
            }
            diskId = disks.get(0).getDiskId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return diskId;
    }

    /**
     * Create a snapshot for the system disk. 
     */
    public static String createSnapshot(String diskId){
        CreateSnapshotRequest request = new CreateSnapshotRequest();
        request.setDiskId(diskId);
        request.setSnapshotName("disk_test");

        try {
            CreateSnapshotResponse  response= client.createSnapshot(request);
            System.out.println(JSON.toJSONString(response.getBody()));
            System.out.println(response.getBody().getSnapshotId());
            return response.getBody().getSnapshotId();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * Check whether the system disk snapshot is created. 
     */
    public static void waitCreateSnapshotSuccess(String snapshotId){
        boolean isSuccess = false;
        while (!isSuccess) {
            DescribeSnapshotsResponseBodySnapshotsSnapshot snapshot = describeSnapshots(snapshotId);
            if (null == snapshot) {
                System.err.println("image not exist. imageId: " + snapshotId);
                break;
            }
            if("accomplished".equals(snapshot.getStatus())){
                System.out.println("snapshot created successfully.");
                isSuccess = true;
            }
        }
    }

    /**
     * Call the DescribeSnapshots operation to query the status of the system disk snapshot. 
     */
    public static DescribeSnapshotsResponseBodySnapshotsSnapshot describeSnapshots(String snapshotId){
        DescribeSnapshotsRequest request = new DescribeSnapshotsRequest();
        request.setRegionId(regionId);
        List<String> snapshotIds = Lists.newArrayList(snapshotId);
        String s = JSON.toJSONString(snapshotIds);
        request.setSnapshotIds(s);
        try {
            DescribeSnapshotsResponse response = client.describeSnapshots(request);
            if (CollectionUtils.isEmpty(response.getBody().getSnapshots().getSnapshot())) {
                return null;
            }
            return  response.getBody().getSnapshots().getSnapshot().get(0);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    // Create a custom image. 
    public static String createImage(String snapshotId) {
        try {
            // Configure the request parameters of the CreateImage operation and send the request. 
            CreateImageRequest request = new CreateImageRequest();
            request.setRegionId(regionId);
            request.setSnapshotId(snapshotId);
            request.setImageName("image_test");
            // Obtain the response and the ID of the custom image. 
            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;
    }
}

Step 4: Create a preemptible instance from the custom image to restore data

In this step, the CreateSpotInstanceFromImage Java class is used. The following sample code provides an example on how to create a preemptible instance from the custom image by calling the RunInstances operation:

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. 
        // We recommend that you use STS tokens, which provide higher security. For information about credential-based authentication methods, see the topic at the following URL: https://www.alibabacloud.com/help/en/sdk/developer-reference/v2-manage-access-credentials?spm=a2c63.p38356.0.0.cc196072Z9j9AY. 
        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 a preemptible 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;
    }
}

References

You can use one of the following methods to restore important data that is stored on a data disk of a preemptible instance: