KAI Scheduler supports fractional GPU scheduling so that multiple workloads can share GPU devices.
Administrators select the cluster GPU-sharing mode, and users request fractional GPUs with pod annotations.
The intended audience for this page is cluster administrators who install and configure KAI Scheduler, and users who submit GPU-sharing workloads.
Make sure the following conditions are met:
- A Kubernetes cluster is running.
- The
kubectlcommand-line tool has communication with your cluster. - Helm is installed.
- KAI Scheduler is installed or ready to be installed.
- NVIDIA GPU Operator is installed.
For NvFractions, also make sure the cluster can run the gpu-sharing operator and that NVIDIA CDI/NRI support is configured when runtime memory enforcement is required.
Administrators choose one GPU-sharing mode for the cluster. The mode configures the default admission and binder plugin behavior used by KAI.
| Mode | Purpose | Runtime enforcement | Main user annotations |
|---|---|---|---|
Disabled |
Reject fractional GPU workloads. | None. | None. |
NonMemoryEnforced |
Schedule fractional GPU workloads without runtime memory isolation. This is the default mode. | Not enforced by KAI. Containers may see and use more GPU memory than requested. | gpu-fraction, gpu-memory |
HamiCore |
Schedule fractional GPU workloads and use HAMi-core for CUDA memory isolation. | Enforced through HAMi-core. | gpu-fraction, gpu-memory |
NvFractions |
Schedule fractional GPU workloads using NvFractions annotations and the GPU-sharing operator. | Enforced by the NvFractions runtime path when CDI/NRI is configured. | nvidia.com/container.<container>.gpu-memory.request, nvidia.com/container.<container>.gpu-memory.limit |
Set the mode with global.gpuSharingMode. The legacy global.gpuSharing value is deprecated and should only be used for upgrades that still rely on the old boolean value.
Use NonMemoryEnforced when the scheduler should place fractional GPU pods but the cluster does not need KAI to enforce CUDA memory limits:
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set global.gpuSharingMode=NonMemoryEnforcedThis mode keeps the legacy GPU-sharing behavior. It creates reservation pods in the kai-resource-reservation namespace and uses KAI's shared GPU metadata path.
Use HamiCore when workloads should continue to use the gpu-fraction and gpu-memory annotations, but GPU memory limits are be enforced by HAMi-core
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set global.gpuSharingMode=HamiCoreThen install kai-resource-isolator.
See HAMi Resource Isolation for more details.
Use NvFractions when the cluster should use the GPU-sharing operator and NvFractions annotations:
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set global.nvFractions.set=trueSetting global.nvFractions.set=true installs the gpu-sharing Helm dependency from oci://ghcr.io/kai-scheduler/gpu-sharing and renders KAI with global.gpuSharingMode=NvFractions.
If the gpu-sharing operator is already installed and managed separately, do not install the subchart from KAI. Set global.gpuSharingMode=NvFractions and keep global.nvFractions.set=false:
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set global.gpuSharingMode=NvFractions \
--set global.nvFractions.set=falseYou may set the mode explicitly, but it must match:
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set global.gpuSharingMode=NvFractions \
--set global.nvFractions.set=trueThe chart rejects global.nvFractions.set=true when global.gpuSharingMode is set to another mode.
KAI's global scheduling placement values are not propagated into the gpu-sharing subchart. Configure the subchart under the top-level gpu-sharing key:
global:
nvFractions:
set: true
gpu-sharing:
imagePullSecrets:
- name: registry-credentials
nodeSelector:
nvidia.com/gpu.present: "true"
tolerations:
- key: nvidia.com/gpu
operator: Exists
effect: NoScheduleFor air-gapped environments, mirror both the KAI images and the gpu-sharing operator chart and images, or vendor the dependency before installing.
KAI can auto-detect CDI and the CDI NRI plugin from the NVIDIA GPU Operator ClusterPolicy. When the ClusterPolicy indicates that CDI is enabled and selected as the default device injection path, KAI configures its CDI-aware binder plugins automatically. When NRI is enabled, KAI also enables the admission behavior that avoids injecting the legacy GPU-sharing environment variables.
Use that detection to decide whether fractional GPU pods need a runtime class:
- If the cluster uses CDI as the default GPU device injection path, fractional GPU pods usually do not need
runtimeClassName: nvidia; setadmission.gpuFractionRuntimeClassName=null. - If the cluster does not use CDI as the default path and the default container runtime is not already NVIDIA-enabled, keep the default
admission.gpuFractionRuntimeClassName=nvidiaor set a custom runtime class. - If KAI cannot read the NVIDIA
ClusterPolicy, configure the runtime class and CDI behavior explicitly.
To suppress runtimeClassName injection on fractional GPU pods:
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set admission.gpuFractionRuntimeClassName=nullKAI also creates GPU reservation pods for fractional GPU workloads. If reservation pods need a runtime class for GPU access, set it separately:
helm upgrade -i kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
-n kai-scheduler --create-namespace \
--set binder.runtimeClassName=nvidiaYou can also set binder.cdiEnabled or the binder plugin cdiEnabled argument explicitly in the KAI Config if CDI auto-detection is not available in your environment.
In NvFractions mode, KAI waits for the GPU-sharing operator before scheduling fractional GPU pods.
The operator must create a cluster-scoped GpuSharingConfig named default with a Ready=True condition:
kubectl get gpusharingconfig default -o yamlGPU nodes must also have the node condition gpu-sharing.nvidia.com/Ready=True. If the condition is missing or false, KAI reports a fit error that includes the condition status, reason, and message.
KAI admission validates fractional GPU requests before scheduling:
- A pod cannot combine a fractional GPU request with a whole
nvidia.com/gpurequest or limit. gpu-fractionmust be greater than0and smaller than1.gpu-memorymust be a positive integer in MiB.- NvFractions memory values must be valid positive Kubernetes memory quantities, such as
512Mi,1Gi, or7680Mi. - NvFractions request must be less than or equal to limit when both are present.
- Only one container in a pod can request a fractional GPU.
- NvFractions annotations must reference an existing container.
- Users cannot create or modify
nvidia.com/container.<container>.gpus.devices; KAI Binder writes that annotation after allocation.
Users request fractional GPUs with pod annotations. All fractional GPU pods must use the KAI scheduler and must belong to a KAI queue.
metadata:
labels:
kai.scheduler/queue: default-queue
spec:
schedulerName: kai-schedulerUse the annotation style that matches the cluster mode selected by your administrator. In NvFractions mode, the legacy gpu-fraction and gpu-memory annotations are still supported for backwards compatibility, but new memory-based workloads should prefer the per-container NvFractions request annotation.
| User goal | Use this when the cluster mode is | Annotation |
|---|---|---|
| Request a fraction of one GPU by proportion | NonMemoryEnforced, HamiCore, or NvFractions |
gpu-fraction: "0.5" |
| Request a specific memory amount in MiB | NonMemoryEnforced, HamiCore, or NvFractions for compatibility |
gpu-memory: "4096" |
| Request a specific memory amount with Kubernetes quantity syntax | NvFractions preferred for memory-based requests |
nvidia.com/container.<container>.gpu-memory.request: 4096Mi |
| Set a runtime memory limit that differs from the scheduling request | NvFractions |
nvidia.com/container.<container>.gpu-memory.limit: 8192Mi |
| Request fractional allocations on more than one GPU device | Any GPU-sharing mode | gpu-fraction-num-devices: "2" |
The gpu-fraction annotation requests a portion of one GPU. For example, 0.5 reserves half of one GPU's memory capacity:
apiVersion: v1
kind: Pod
metadata:
name: half-gpu
labels:
kai.scheduler/queue: default-queue
annotations:
gpu-fraction: "0.5"
spec:
schedulerName: kai-scheduler
containers:
- name: gpu-workload
image: nvidia/cuda:13.0.2-base-ubi8
command: ["nvidia-smi"]
args: ["--query-gpu=name,memory.total", "--format=csv,noheader"]Create the example:
kubectl apply -f gpu-sharing.yamlThe gpu-memory annotation requests a specific GPU memory amount in MiB:
metadata:
annotations:
gpu-memory: "4096"In NonMemoryEnforced mode, KAI uses this value for scheduling only. In HamiCore mode, HAMi-core also uses it for runtime memory isolation. In NvFractions mode, gpu-memory remains supported for backwards compatibility with existing manifests, but nvidia.com/container.<container>.gpu-memory.request is preferred because it names the target container directly and uses Kubernetes quantity syntax.
Create the example:
kubectl apply -f gpu-memory-mib-annotation.yamlNvFractions uses per-container annotations. The container name is part of the annotation key:
metadata:
annotations:
nvidia.com/container.gpu-workload.gpu-memory.request: 7680Mi
spec:
containers:
- name: gpu-workloadCreate the example:
kubectl apply -f nv-fractions-memory.yamlKAI schedules the pod using the request value. If a limit is also present, the request must be less than or equal to the limit:
metadata:
annotations:
nvidia.com/container.gpu-workload.gpu-memory.request: 4096Mi
nvidia.com/container.gpu-workload.gpu-memory.limit: 8192MiCreate the request-and-limit example:
kubectl apply -f nv-fractions-request-limit.yamlIf only limit is present, KAI defaults the request to the same value.
Add gpu-fraction-num-devices when the workload needs fractional capacity from more than one GPU:
metadata:
annotations:
nvidia.com/container.gpu-workload.gpu-memory.request: 7680Mi
gpu-fraction-num-devices: "2"This asks KAI to allocate the requested fractional memory on each of two GPU devices.
KAI uses the resolved request for scheduling, pod group resource accounting, and node scale adjustment. For memory-based requests, gpu-fraction-num-devices multiplies the requested memory by the number of fractional devices.
By default, legacy fractional requests apply to the first container. In NonMemoryEnforced and HamiCore modes, select another container with gpu-fraction-container-name:
metadata:
annotations:
gpu-fraction: "0.5"
gpu-fraction-container-name: gpu-workloadIn NvFractions mode, the target container is already encoded in the annotation key. gpu-fraction-container-name is still supported for backwards compatibility with legacy annotations; if it is present together with NvFractions annotations, it must match the container name in the NvFractions annotation key.
Create the non-default-container example:
kubectl apply -f gpu-sharing-non-default-container.yamlPods that share a GPU must use compatible compute sharing behavior within the same fractional GPU group. Use kai.scheduler/gpu-compute-sharing-mode when the workload needs to declare its compute sharing mode explicitly:
metadata:
annotations:
gpu-fraction: "0.5"
kai.scheduler/gpu-compute-sharing-mode: time-slicingKAI keeps pods with incompatible compute sharing modes out of the same fractional GPU group.
time-slicing is the default. Use sm-sharing for workloads that need to run
concurrently and have MPS configured. For guidance on choosing a mode, the
memory request and limit semantics, and diagrams of both models, see
NvFractions GPU Sharing.
Check the admission error. Common causes are:
gpu-fractionis1,0, negative, or not a number.gpu-memoryis not a positive integer in MiB.- NvFractions memory quantity is invalid or not positive.
- The pod requests both a fractional GPU and a whole
nvidia.com/gpu. - More than one container has NvFractions annotations.
- The NvFractions annotation references a container that does not exist.
Start with the pod status and events:
kubectl get pod <pod-name> -n <namespace> -o wide
kubectl describe pod <pod-name> -n <namespace>The events usually show whether the pod is blocked by scheduling, admission, or runtime setup.
Then check the GPU-sharing operator status:
kubectl get gpusharingconfig default -o yamlThen check the target GPU node conditions:
kubectl describe node <node-name>KAI requires gpu-sharing.nvidia.com/Ready=True on a node before scheduling NvFractions fractional GPU workloads there.
Do not combine global.nvFractions.set=true with another explicit mode:
helm template kai-scheduler oci://ghcr.io/kai-scheduler/kai-scheduler/kai-scheduler \
--set global.nvFractions.set=true \
--set global.gpuSharingMode=HamiCoreUse global.gpuSharingMode=NvFractions or leave global.gpuSharingMode empty when global.nvFractions.set=true.