edit-icon download-icon

Use APIs to manage preemptible instances

Last Updated: Jun 14, 2018

This document describes how to use Alibaba Cloud ECS SDKs to quickly create and manage preemptible instances.

Preparation

Before you begin, make sure that:

  • You know which instance types and regions meet your business requirements.
  • You have a basic understanding of Alibaba Cloud ECS SDKs and calling methods. For more information, see SDK documentation.

    NOTE:
    The ECS SDK version for preemptible instances is 4.2.0 and later. Here is an example of how to change the pom dependency.

    1. <dependency>
    2. <groupId>com.aliyun</groupId>
    3. <artifactId>aliyun-java-sdk-core</artifactId>
    4. <version>3.2.8</version>
    5. </dependency>
    6. <dependency>
    7. <groupId>com.aliyun</groupId>
    8. <artifactId>aliyun-java-sdk-ecs</artifactId>
    9. <version>4.2.0</version>
    10. </dependency>

Query regions and available instance types

Use the DescribeZones interface to query the regions where you can create preemptible instances and the available instance types. The sample code is as follows.

  • OpenApiCaller.java

    1. public class OpenApiCaller {
    2. IClientProfile profile;
    3. IAcsClient client;
    4. public OpenApiCaller() {
    5. profile = DefaultProfile.getProfile("cn-hangzhou", AKSUtil.accessKeyId, AKSUtil.accessKeySecret);
    6. client = new DefaultAcsClient(profile);
    7. }
    8. public <T extends AcsResponse> T doAction(AcsRequest<T> var1) {
    9. try {
    10. return client.getAcsResponse(var1);
    11. } catch (Throwable e) {
    12. e.printStackTrace();
    13. return null;
    14. }
    15. }
    16. }
  • DescribeZonesSample.java

    1. public class DescribeZonesSample {
    2. public static void main(String[] args) {
    3. OpenApiCaller caller = new OpenApiCaller();
    4. DescribeZonesRequest request = new DescribeZonesRequest();
    5. request.setRegionId("cn-zhangjiakou");//You can use DescribeRegionsRequest to get the RegionId of each region
    6. request.setSpotStrategy("SpotWithPriceLimit");//This field must be entered to query the availability of instance types
    7. request.setInstanceChargeType("PostPaid");//Post-paid mode, preemptible instances must be post-paid
    8. DescribeZonesResponse response = caller.doAction(request);
    9. System.out.println(JSON.toJSONString(response));
    10. }
    11. }

In the following output result, you can see the instance types, disk types, and network types available in each region.

  1. {
  2. "requestId": "388D6321-E587-470C-8CFA-8985E2963DAE",
  3. "zones": [
  4. {
  5. "localName": "China North 3 Zone A",
  6. "zoneId": "cn-zhangjiakou-a",
  7. "availableDiskCategories": [
  8. "cloud_ssd",
  9. "cloud_efficiency"
  10. ],
  11. "availableInstanceTypes": [
  12. "ecs.e4.large",
  13. "ecs.n4.4xlarge",
  14. "ecs.sn2.medium",
  15. "ecs.i1.2xlarge",
  16. "ecs.se1.2xlarge",
  17. "ecs.n4.xlarge",
  18. "ecs.se1ne.2xlarge",
  19. "ecs.se1.large",
  20. "ecs.sn2.xlarge",
  21. "ecs.se1ne.xlarge",
  22. "ecs.xn4.small",
  23. "ecs.sn2ne.4xlarge",
  24. "ecs.se1ne.4xlarge",
  25. "ecs.sn1.medium",
  26. "ecs.n4.8xlarge",
  27. "ecs.mn4.large",
  28. "ecs.e4.2xlarge",
  29. "ecs.mn4.2xlarge",
  30. "ecs.mn4.8xlarge",
  31. "ecs.n4.2xlarge",
  32. "ecs.e4.xlarge",
  33. "ecs.sn2ne.large",
  34. "ecs.sn2ne.xlarge",
  35. "ecs.sn1ne.large",
  36. "ecs.n4.large",
  37. "ecs.sn1.3xlarge",
  38. "ecs.e4.4xlarge",
  39. "ecs.sn1ne.2xlarge",
  40. "ecs.e4.small",
  41. "ecs.i1.4xlarge",
  42. "ecs.se1.4xlarge",
  43. "ecs.sn2ne.2xlarge",
  44. "ecs.sn2.3xlarge",
  45. "ecs.i1.xlarge",
  46. "ecs.n4.small",
  47. "ecs.sn1ne.4xlarge",
  48. "ecs.mn4.4xlarge",
  49. "ecs.sn1ne.xlarge",
  50. "ecs.se1ne.large",
  51. "ecs.sn2.large",
  52. "ecs.i1-c5d1.4xlarge",
  53. "ecs.sn1.xlarge",
  54. "ecs.sn1.large",
  55. "ecs.mn4.small",
  56. "ecs.mn4.xlarge",
  57. "ecs.se1.xlarge"
  58. ],
  59. "availableResourceCreation": [
  60. "VSwitch",
  61. "IoOptimized",
  62. "Instance",
  63. "Disk"
  64. ],
  65. "availableResources": [
  66. {
  67. "dataDiskCategories": [
  68. "cloud_ssd",
  69. "cloud_efficiency"
  70. ],
  71. "instanceGenerations": [
  72. "ecs-3",
  73. "ecs-2"
  74. ],
  75. "instanceTypeFamilies": [
  76. "ecs.mn4",
  77. "ecs.sn1",
  78. "ecs.sn2",
  79. "ecs.sn1ne",
  80. "ecs.xn4",
  81. "ecs.i1",
  82. "ecs.se1",
  83. "ecs.e4",
  84. "ecs.n4",
  85. "ecs.se1ne",
  86. "ecs.sn2ne"
  87. ],
  88. "instanceTypes": [
  89. "ecs.n4.4xlarge",
  90. "ecs.sn2.medium",
  91. "ecs.i1.2xlarge",
  92. "ecs.se1.2xlarge",
  93. "ecs.n4.xlarge",
  94. "ecs.se1ne.2xlarge",
  95. "ecs.se1.large",
  96. "ecs.sn2.xlarge",
  97. "ecs.se1ne.xlarge",
  98. "ecs.xn4.small",
  99. "ecs.sn2ne.4xlarge",
  100. "ecs.se1ne.4xlarge",
  101. "ecs.sn1.medium",
  102. "ecs.n4.8xlarge",
  103. "ecs.mn4.large",
  104. "ecs.mn4.2xlarge",
  105. "ecs.mn4.8xlarge",
  106. "ecs.n4.2xlarge",
  107. "ecs.sn2ne.large",
  108. "ecs.sn2ne.xlarge",
  109. "ecs.sn1ne.large",
  110. "ecs.n4.large",
  111. "ecs.sn1.3xlarge",
  112. "ecs.sn1ne.2xlarge",
  113. "ecs.e4.small",
  114. "ecs.i1.4xlarge",
  115. "ecs.se1.4xlarge",
  116. "ecs.sn2ne.2xlarge",
  117. "ecs.sn2.3xlarge",
  118. "ecs.i1.xlarge",
  119. "ecs.n4.small",
  120. "ecs.sn1ne.4xlarge",
  121. "ecs.mn4.4xlarge",
  122. "ecs.sn1ne.xlarge",
  123. "ecs.se1ne.large",
  124. "ecs.sn2.large",
  125. "ecs.i1-c5d1.4xlarge",
  126. "ecs.sn1.xlarge",
  127. "ecs.sn1.large",
  128. "ecs.mn4.small",
  129. "ecs.mn4.xlarge",
  130. "ecs.se1.xlarge"
  131. ],
  132. "ioOptimized": true,
  133. "networkTypes": [
  134. "vpc"
  135. ],
  136. "systemDiskCategories": [
  137. "cloud_ssd",
  138. "cloud_efficiency"
  139. ]
  140. }
  141. ],
  142. "availableVolumeCategories": [
  143. "san_ssd",
  144. "san_efficiency"
  145. ]
  146. }
  147. ]
  148. }

Query preemptible instance price history

Use the DescribeSpotPriceHistory interface to query the price changes of a preemptible instance type over the last 30 days, so you can find the most cost efficient regions and instance types. The sample code (DescribeSpotPriceHistorySample.java) is as follows.

  1. public class DescribeSpotPriceHistorySample {
  2. public static void main(String[] args) {
  3. OpenApiCaller caller = new OpenApiCaller();
  4. List<DescribeSpotPriceHistoryResponse.SpotPriceType> result = new ArrayList<DescribeSpotPriceHistoryResponse.SpotPriceType>();
  5. int offset = 0;
  6. while (true) {
  7. DescribeSpotPriceHistoryRequest request = new DescribeSpotPriceHistoryRequest();
  8. request.setRegionId("cn-hangzhou");//You can use DescribeRegionsRequest to get the RegionId of each region where preemptible instances are available
  9. request.setZoneId("cn-hangzhou-b");//You must enter the zone
  10. request.setInstanceType("ecs.sn2.medium");//See the instance types returned by DescribeZones, this field is mandatory
  11. request.setNetworkType("vpc");//See the network types returned by DescribeZones, this field is mandatory
  12. // request.setIoOptimized("optimized");//Determines if the instance is I/O optimized, see IoOptimized returned by DescribeZones, this field is optional
  13. // request.setStartTime("2017-09-20T08:45:08Z");//The price start time, optional, default value: within 3 days
  14. // request.setEndTime("2017-09-28T08:45:08Z");//Price end time, optional
  15. request.setOffset(offset);
  16. DescribeSpotPriceHistoryResponse response = caller.doAction(request);
  17. if (response != null && response.getSpotPrices() != null) {
  18. result.addAll(response.getSpotPrices());
  19. }
  20. if (response.getNextOffset() == null || response.getNextOffset() == 0) {
  21. break;
  22. } else {
  23. offset = response.getNextOffset();
  24. }
  25. }
  26. if (!result.isEmpty()) {
  27. for (DescribeSpotPriceHistoryResponse.SpotPriceType spotPriceType : result) {
  28. System.out.println(spotPriceType.getTimestamp() + "--->spotPrice:" + spotPriceType.getSpotPrice() + "---->originPrice:" + spotPriceType.getOriginPrice());
  29. }
  30. System.out.println(result.size());
  31. } else {
  32. }
  33. }
  34. }

Returned results sample.

  1. 2017-09-26T06:28:55Z--->spotPrice:0.24---->originPrice:1.2
  2. 2017-09-26T14:00:00Z--->spotPrice:0.36---->originPrice:1.2
  3. 2017-09-26T15:00:00Z--->spotPrice:0.24---->originPrice:1.2
  4. 2017-09-27T14:00:00Z--->spotPrice:0.36---->originPrice:1.2
  5. 2017-09-27T15:00:00Z--->spotPrice:0.24---->originPrice:1.2
  6. 2017-09-28T14:00:00Z--->spotPrice:0.36---->originPrice:1.2
  7. 2017-09-28T15:00:00Z--->spotPrice:0.24---->originPrice:1.2
  8. 2017-09-29T06:28:55Z--->spotPrice:0.24---->originPrice:1.2

Repeat this process to find the price trends and recent prices of the instance type in each zones.

Note:
You can use average price or maximum price to determine if you can afford this preemptible instance. You can also use more rational data models to analyze historical price data and adjust your instance types and zones at will for maximum cost effectiveness.

Create a preemptible instance

You must complete the following work before creating a preemptible instance:

Use the CreateInstance to create a preemptible instance. The sample code (CreateInstaneSample.java) is as follows.

  1. public class CreateInstaneSample {
  2. public static void main(String[] args) {
  3. OpenApiCaller caller = new OpenApiCaller();
  4. CreateInstanceRequest request = new CreateInstanceRequest();
  5. request.setRegionId("cn-hangzhou");//The region ID
  6. request.setZoneId("cn-hangzhou-b"); //The zone ID
  7. request.setSecurityGroupId("sg-bp11nhf94ivkdxwb2gd4");//The ID of the security group
  8. request.setImageId("centos_7_03_64_20G_alibase_20170818.vhd");//We recommend that you select a custom image you have prepared in this region
  9. request.setVSwitchId("vsw-bp164cyonthfudn9kj5br");//For VPC, the VSwitch ID is required
  10. request.setInstanceType("ecs.sn2.medium"); //Enter the instance type you want to purchase
  11. request.setIoOptimized("optimized");//See the parameters returned by DescirbeZones
  12. request.setSystemDiskCategory("cloud_ssd");//See the parameters returned by DescirbeZones, select one: cloud_ssd, cloud_efficiency, or cloud
  13. request.setSystemDiskSize(40);
  14. request.setInstanceChargeType("PostPaid");//Post-paid is required for preemptible instances
  15. request.setSpotStrategy("SpotWithPriceLimit");//SpotWithPriceLimit: bid mode, SpotAsPriceGo: no bids, the maximum Pay-As-You-Go price
  16. request.setSpotPriceLimit(0.25F);//This applies only to SpotWithPriceLimit. Set the maximum price you are willing to pay, units: USD/hour. An instance is created when this price is higher than the current market price
  17. CreateInstanceResponse response = caller.doAction(request);
  18. System.out.println(response.getInstanceId());
  19. }
  20. }

Recover a preemptible instance

Mandatory recovery can be imposed on preemptible instances due to changes in price or supply and demand. At such a time, the operation of the preemptible instance is suspended. Before being released, the preemptible instance enters the locked status and a prompt notifies you that the instance will be automatically recovered. You can design a withdrawal logic to automatically process instances in the recovery status.

Now, you can use the following methods to determine the suspension and lock statuses of preemptible instances:

  • Obtain this information from the instance metadata. Run the following command.

    1. curl 'http://100.100.100.200/latest/meta-data/instance/spot/termination-time'

    If no result is returned, it indicates the instance can continue to be used. If the returned result contains UTC time stamp information in the format of YYYY-MM-DDTHH:mm:ssZ (for example 2015-01-05T18:02:00Z), it indicates the instance will be released at the specified time.

  • You can use the OperationLocks information returned by the DescribeInstances to see if an instance is in the Awaiting Recovery status. The sample code (DescribeInstancesSample.java) is as follows.

    1. public class DescribeInstancesSample {
    2. public static void main(String[] args) throws InterruptedException {
    3. OpenApiCaller caller = new OpenApiCaller();
    4. JSONArray allInstances = new JSONArray();
    5. allInstances.addAll(Arrays.asList("i-bp18hgfai8ekoqwo0y2n", "i-bp1ecbyds24ij63w146c"));
    6. while (!allInstances.isEmpty()) {
    7. DescribeInstancesRequest request = new DescribeInstancesRequest();
    8. request.setRegionId("cn-hangzhou");
    9. request.setInstanceIds(allInstances.toJSONString());//Specify the instance ID, maximum efficiency
    10. DescribeInstancesResponse response = caller.doAction(request);
    11. List<DescribeInstancesResponse.Instance> instanceList = response.getInstances();
    12. if (instanceList != null && !instanceList.isEmpty()) {
    13. for (DescribeInstancesResponse.Instance instance : instanceList) {
    14. System.out.println("result:instance:" + instance.getInstanceId() + ",az:" + instance.getZoneId());
    15. if (instance.getOperationLocks() != null) {
    16. for (DescribeInstancesResponse.Instance.LockReason lockReason : instance.getOperationLocks()) {
    17. System.out.println("instance:" + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",vmStatus:" + instance.getStatus());
    18. if ("Recycling".equals(lockReason.getLockReason())) {
    19. //do your action
    20. System.out.println("spot instance will be recycled immediately, instance id:" + instance.getInstanceId());
    21. allInstances.remove(instance.getInstanceId());
    22. }
    23. }
    24. }
    25. }
    26. System.out.print("try describeInstances again later ...");
    27. Thread.sleep(2 * 60 * 1000);
    28. } else {
    29. break;
    30. }
    31. }
    32. }
    33. }

    The output result when recovery is triggered is as follows.

    1. instance:i-bp1ecbyds24ij63w146c-->lockReason:Recycling,vmStatus:Stopped
    2. spot instance will be recycled immediately, instance id:i-bp1ecbyds24ij63w146c

Other operations

You can start, stop, and release preemptible instances. These operations are the same as for Pay-As-You-Go instances. For more information, see the API documentation:

Thank you! We've received your feedback.