In multi-region fleet deployments, schedule GPU workloads using real-time ECS inventory and instant node elasticity to maximize placement success and avoid idle GPU nodes.
This feature is in invitational preview. To request access, submit a ticket.
How it works
In GPU inference scenarios, GPU supply varies by region and pre-provisioned GPU nodes incur high idle costs. Inventory-aware scheduling with instant node elasticity addresses both challenges. Three components enable inventory-aware elastic scheduling:
|
Component |
Role |
|
Fleet scheduler |
Detects shortfalls in child clusters, queries inventory via ACK GOATScaler, and distributes replicas by available capacity—including inventory not yet provisioned as nodes. |
|
ACK GOATScaler |
Runs in each child cluster, checks real-time ECS inventory, and returns available instance counts to the fleet scheduler. |
|
Child cluster node pools |
Uses instant node elasticity with zero desired nodes. Nodes scale out when the scheduler assigns workloads and scale in when workloads are removed. |
When you deploy an application to a fleet and no child cluster has enough running resources:
-
The scheduler detects insufficient resources in child clusters and cannot schedule the workload.
-
The scheduler triggers ACK GOATScaler in each child cluster to query inventory.
-
The scheduler redistributes the application to the cluster with available inventory.
-
The selected cluster scales out nodes and runs the application.
Prerequisites
You need:
-
Multiple associated clusters in the fleet for cross-cluster workload distribution.
-
Instant node elasticity enabled on each child cluster to scale out GPU nodes on demand.
-
The AMC command-line tool installed to verify pod distribution in Step 3.
If node autoscaling is enabled on a child cluster, switch to instant node elasticity. See Enable instant node elasticity.
GPU instance specifications and cost estimation
Model parameters consume most GPU memory during inference. Estimate required GPU memory with:
GPU memory = Number of parameters × Bytes per parameter
Example: 7B model, FP16 precision
|
Factor |
Value |
|
Parameters |
7 × 10⁹ |
|
Bytes per parameter (FP16) |
2 bytes |
|
Model memory |
7 × 10⁹ × 2 bytes ≈ 13.04 GiB |
Account for KV cache and computation buffers beyond model loading. For a 7B FP16 model, use a GPU instance with at least 24 GiB GPU memory, such as ecs.gn7i-c8g1.2xlarge or ecs.gn7i-c16g1.4xlarge.
For full instance type details and pricing, see GPU-accelerated compute optimized instance family and Elastic GPU Service billing.
Prepare model files and storage
Download the Qwen3-8B model and create OSS PersistentVolumes in each child cluster.
1. Download the model
Install Git Large File Storage (LFS) if needed: run yum install git-lfs or apt-get install git-lfs. See Install Git Large File Storage.
git lfs install
GIT_LFS_SKIP_SMUDGE=1 git clone https://www.modelscope.cn/Qwen/Qwen3-8B.git
cd Qwen3-8B
git lfs pull
2. Upload the model to OSS
See Install ossutil.
ossutil mkdir oss://<your-bucket-name>/models/Qwen3-8B
ossutil cp -r ./Qwen3-8B oss://<your-bucket-name>/models/Qwen3-8B
3. Create a PersistentVolume and PersistentVolumeClaim in each child cluster
See Use ossfs 1.0 static persistent volume.
apiVersion: v1
kind: Secret
metadata:
name: oss-secret
stringData:
akId: <your-oss-ak> # AccessKey ID for accessing OSS
akSecret: <your-oss-sk> # AccessKey Secret for accessing OSS
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: qwen3-8b
namespace: default
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 20Gi
selector:
matchLabels:
alicloud-pvname: qwen3-8b
storageClassName: oss
volumeMode: Filesystem
volumeName: qwen3-8b
---
apiVersion: v1
kind: PersistentVolume
metadata:
labels:
alicloud-pvname: qwen3-8b
name: qwen3-8b
spec:
accessModes:
- ReadWriteMany
capacity:
storage: 20Gi
csi:
driver: ossplugin.csi.alibabacloud.com
nodePublishSecretRef:
name: oss-secret
namespace: default
volumeAttributes:
bucket: <your-bucket-name> # Bucket name
otherOpts: '-o allow_other -o umask=000'
path: <your-model-path> # Example: /models/Qwen3-8B/
url: <your-bucket-endpoint> # Example: oss-cn-hangzhou-internal.aliyuncs.com
volumeHandle: qwen3-8b
persistentVolumeReclaimPolicy: Retain
storageClassName: oss
volumeMode: Filesystem
Step 1: Configure node pools for child clusters
In each child cluster, create or edit a GPU node pool with these settings:
|
Setting |
Value |
|
Instance type |
|
|
Scaling Mode |
Auto |
|
Desired nodes |
0 |
Zero desired nodes eliminate idle GPU costs. The pool scales out only when the fleet scheduler assigns workloads.
See Create and manage node pools.
Shorten the scale-in trigger delay in node pool settings to reduce wait time in Step 3.
Step 2: Create an application and distribution policy in the fleet cluster
Use the fleet cluster's kubeconfig for all resources in this step.
1. Create deploy.yaml
The Deployment runs 4 Qwen3-8B replicas with vLLM, each pod requesting 1 GPU.
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: qwen3-8b
name: qwen3-8b
namespace: default
spec:
replicas: 4
selector:
matchLabels:
app: qwen3-8b
template:
metadata:
labels:
app: qwen3-8b
spec:
volumes:
- name: qwen3-8b
persistentVolumeClaim:
claimName: qwen3-8b
- name: dshm
emptyDir:
medium: Memory
sizeLimit: 20Gi
containers:
- command:
- sh
- -c
- vllm serve /models/qwen3-8b --port 8000 --trust-remote-code --served-model-name qwen3-8b --tensor-parallel=1 --max-model-len 8192 --gpu-memory-utilization 0.95 --enforce-eager
image: kube-ai-registry.cn-shanghai.cr.aliyuncs.com/kube-ai/vllm-openai:v0.9.1
name: vllm
ports:
- containerPort: 8000
readinessProbe:
tcpSocket:
port: 8000
initialDelaySeconds: 30
periodSeconds: 30
resources:
limits:
nvidia.com/gpu: "1"
volumeMounts:
- mountPath: /models/qwen3-8b
name: qwen3-8b
- mountPath: /dev/shm
name: dshm
2. Create PropagationPolicy.yaml
The PropagationPolicy distributes the Deployment across two child clusters.
Key fields
|
Field |
Value |
Description |
|
|
|
Enables inventory-aware elastic scheduling and queries real-time ECS inventory when placing workloads. |
|
|
|
Distributes replicas across clusters. Use |
|
|
— |
Allocates replicas proportionally to each cluster's schedulable capacity—including ECS inventory. Clusters with available inventory get more replicas, even without running GPU nodes. |
apiVersion: policy.one.alibabacloud.com/v1alpha1
kind: PropagationPolicy
metadata:
name: demo-policy
spec:
# Enables inventory-aware elastic scheduling
autoScaling:
ecsProvision: true
preserveResourcesOnDeletion: false
conflictResolution: Overwrite
resourceSelectors:
- apiVersion: apps/v1
kind: Deployment
name: qwen3-8b
namespace: default
placement:
replicaScheduling:
replicaSchedulingType: Divided
weightPreference:
dynamicWeight: AvailableReplicas
clusterAffinity:
clusterNames:
- ${cluster1-id} # Replace with your actual child cluster ID
- ${cluster2-id} # Replace with your actual child cluster ID
3. Apply the manifests
kubectl apply -f deploy.yaml
kubectl apply -f PropagationPolicy.yaml
GPU node pools in both child clusters begin scaling out shortly after.
Step 3: Verify elastic scaling
Check workload scheduling status
kubectl get resourcebinding
Example output:
NAME SCHEDULED FULLYAPPLIED OVERRIDDEN ALLAVAILABLE AGE
qwen3-8b-deployment True True True False 7m47s
|
Field |
Value |
Meaning |
|
|
|
The fleet scheduler placed the workload across child clusters. |
|
|
|
Nodes are still scaling out—a normal intermediate state, not an error. Changes to |
Check pod distribution across clusters
When pods reach the Running state, run:
kubectl amc get deploy qwen3-8b -M
Example output:
NAME CLUSTER READY UP-TO-DATE AVAILABLE AGE ADOPTION
qwen3-8b cxxxxxxxxxxxxxx 2/2 2 2 3m22s Y
qwen3-8b cxxxxxxxxxxxxxx 2/2 2 2 3m22s Y
|
Field |
Value |
Meaning |
|
|
|
All replicas in the cluster are running. |
|
|
|
The cluster owns the workload. |
All 4 replicas run across both clusters, even though both had zero GPU nodes before deployment.
Verify scale-in behavior
Scale the Deployment to 2 replicas and re-apply:
kubectl apply -f deploy.yaml
Or delete the workload to simulate zero replicas.
After ten minutes, GPU node pools in each child cluster scale in to one node. If you deleted the workload, nodes scale in to zero.
This confirms the full workflow: the fleet schedules workloads from real-time inventory, scales out GPU nodes to run them, and scales back in when workloads are removed—eliminating idle GPU costs.