抢占式实例可能会因为价格因素或者市场供需变化而被强制回收,此时会触发抢占式实例的中断。抢占式实例被回收前会进入锁定状态,系统会提示您实例将会被自动回收。本文介绍如何查询抢占式实例是否被中断。
方式一:通过云监控SDK查询
以云监控Java SDK为例,介绍如何查询抢占式实例中断事件。
接入云监控SDK。
具体操作,请参见SDK参考。
通过SDK查询系统事件。
示例代码如下所示:
import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.exceptions.ClientException; import com.aliyuncs.exceptions.ServerException; import com.aliyuncs.profile.DefaultProfile; import com.google.gson.Gson; import java.util.*; import com.aliyuncs.cms.model.v20190101.*; public class DescribeSystemEventAttribute { public static void main(String[] args) { // 初始化DefaultAcsClient实例。 // 请确保代码运行环境设置了环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。 // 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取AccessKey的方式进行调用,建议使用更安全的STS方式。 DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET")); IAcsClient client = new DefaultAcsClient(profile); // 查询抢占式实例中断事件。 DescribeSystemEventAttributeRequest request = new DescribeSystemEventAttributeRequest(); request.setRegionId("cn-hangzhou"); request.setProduct("ECS"); request.setEventType("StatusNotification"); request.setName("Instance:PreemptibleInstanceInterruption"); try { // 接收响应结果。 DescribeSystemEventAttributeResponse response = client.getAcsResponse(request); System.out.println(new Gson().toJson(response)); } catch (ServerException e) { e.printStackTrace(); } catch (ClientException e) { System.out.println("ErrCode:" + e.getErrCode()); System.out.println("ErrMsg:" + e.getErrMsg()); System.out.println("RequestId:" + e.getRequestId()); } } }
根据返回结果判断抢占式实例中断事件。
事件通知的JSON格式如下所示:
{ "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" } }
content
字段解释如下表所示。更多参数说明,请参见DescribeSystemEventAttribute。字段
说明
示例值
instanceId
抢占式实例的ID。
i-bp1ecr********5go2go
action
抢占式实例的操作事件。取值delete时表示抢占式实例中断,将被强制回收。
delete
方式二:通过元数据在实例内部查询
Linux实例
# 获取元数据服务器的访问凭证用于鉴权
TOKEN=`curl -X PUT "http://100.100.100.200/latest/api/token" -H "X-aliyun-ecs-metadata-token-ttl-seconds:<元数据服务器访问凭证有效期>"`
# 查询抢占式实例是否被中断回收
curl -H "X-aliyun-ecs-metadata-token: $TOKEN" http://100.100.100.200/latest/meta-data/instance/spot/termination-time
Windows实例
# 获取元数据服务器的访问凭证用于鉴权
$token = Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token-ttl-seconds" = "<元数据服务器访问凭证有效期>"} -Method PUT –Uri http://100.100.100.200/latest/api/token
# 查询抢占式实例是否被中断回收
Invoke-RestMethod -Headers @{"X-aliyun-ecs-metadata-token" = $token} -Method GET -Uri http://100.100.100.200/latest/meta-data/instance/spot/termination-time
如果返回404:实例可持续使用。
如果返回类似
2015-01-05T18:02:00Z
格式的信息(UTC时间):实例将于这个时间被回收。
方式三:通过API查询
调用DescribeInstances,并根据返回的OperationLocks判断实例是否进入待回收状态。
若返回空值:实例可持续使用。
若返回LockReason值为Recycling:抢占式实例被中断,处于待回收状态。
代码示例(DescribeInstancesSample.java)如下所示:
import com.alibaba.fastjson.JSONArray;
import com.aliyuncs.AcsRequest;
import com.aliyuncs.AcsResponse;
import com.aliyuncs.DefaultAcsClient;
import com.aliyuncs.IAcsClient;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesRequest;
import com.aliyuncs.ecs.model.v20140526.DescribeInstancesResponse;
import com.aliyuncs.profile.DefaultProfile;
import com.aliyuncs.profile.IClientProfile;
import java.util.*;
public class DescribeInstancesSample {
public static void main(String[] args) throws InterruptedException {
// 初始化DefaultAcsClient实例。
OpenApiCaller caller = new OpenApiCaller();
// 设置待查询的一个或多个ECS实例ID。
JSONArray allInstances = new JSONArray();
allInstances.addAll(Arrays.asList("i-bp1i9c3qiv1qs6nc****"));
while (!allInstances.isEmpty()) {
DescribeInstancesRequest request = new DescribeInstancesRequest();
// 指定实例所在的地域。
request.setRegionId("cn-hangzhou");
// 指定实例ID,查询效率高。
request.setInstanceIds(allInstances.toJSONString());
// 接收响应结果。
DescribeInstancesResponse response = caller.doAction(request);
// 获取实例相关的返回结果。
List<DescribeInstancesResponse.Instance> instanceList = response.getInstances();
if (instanceList != null && !instanceList.isEmpty()) {
for (DescribeInstancesResponse.Instance instance : instanceList) {
// 输出被查询的实例ID与可用区信息。
System.out.println("result:instance:" + instance.getInstanceId() + ",az:" + instance.getZoneId());
if (instance.getOperationLocks() != null) {
for (DescribeInstancesResponse.Instance.LockReason lockReason : instance.getOperationLocks()) {
// 如果实例被锁定,输出指定实例ID以及对应的锁定类型。
System.out.println("instance:" + instance.getInstanceId() + "-->lockReason:" + lockReason.getLockReason() + ",vmStatus:" + instance.getStatus());
if ("Recycling".equals(lockReason.getLockReason())) {
// 输出即将被回收的实例ID信息。
System.out.println("spot instance will be recycled immediately, instance id:" + instance.getInstanceId());
allInstances.remove(instance.getInstanceId());
}
}
}
}
// 如果抢占式实例还未被锁定,将每隔两分钟查询一次。
System.out.print("try describeInstances again later ...");
Thread.sleep(2 * 60 * 1000);
} else {
break;
}
}
}
}
// 初始化DefaultAcsClient实例的类。
class OpenApiCaller{
IClientProfile profile;
IAcsClient client;
public OpenApiCaller() {
// 请确保代码运行环境设置了环境变量ALIBABA_CLOUD_ACCESS_KEY_ID和ALIBABA_CLOUD_ACCESS_KEY_SECRET。
// 工程代码泄露可能会导致AccessKey泄露,并威胁账号下所有资源的安全性。以下代码示例使用环境变量获取AccessKey的方式进行调用,建议使用更安全的STS方式。
profile = DefaultProfile.getProfile("cn-hangzhou", System.getenv("ALIBABA_CLOUD_ACCESS_KEY_ID"), System.getenv("ALIBABA_CLOUD_ACCESS_KEY_SECRET"));
client = new DefaultAcsClient(profile);
}
public <T extends AcsResponse> T doAction(AcsRequest<T> var1) {
try {
return client.getAcsResponse(var1);
} catch (Throwable e) {
e.printStackTrace();
return null;
}
}
}
触发回收时输出结果如下:
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****