Detect spot instance interruptions through the ECS SDK, instance metadata, or Cloud Monitor, and respond with graceful shutdown or data persistence.
Detect interruptions
Query using the ECS SDK
Call the DescribeInstances operation to query instance details. Check the returned OperationLocks field to determine whether the instance has entered the pending release state.
If the response is empty, the instance is still available.
If
LockReasonisRecycling, the spot instance is interrupted and pending release.
SDK usage example
Prerequisites
Create an AccessKey
An Alibaba Cloud account has full permissions for all resources. If its AccessKey is compromised, your resources are at high risk. Use a RAM user AccessKey with minimum required permissions instead. See Create an AccessKey.
Grant ECS permissions to the RAM user
Grant the RAM user permissions to manage ECS resources. The sample code requires the permission to query instance information. Grant the following system policy:
Cloud Products
Permission granted
Elastic Compute Service (ECS)
System policy: AliyunECSFullAccess
Configure access credentials
The sample code reads the AccessKey from system environment variables to authenticate requests. See Configure environment variables on Linux, macOS, and Windows.
Install the ECS SDK
Obtain the ECS SDK. This example uses Maven. For other installation methods, see Install the ECS Java SDK.
Initialize the client
Alibaba Cloud SDKs support multiple credential types for client initialization, such as an AccessKey and an STS token. For other options, see Manage access credentials. This example initializes the client with an AccessKey.
import com.aliyun.ecs20140526.Client;
import com.aliyun.teaopenapi.models.Config;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.aliyun.com/product/Ecs
.setEndpoint("ecs.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
}Build the request object
Before building the request, see the API documentation for parameter details.
// Build the request object
DescribeInstancesRequest request = new DescribeInstancesRequest().setRegionId("cn-hangzhou");
Make the call
When calling OpenAPI operations, you can configure runtime parameters such as timeout and proxy settings. See Advanced configuration.
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
// Call the DescribeInstances operation
DescribeInstancesResponse response = client.describeInstancesWithOptions(request, runtime);
System.out.println(response.body.toMap());Handle exceptions
The Java SDK categorizes exceptions into TeaUnretryableException and TeaException:
TeaUnretryableException: Typically caused by network issues after the maximum retries are reached.
TeaException: Primarily caused by business-related errors.
Implement proper exception handling, such as propagating exceptions, logging errors, or attempting recovery, to ensure system robustness.
Complete example
import com.aliyun.ecs20140526.Client;
import com.aliyun.ecs20140526.models.DescribeInstancesRequest;
import com.aliyun.ecs20140526.models.DescribeInstancesResponse;
import com.aliyun.ecs20140526.models.DescribeInstancesResponseBody;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
import com.alibaba.fastjson.JSONArray;
import java.util.Arrays;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.aliyun.com/product/Ecs
.setEndpoint("ecs.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
public static void main(String[] args) {
try {
Client client = Sample.createClient();
// Build the request object
// Specify one or more ECS instance IDs to query.
JSONArray instanceIds = new JSONArray();
instanceIds.addAll(Arrays.asList("i-bp145cvd0exyqj****","i-bp1gehfgfrrk4lah****"));
DescribeInstancesRequest request = new DescribeInstancesRequest()
.setRegionId("cn-hangzhou")
.setInstanceIds(instanceIds.toJSONString());
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
while (!instanceIds.isEmpty()) {
// Call the DescribeInstances operation
DescribeInstancesResponse response = client.describeInstancesWithOptions(request, runtime);
// Get instance details from the response.
DescribeInstancesResponseBody responseBody = response.getBody();
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstances instanceList = responseBody.getInstances();
// Check instance details and evaluate lockReason values.
if (instanceList != null && instanceList.getInstance()!= null && !instanceList.getInstance().isEmpty()) {
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstance instance : instanceList.getInstance()) {
// Print the queried instance ID and zone ID.
System.out.println("result:instance:" + instance.getInstanceId() + ",az:" + instance.getZoneId());
if (instance.getOperationLocks() != null ) {
DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstanceOperationLocks operationLocks = instance.getOperationLocks();
if(operationLocks.getLockReason()!=null && !operationLocks.getLockReason().isEmpty()){
for (DescribeInstancesResponseBody.DescribeInstancesResponseBodyInstancesInstanceOperationLocksLockReason lockReason : operationLocks.getLockReason()) {
// If the instance is locked, print its ID and lock reason.
System.out.println("instance:" + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",vmStatus:" + instance.getStatus());
if ("Recycling".equals(lockReason.getLockReason())) {
// Print the ID of the instance scheduled for immediate release.
System.out.println("spot instance will be recycled immediately, instance id:" + instance.getInstanceId());
instanceIds.remove(instance.getInstanceId());
}
}
}
}
}
// If no spot instance is locked yet, query again every two minutes.
System.out.print("try describeInstances again later ...");
Thread.sleep(2 * 60 * 1000);
} else {
break;
}
}
} catch (TeaUnretryableException ue) {
// Print only for demonstration. Never ignore exceptions in production code.
ue.printStackTrace();
// Print error message
System.out.println(ue.getMessage());
// Print request details for debugging
System.out.println(ue.getLastRequest());
} catch (TeaException e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
// Print error code
System.out.println(e.getCode());
// Print error message (includes RequestId)
System.out.println(e.getMessage());
// Print detailed server-side error content
System.out.println(e.getData());
} catch (Exception e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
}
}
}
Returned results
When a release is triggered, the output is:
result:instance:i-bp1i9c3qiv1qs6nc****,az:cn-hangzhou-i
instance:i-bp1i9c3qiv1qs6nc****-->lockReason:Recycling,vmStatus:Stopped
spot instance will be recycled immediately, instance id:i-bp1i9c3qiv1qs6nc****Query from within the instance with metadata
Access the instance metadata service from within an ECS instance to check when a spot instance will be terminated. See Instance metadata.
Metadata path for the termination time of a spot instance: instance/spot/termination-time
Results:
If the response is 404, the instance is still available.
If the response returns a UTC timestamp such as
2015-01-05T18:02:00Z, the instance will be reclaimed at that time.
Examples:
Linux instance
# Get a metadata service token for authentication
TOKEN=`curl -X PUT "http://100.100.100.200/latest/api/token" -H "X-aliyun-ecs-metadata-token-ttl-seconds:<metadata service token TTL>"`
# Check whether the spot instance is scheduled for interruption
curl -H "X-aliyun-ecs-metadata-token: $TOKEN" http://100.100.100.200/latest/meta-data/instance/spot/termination-timeWindows instance
# Get a metadata service token for authentication
$token = Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token-ttl-seconds" = "<metadata service token TTL>"} -Method PUT -Uri http://100.100.100.200/latest/api/token
# Check whether the spot instance is scheduled for interruption
Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token" = $token} -Method GET -Uri http://100.100.100.200/latest/meta-data/instance/spot/termination-timeQuery with the Cloud Monitor SDK
ECS events are synced to Cloud Monitor. Call the DescribeSystemEventAttribute operation to query spot instance interruption events (Instance:PreemptibleInstanceInterruption). If the content field contains delete, the spot instance is scheduled for reclamation.
SDK usage example
Prerequisites
Create an AccessKey
An Alibaba Cloud account has full permissions for all resources. If its AccessKey is compromised, your resources are at high risk. Use a RAM user AccessKey with minimum required permissions instead. See Create an AccessKey.
Grant Cloud Monitor permissions to the RAM user
Grant the RAM user permissions to manage Cloud Monitor (CMS). The sample code requires the permission to query system events. Grant the following policy:
Cloud products
Permission granted
Cloud Monitor (CMS)
AliyunCloudMonitorFullAccess
Configure access credentials
The sample code reads the AccessKey from system environment variables to authenticate requests. See Configure environment variables on Linux, macOS, and Windows.
Install the CMS SDK
Obtain the CMS SDK. This example uses Maven. For other installation methods, see Install the CMS Java SDK.
Initialize the client
Alibaba Cloud SDKs support multiple credential types for client initialization, such as an AccessKey and an STS token. For other options, see Manage access credentials. This example initializes the client with an AccessKey.
import com.aliyun.cms20190101.Client;
import com.aliyun.teaopenapi.models.Config;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.aliyun.com/product/Ecs
.setEndpoint("metrics.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
}Build the request object
Configure query parameters for spot instance interruption events. For other parameters, see DescribeSystemEventAttribute.
API | Parameter | Example value |
Product | Service abbreviation: ECS | |
EventType | Event type: StatusNotification | |
Name | Event name: Instance:PreemptibleInstanceInterruption |
// Build the request object
DescribeSystemEventAttributeRequest request = new DescribeSystemEventAttributeRequest()
.setProduct("ECS")
.setEventType("StatusNotification")
.setName("Instance:PreemptibleInstanceInterruption");
Make the call
When calling OpenAPI operations, you can configure runtime parameters such as timeout and proxy settings. See Advanced configuration.
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
// Call the DescribeSystemEventAttribute operation
DescribeSystemEventAttributeResponse response = client.describeSystemEventAttributeWithOptions(request, runtime);
System.out.println(response.body.toMap());
Handle exceptions
The Java SDK categorizes exceptions into TeaUnretryableException and TeaException:
TeaUnretryableException: Typically caused by network issues after the maximum retries are reached.
TeaException: Primarily caused by business-related errors.
Implement proper exception handling, such as propagating exceptions, logging errors, or attempting recovery, to ensure system robustness.
Complete example
import com.aliyun.cms20190101.Client;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.cms20190101.models.DescribeSystemEventAttributeRequest;
import com.aliyun.cms20190101.models.DescribeSystemEventAttributeResponse;
import com.aliyun.tea.TeaException;
import com.aliyun.tea.TeaUnretryableException;
import com.aliyun.teaopenapi.models.Config;
import com.aliyun.teautil.models.RuntimeOptions;
public class Sample {
private static Client createClient() throws Exception {
Config config = new Config()
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_ID environment variable is set.
.setAccessKeyId(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"))
// Required. Ensure the ALIBABA_CLOUD_ACCESS_KEY_SECRET environment variable is set.
.setAccessKeySecret(System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"))
// Endpoint reference: https://api.aliyun.com/product/Ecs
.setEndpoint("metrics.cn-hangzhou.aliyuncs.com");
return new Client(config);
}
public static void main(String[] args) {
try {
Client client = Sample.createClient();
// Build the request object
DescribeSystemEventAttributeRequest request = new DescribeSystemEventAttributeRequest()
.setProduct("ECS")
.setEventType("StatusNotification")
.setName("Instance:PreemptibleInstanceInterruption");
// Set runtime options
RuntimeOptions runtime = new RuntimeOptions();
// Call the DescribeSystemEventAttribute operation
DescribeSystemEventAttributeResponse response = client.describeSystemEventAttributeWithOptions(request, runtime);
System.out.println(response.body.toMap());
} catch (TeaUnretryableException ue) {
// Print only for demonstration. Never ignore exceptions in production code.
ue.printStackTrace();
// Print error message
System.out.println(ue.getMessage());
// Print request details for debugging
System.out.println(ue.getLastRequest());
} catch (TeaException e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
// Print error code
System.out.println(e.getCode());
// Print error message (includes RequestId)
System.out.println(e.getMessage());
// Print detailed server-side error content
System.out.println(e.getData());
} catch (Exception e) {
// Print only for demonstration. Never ignore exceptions in production code.
e.printStackTrace();
}
}
}
Result
Interpret the response to identify spot instance interruption events.
Event notification in JSON format:
{
"ver": "1.0",
"id": "2256A988-0B26-4E2B-820A-8A********E5",
"product": "ECS",
"resourceId": "acs:ecs:cn-hangzhou:169070********30:instance/i-bp1ecr********5go2go",
"level": "INFO",
"name": "Instance:PreemptibleInstanceInterruption",
"userId": "169070********30",
"eventTime": "20190409T121826.922+0800",
"regionId": "cn-hangzhou",
"content": {
"instanceId": "i-bp1ecr********5go2go",
"action": "delete"
}
}The content field is described below. For parameter details, see DescribeSystemEventAttribute.
Field | Description | Example value |
instanceId | The spot instance ID. | i-bp1ecr********5go2go |
action | The operation event. A value of delete indicates the instance is interrupted and will be forcibly reclaimed. | delete |
Subscribe to Cloud Monitor events
Subscribe to Cloud Monitor events to monitor spot instance interruptions in real time. Notifications can be sent through channels such as text messages, email, Function Compute, Simple Message Queue, or a webhook.
Workflow
Procedure
Prepare the receiving channel
Lightweight Message Queue
Log on to the SMQ console.
In the left-side navigation pane, choose Queue Model > Queues.
In the top navigation bar, select a region.
On the Queues page, click Create Queue.
In the Create Queue panel, configure the following parameters and click OK:
Name: the name of the queue.
Maximum Message Length: the maximum length of the message that is sent to the queue.
Long Polling Period: the maximum duration for which long polling requests are held after the ReceiveMessage operation is called.
Visibility Timeout Period: the duration for which a message stays in the Inactive state after the message is received from the queue.
Message Retention Period: the maximum duration for which a message exists in the queue. After the specified retention period, the message is deleted regardless of whether the message is received.
Message Delay Period: the period after which all messages sent to the queue are consumed.
Enable Logging Feature: specifies whether to enable the logging feature.
After the queue is created, it is displayed on the Queues page.
Webhook
ImportantDeploy the webhook service on an Internet-accessible server. Ensure inbound traffic is allowed on the response port.
Java sample code:
import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RestController; @RestController public class WebhookController { @PostMapping("/callback") public ResponseEntity<String> receiveWebhook(@RequestBody String payload) { // Process the payload, such as logging or executing business logic System.out.println("Received webhook payload: " + payload); // Return a success response return ResponseEntity.ok("Webhook received"); } }Create a subscription policy
Log on to the Cloud Monitor console.
In the left navigation pane, choose .
On the Subscription Policies tab, click Create Subscription Policy.
On the Create Subscription Policy page, configure the policy parameters.
This example covers only parameters relevant to spot instance interruption events. For all parameters, see Manage event subscriptions (recommended).
Basic Information: Enter a Name and Description for the subscription policy.
Alert Subscription:
Subscription Type: Select System Events.
Subscription Scope:
Service: Select ECS.
Event Type: Select Status Notification.
Event Name: Select Spot Instance Interruption Notification.
Event Severity: Select Warning.
Application Groups, Event Content, and Event Resource: Leave these parameters empty to subscribe to all ECS system events that are named Spot Instance Interruption Notification across all application groups in your account.
Noise Reduction: Use the default.
Notification: The Custom Notification Method uses the default method.
Push and Integration: Click Add Channel. In the pop-up window, click Add Channel, select the channel prepared in Step 1 as the Target Type, and complete the remaining fields. For push channel details, see Manage push channels.
Simulate an interruption event
Spot instance interruptions are passive, making it difficult to debug interruption-handling code. Use the Debug Event Subscription feature to simulate a spot instance interruption event.
On the Subscription Policies tab, click Debug Event Subscription.
In the Create Event Debug panel, set Service to ECS and Name to Spot Instance Interruption Notification.
The system generates a debug payload in JSON format. Replace the resource-related placeholders with actual values for the spot instance to simulate.
Replace
Alibaba Cloud account UIDwith your Alibaba Cloud account UID.Replace
<resource-id>and<instanceId>with the spot instance ID.Replace
<region ID>with the region ID of the spot instance.{ "product": "ECS", "resourceId": "acs:ecs:cn-shanghai:Alibaba Cloud account UID:instance/<resource-id>", "level": "WARN", "instanceName": "instanceName", "regionId": "<region ID>", "groupId": "0", "name": "Instance:PreemptibleInstanceInterruption", "content": { "instanceId": "i-2zeg014dfo4y892z***", "instanceName": "wor***b73", "action": "delete" }, "status": "Normal" }
Click OK.
The system displays the The operation is successful. message and sends a test alert notification based on your subscription policy.
Receive and view notifications
Lightweight Message Queue
Log on to the Simple Message Queue (formerly MNS) console. In the navigation pane on the left, click Queues.
In the top navigation bar, select a region. On the Queues page, find your target queue and click Action > Send Messages.
Optional: On the Send/Receive Messages Quick Experience page, click Edit Parameters of Receiving Messages. In the Edit Parameters of Receiving Messages panel, set Receive Times and Polling Period, and then click OK.
On the Queue Send/Receive Messages Quick Experience page, click Receive Message. The message list appears in the Received Messages section.
Optional: In the message list, find your target message, click Details in the Actions column, and view the message content in the Message Details dialog box.
Webhook
You can check the invocation logs and notification content in your deployed webhook application.
Respond to interruptions
Your response strategy depends on your business scenario. Test your application to ensure it can gracefully handle spot instance interruptions. Consider the following approaches:
Graceful interruption handling
Respond promptly to interruption signals by saving task progress, cleaning up resources, and terminating task execution.
Data persistence and checkpoints
Periodically save task progress and intermediate results to persistent storage, such as local files or databases, to preserve critical business data. See Data retention and recovery for spot instances.
Test integration success
Trigger a test event in Cloud Monitor to verify that your program responds as expected. See Detect and respond to spot instance interruption events using Simple Message Queue.