Compared with the native Kubernetes scheduler, ACK extends scheduling with Gang Scheduling, CPU topology-aware scheduling, ECI elastic scheduling, and more. Install the ack-co-scheduler add-on on a registered cluster to use ACK scheduling in your local cluster and improve efficiency for big data, AI, and other compute-intensive workloads.ack-co-scheduler in a registered cluster to enable Gang Scheduling, CPU topology-aware scheduling, and ECI elastic scheduling for compute-intensive workloads.
Prerequisites
Make sure you have:
-
Your self-managed Kubernetes cluster is connected to an ACK One registered cluster.
-
System components at these versions:
Component Version Kubernetes 1.18.8 or later Helm 3.0 or later Docker 19.03.5 Operating system CentOS 7.6, CentOS 7.7, Ubuntu 16.04, Ubuntu 18.04, Alibaba Cloud Linux
Usage notes
Set .template.spec.schedulerName to ack-co-scheduler in your job spec to route pods through the ACK co-scheduler instead of the default scheduler.
Install the ack-co-scheduler component
Use onectl for scripted environments. Use the console for a UI-based approach.
Install using onectl
-
Install onectl on your machine.
-
Install ack-co-scheduler:
onectl addon install ack-co-schedulerExpected output:
Addon ack-co-scheduler, version **** installed.
Install using the console
-
Log on to the Container Service Management Console. In the left navigation pane, click Clusters.
-
Click the name of your cluster. In the left navigation pane, click Add-ons.
-
On the Add-ons page, click the Others tab. Find ack-co-scheduler and click Install.
-
In the dialog box, click OK.
Gang scheduling
Gang scheduling enforces all-or-nothing pod placement: all pods in a group are scheduled together, or none are. This prevents resource deadlocks in distributed jobs such as MPI and AI training, where all workers must run simultaneously.
Submit a TensorFlow distributed job
This example submits a TensorFlow distributed training job with Gang Scheduling. Both PS and Worker pods use pod-group.scheduling.sigs.k8s.io labels to form a pod group.
apiVersion: "kubeflow.org/v1"
kind: "TFJob"
metadata:
name: "tf-smoke-gpu"
spec:
tfReplicaSpecs:
PS:
replicas: 1
template:
metadata:
creationTimestamp: null
labels:
pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
pod-group.scheduling.sigs.k8s.io/min-available: "2"
spec:
schedulerName: ack-co-scheduler # Route pods through the ACK co-scheduler.
containers:
- args:
- python
- tf_cnn_benchmarks.py
- --batch_size=32
- --model=resnet50
- --variable_update=parameter_server
- --flush_stdout=true
- --num_gpus=1
- --local_parameter_device=cpu
- --device=cpu
- --data_format=NHWC
image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3
name: tensorflow
ports:
- containerPort: 2222
name: tfjob-port
resources:
limits:
cpu: '10'
workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
restartPolicy: OnFailure
Worker:
replicas: 4
template:
metadata:
creationTimestamp: null
labels:
pod-group.scheduling.sigs.k8s.io/name: tf-smoke-gpu
pod-group.scheduling.sigs.k8s.io/min-available: "2"
spec:
schedulerName: ack-co-scheduler
containers:
- args:
- python
- tf_cnn_benchmarks.py
- --batch_size=32
- --model=resnet50
- --variable_update=parameter_server
- --flush_stdout=true
- --num_gpus=1
- --local_parameter_device=cpu
- --device=gpu
- --data_format=NHWC
image: registry.cn-hangzhou.aliyuncs.com/kubeflow-images-public/tf-benchmarks-cpu:v20171202-bdab599-dirty-284af3
name: tensorflow
ports:
- containerPort: 2222
name: tfjob-port
resources:
limits:
cpu: 10
workingDir: /opt/tf-benchmarks/scripts/tf_cnn_benchmarks
restartPolicy: OnFailure
Key fields:
| Field | Description |
|---|---|
pod-group.scheduling.sigs.k8s.io/name |
Groups pods into a pod group. Pods with the same name are scheduled together. |
pod-group.scheduling.sigs.k8s.io/min-available |
Minimum pods that must be schedulable before any pod in the group starts. In this example, at least 2 of 5 pods (1 PS + 4 Workers) must be schedulable. |
schedulerName: ack-co-scheduler |
Routes the pod through the ACK co-scheduler. Set this on every pod template in the job. |
Verify Gang scheduling
After submitting the job, verify that pods enter a pending state together:
kubectl get pods -l pod-group.scheduling.sigs.k8s.io/name=tf-smoke-gpu
Pods remain in Pending until at least min-available pods are simultaneously schedulable. This is expected. If pods stay pending, check Events for scheduling messages:
kubectl describe pod <pod-name>
See Use Gang scheduling.
CPU topology-aware scheduling
CPU topology-aware scheduling pins container CPU cores to the same Non-Uniform Memory Access (NUMA) node, reducing cross-node memory latency. This benefits CPU-intensive workloads such as real-time inference and latency-sensitive services.
Prerequisites
The resource-controller component is deployed. See Manage add-ons.
Enable CPU topology-aware scheduling
Add the cpuset-scheduler: "true" annotation to your Deployment's pod template and set schedulerName to ack-co-scheduler:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-numa
labels:
app: nginx-numa
spec:
replicas: 2
selector:
matchLabels:
app: nginx-numa
template:
metadata:
annotations:
cpuset-scheduler: "true" # Enable CPU topology-aware scheduling.
labels:
app: nginx-numa
spec:
schedulerName: ack-co-scheduler # Route pods through the ACK co-scheduler.
containers:
- name: nginx-numa
image: nginx:1.13.3
ports:
- containerPort: 80
resources:
requests:
cpu: 4
limits:
cpu: 4
Key fields:
| Field | Description |
|---|---|
cpuset-scheduler: "true" |
Pins the pod's CPU cores to a single NUMA node. Set under template.metadata.annotations. |
schedulerName: ack-co-scheduler |
Routes the pod through the ACK co-scheduler. |
resources.requests.cpu / resources.limits.cpu |
CPU resource requests and limits for the container. |
Verify CPU topology-aware scheduling
Once running, confirm pods were scheduled with cpuset pinning:
kubectl get pods -l app=nginx-numa -o wide
To confirm NUMA pinning, log on to the node and check the container's cpuset:
cat /sys/fs/cgroup/cpuset/kubepods/pod<pod-uid>/<container-id>/cpuset.cpus
If all listed cores belong to the same NUMA node, cpuset pinning is active.
ECI elastic scheduling
ECI elastic scheduling controls whether pods run on Elastic Compute Service (ECS) nodes, Elastic Container Instance (ECI) resources, or burst to ECI only when ECS capacity is insufficient. Use it for workloads with spiky resource demands to avoid over-provisioning ECS nodes.
Prerequisites
The ack-virtual-node component is deployed. See Use ECI in ACK.
Enable ECI elastic scheduling
Add the alibabacloud.com/burst-resource annotation to your Deployment's pod template:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx
labels:
app: nginx
spec:
replicas: 4
selector:
matchLabels:
app: nginx
template:
metadata:
name: nginx
annotations:
alibabacloud.com/burst-resource: eci # Use ECI when ECS capacity is insufficient.
labels:
app: nginx
spec:
schedulerName: ack-co-scheduler # Route pods through the ACK co-scheduler.
containers:
- name: nginx
image: nginx
resources:
limits:
cpu: 2
requests:
cpu: 2
Annotation values for `alibabacloud.com/burst-resource`:
| Value | Behavior |
|---|---|
| Not set | Use only ECS nodes in the cluster. |
eci |
Use ECS nodes first; burst to ECI when ECS capacity is insufficient. |
eci_only |
Use only ECI resources. |
Verify ECI elastic scheduling
After deploying, check which nodes the pods are running on:
kubectl get pods -l app=nginx -o wide
See Use ElasticResource to implement ECI elastic scheduling (deprecated).
Shared GPU scheduling
Shared GPU scheduling lets multiple pods share a single GPU, improving utilization for inference and workloads that do not require a full GPU.
See: