Running batch jobs and fault-tolerant workloads on standard pay-as-you-go instances is expensive when you only need the compute for a short window. Preemptible instances (also called spot instances) let you bid for unused Alibaba Cloud capacity and pay discounted market prices, significantly reducing compute costs. This topic explains how to configure preemptible Elastic Container Instance (ECI)-based pods in a Kubernetes cluster.
When to use preemptible instances
Preemptible instances are suitable for workloads that tolerate interruption and restart cleanly. Good candidates include:
Batch processing and short-lived jobs
Scalable web services with stateless replicas
Image rendering and media processing
Big data analysis and large-scale parallel computing
Do not run stateful workloads or services that cannot survive unexpected termination on preemptible instances.
How preemptible instances work
Billing
When you create a preemptible instance, you specify a bid price. If your bid exceeds the real-time market price and inventory is available, the instance starts and enters a protection period (1 hour by default). During this period, you are billed at the market price at the time of creation and the instance is guaranteed to run. After the protection period, billing switches to the real-time market price.
Preemptible instances are billed at lower prices compared with pay-as-you-go instances. Billing is based on actual usage duration. For details, see the "Billing methods" section of the Preemptible instances topic.
Reclaim mechanism
After the protection period ends, ECI checks the market price and inventory every 5 minutes. If the market price exceeds your bid or inventory runs out, the instance is released.
A SpotToBeReleased event is generated approximately 3 minutes before release. Use this window to drain connections and save state. After reclaim, the instance information is retained, billing stops, and the status changes to Expired.
Creation methods
| Method | How it works | Billing basis |
|---|---|---|
| Specify an ECS instance type | Pin the workload to a specific instance type (for example, ecs.c6.large) | Real-time discounted pay-as-you-go price of that instance type |
| Specify vCPU and memory | ECI selects an instance type that meets your vCPU and memory requirements | Real-time discounted market price of the selected instance type (not the vCPU/memory pay-as-you-go rate) |
The vCPU/memory method requires at least 2 vCPUs. Supported combinations:
| vCPUs | Memory (GiB) |
|---|---|
| 2 | 2, 4, 8, 16 |
| 4 | 4, 8, 16, 32 |
| 8 | 8, 16, 32, 64 |
| 12 | 12, 24, 48, 96 |
| 16 | 16, 32, 64, 128 |
| 24 | 24, 48, 96, 192 |
| 32 | 32, 64, 128, 256 |
| 52 | 96, 192, 384 |
| 64 | 128, 256, 512 |
If you specify a combination that is not listed, ECI automatically uses the next supported higher specification.
Prerequisites
Before you begin, make sure that you have:
A Kubernetes cluster with an ECI virtual node
Permission to create pods and jobs in the cluster
Reviewed the preemptible instance documentation to understand pricing and availability in your target zone
To choose a suitable instance type and bid, query historical pricing data with these ECS API operations:
DescribeSpotPriceHistory: returns price history for the past 30 days
DescribeSpotAdvice: returns average release rate and discount rate per instance type
Set your bid above the average market price but within a range that keeps costs acceptable for your workload. This improves the creation success rate while reducing the risk of release due to price fluctuation.
Store critical data on persistent storage that survives instance release — for example, an independent disk not tied to the instance lifecycle, or an external File Storage NAS file system.
Configure annotations
Add annotations to spec.template.metadata in your pod or job YAML to create a preemptible instance. Annotations are read only at creation time; adding or modifying them on an existing pod has no effect.
| Annotation | Example | Required | Description |
|---|---|---|---|
k8s.aliyun.com/eci-spot-strategy | SpotAsPriceGo | Yes | Bid policy. SpotAsPriceGo uses the market price at creation time. SpotWithPriceLimit caps the hourly price at the value you set. |
k8s.aliyun.com/eci-spot-price-limit | "0.5" | No | Maximum hourly price (up to three decimal places). Required when eci-spot-strategy is SpotWithPriceLimit. |
k8s.aliyun.com/eci-spot-duration | "0" | No | Protection period in hours. Default: 1. Set to 0 to disable the protection period. |
k8s.aliyun.com/eci-spot-fallback | "true" | No | When set to true, creates a pay-as-you-go instance if preemptible inventory is insufficient. Default: false. |
Add annotations to the metadata of pods. For jobs, use spec.template.metadata.
Examples
All examples create a Kubernetes Job. The alibabacloud.com/eci: "true" label routes the pod to the ECI virtual node.
Example 1: Fixed instance type with a price cap
Use SpotWithPriceLimit when you want to pin the workload to a specific instance type and set a hard upper bound on hourly cost.
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-use-specs: "ecs.c6.large" # Pin to a specific instance type.
k8s.aliyun.com/eci-spot-strategy: "SpotWithPriceLimit" # Cap the hourly price.
k8s.aliyun.com/eci-spot-price-limit: "0.25" # Maximum price per hour.
spec:
containers:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: NeverThis creates a preemptible ecs.c6.large instance with a 1-hour protection period. After the protection period:
If inventory is available and the market price is at or below
0.25per hour, the instance continues running.If the market price exceeds
0.25per hour or inventory runs out, the instance is released.
If inventory or pricing conditions are not met at creation time, the instance is not created.
Example 2: Auto-selected instance type at market price
Use SpotAsPriceGo when you want ECI to automatically select an instance type based on your vCPU and memory requirements, bidding at the current market price.
Option A: Specify resources in the container spec
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" # Bid at the current market price.
spec:
containers:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
resources:
limits:
cpu: 2000m # 2 vCPUs
memory: 4096Mi # 4 GiB memory
restartPolicy: NeverOption B: Specify resources in an annotation
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-use-specs: "2-4Gi" # 2 vCPUs, 4 GiB memory.
k8s.aliyun.com/eci-spot-strategy: "SpotAsPriceGo" # Bid at the current market price.
spec:
containers:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: NeverBoth options create a preemptible instance with 2 vCPUs and 4 GiB of memory. After the 1-hour protection period, the instance is released if the market price rises or inventory runs out.
If SpotAsPriceGo is set and resources in the target zone are insufficient, set the eci-spot-price-limit annotation to a value close to the pay-as-you-go price for the instance type. This improves the creation success rate.
Example 3: No protection period
Example 4: Fallback to pay-as-you-go
Set eci-spot-fallback to "true" to automatically create a pay-as-you-go instance if preemptible inventory is insufficient. This guarantees that a pod is created even when spot capacity is unavailable.
apiVersion: batch/v1
kind: Job
metadata:
name: test
spec:
template:
metadata:
labels:
app: perl
alibabacloud.com/eci: "true"
annotations:
k8s.aliyun.com/eci-use-specs: "ecs.c6.large"
k8s.aliyun.com/eci-spot-strategy: "SpotWithPriceLimit"
k8s.aliyun.com/eci-spot-price-limit: "0.05"
k8s.aliyun.com/eci-spot-fallback: "true" # Fall back to pay-as-you-go if spot is unavailable.
spec:
containers:
- name: pi
image: registry.cn-shanghai.aliyuncs.com/eci_open/perl:5
command: ["perl", "-Mbignum=bpi", "-wle", "print bpi(2000)"]
restartPolicy: NeverBehavior after the pod is created:
Preemptible instance created: runs normally during the 1-hour protection period; released after the period if the market price exceeds
0.05per hour or inventory runs out.Pay-as-you-go instance created: runs until explicitly deleted; not automatically released.
To check which type was created, run kubectl describe pod and look for a SpotDegraded event. If present, the pod is running on a pay-as-you-go instance.

Monitor preemptible instance status
Interruption warning
ECI generates a SpotToBeReleased event approximately 3 minutes before releasing a preemptible instance. The ContainerInstanceExpired condition in the pod is also set to true. Use this window to drain in-flight requests or checkpoint work.
Run kubectl describe <pod-name> and check the Events section:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning SpotToBeReleased 3m32s kubelet, eci Spot ECI will be released in 3 minutesOr run kubectl get events to list all events:
LAST SEEN TYPE REASON OBJECT MESSAGE
3m39s Warning SpotToBeReleased pod/pi-frmr8 Spot ECI will be released in 3 minutesStatus after release
After a preemptible instance is released, its record is retained. Run kubectl get pod to see the updated status:
NAME READY STATUS RESTARTS AGE
pi-frmr8 1/1 BidFailed 0 3h5mRun kubectl describe <pod-name> for the full status:
Status: Failed
Reason: BidFailed
Message: The pod is spot instance, and have been released at 2020-04-08T12:36ZConfigure graceful termination
To minimize service disruption when a preemptible instance is reclaimed, add the k8s.aliyun.com/eci-spot-release-strategy: api-evict annotation to your pod. When the virtual node receives a SpotToBeReleased event, it calls the Kubernetes Eviction API to evict the pod gracefully.
Graceful termination via the Eviction API requires ack-virtual-node 2.11.0 or later. For upgrade instructions, see ACK Virtual Node.
The eviction process respects your PodDisruptionBudget (PDB) and the terminationGracePeriodSeconds setting on the pod. The sequence is:
Virtual node receives the
SpotToBeReleasedevent and calls the Eviction API.The API server checks the PDB for the pod.
If eviction is allowed:
The pod's deletion timestamp is set and the grace period begins.
The kubelet on the virtual node initiates graceful termination.
The control plane removes the pod from Endpoints and EndpointSlices.
After the grace period, the kubelet forcefully terminates the pod.
The kubelet notifies the API server, which deletes the pod.
If the pod is managed by a controller (ReplicaSet, StatefulSet, Job, or a fault-tolerant SparkApplication or workflow), the controller automatically creates a replacement pod.
If the PDB is misconfigured or too many pods are in a non-Ready state, eviction may stall. If eviction is not complete when the instance expires, the instance is released directly without waiting for the grace period to finish.
What's next
Learn about preemptible instance pricing: Preemptible instances
Query historical spot prices with DescribeSpotPriceHistory and DescribeSpotAdvice
Manage virtual nodes: ACK Virtual Node