Flexera’s 2026 State of the Cloud Report puts estimated wasted spend on IaaS and PaaS at 29%, the first increase after five years of decline, and attributes the reversal to cost complexity from AI and newer services. Part of that number has a simple shape. An accelerator is billed whole and used in fractions: an inference service that needs 3 GB of GPU memory still holds a card with 24.
Amazon ECS addressed this directly in August 2026 with fractional GPU scheduling on G6f instances, where a task definition asks for GPU=0.125 and lands on an eighth of an NVIDIA L4. Amazon EKS has no equivalent field. On Kubernetes you assemble GPU sharing yourself from four mechanisms, and they sit on different axes rather than on one scale of aggressiveness. Each isolates something else, and one of them isolates nothing at all.
Four mechanisms, one question
Time-slicing lets the GPU’s CUDA scheduler multiplex work from several pods. Software only, available on every NVIDIA instance type on AWS, and no memory or compute isolation whatsoever. MPS (Multi-Process Service) runs several processes against one GPU context, so kernels execute concurrently instead of taking turns. MIG (Multi-Instance GPU) partitions the silicon into instances with dedicated memory, compute units and bandwidth. DRA (Dynamic Resource Allocation) is the scheduling model that replaced counted extended resources, and it drives both time-slicing and MIG.
| Mechanism | Memory isolation | Hardware support | Main constraint |
|---|---|---|---|
| Time-slicing | None. Pods share GPU memory | Every NVIDIA instance type | One pod can exhaust memory the others need |
| MPS | None, but concurrent execution | Every NVIDIA instance type | Requires EXCLUSIVE_PROCESS compute mode |
| MIG | Hardware memory and fault isolation | A100, H100, H200, Blackwell (P family, g7, g7e) | Repartitioning needs a GPU reset, so a node reboot |
| DRA | Whatever the underlying strategy gives | Kubernetes 1.34+, driver installed separately | Not supported on EKS Auto Mode |

Time-slicing with the device plugin
On AL2023 the NVIDIA device plugin reads its time-slicing configuration from a ConfigMap. The replicas value is how many slots each physical GPU advertises, and it is a scheduling number rather than a capacity one.
# yaml: four slots per physical GPU, AL2023 + NVIDIA device plugin
apiVersion: v1
kind: ConfigMap
metadata:
name: nvidia-device-plugin-config
namespace: nvidia
data:
config.yaml: |
version: v1
sharing:
timeSlicing:
renameByDefault: false
failRequestsGreaterThanOne: true
resources:
- name: nvidia.com/gpu
replicas: 4
One setting there matters more than it looks. failRequestsGreaterThanOne rejects a pod that asks for several slots, which is worth enabling because asking for two buys no extra compute and otherwise fails silently. The plugin also does not watch the ConfigMap, so a change needs its pods restarted.
On Bottlerocket the same thing is expressed as node settings, which Karpenter can supply through the EC2NodeClass user data:
# toml: Bottlerocket user data, supplied via a Karpenter EC2NodeClass
[settings.kubelet-device-plugins.nvidia]
device-sharing-strategy = "time-slicing"
[settings.kubelet-device-plugins.nvidia.time-slicing]
replicas = 4
rename-by-default = false
fail-requests-greater-than-one = true
Verify before trusting it. A node with one physical GPU should now advertise four:
# bash: confirm the advertised slot count, then confirm pods share one device
kubectl get nodes \
"-o=custom-columns=NAME:.metadata.name,GPU:.status.allocatable.nvidia\.com/gpu"
# every pod on a shared GPU reports the same UUID
kubectl logs -l app=timeslicing-demo --prefix
Four slots are a scheduling promise, not four GPUs’ worth of memory.
MIG, where the isolation is real
MIG partitions a physical GPU into instances with their own memory, compute slices and bandwidth, so a workload on one cannot affect a workload on another. Profiles follow the pattern <slices>g.<memory>gb and the hardware fixes which ones exist: an A100 40 GB offers seven 1g.5gb instances, three 2g.10gb, two 3g.20gb, up to one whole-card 7g.40gb.
On Bottlerocket, MIG is again node settings, and the profile is keyed by GPU model. A p4d.24xlarge partitioned this way advertises 24 instances, because eight A100s each carry three 2g.10gb partitions:
# toml: Bottlerocket single-strategy MIG on p4d.24xlarge
[settings.kubelet-device-plugins.nvidia]
device-partitioning-strategy = "mig"
[settings.kubelet-device-plugins.nvidia.mig.profile]
"a100.40gb" = "2g.10gb"
That is the single strategy: one profile per node, pods keep requesting a plain nvidia.com/gpu, existing manifests do not change. Mixed profiles on one node need the AL2023 path with the NVIDIA GPU Operator and its MIG Manager, where the layout is declared per device index and applied by labelling the node:
# yaml: GPU Operator values, mixed strategy, half the GPUs partitioned
mig:
strategy: mixed
migManager:
enabled: true
env:
- name: WITH_REBOOT
value: "true"
config:
create: true
name: custom-mig-parted-configs
default: all-disabled
data:
config.yaml: |-
version: v1
mig-configs:
p4d-half-balanced:
- devices: [0, 1, 2, 3]
mig-enabled: true
mig-devices:
"1g.5gb": 2
"2g.10gb": 1
"3g.20gb": 1
- devices: [4, 5, 6, 7]
mig-enabled: false
Under the mixed strategy pods stop asking for nvidia.com/gpu and start naming the profile. A pod that requests one the node does not advertise sits in Pending with nothing obviously wrong, which is the failure mode to watch for in review.
# yaml: mixed strategy, the pod names the profile it needs
resources:
limits:
nvidia.com/mig-1g.5gb: 1
# bash: what the node actually advertises
kubectl describe node <node-name> | grep nvidia.com
DRA, and why it changes the shape of the problem
Dynamic Resource Allocation reached general availability in Kubernetes 1.34 and describes devices by attributes instead of counting them. That is what removes the single-versus-mixed question entirely: the NVIDIA DRA driver publishes each MIG instance as a device in the mig.nvidia.com DeviceClass carrying its profile and its parentUUID, and a claim selects what it needs with a CEL expression.
# yaml: claim a specific MIG profile by attribute rather than by resource name
apiVersion: resource.k8s.io/v1
kind: ResourceClaimTemplate
metadata:
name: mig-profile-1g-5gb
spec:
spec:
devices:
requests:
- name: mig
exactly:
deviceClassName: mig.nvidia.com
selectors:
- cel:
expression: "device.attributes['gpu.nvidia.com'].profile == '1g.5gb'"
The same model drives time-slicing, with a limitation worth knowing before you design around it. DRA time-slicing is user-mediated: pods share a GPU only by pointing at the same ResourceClaim, and a claim is namespace-scoped, so sharing cannot cross namespaces.
# yaml: pods that reference this claim share one physical GPU
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
name: shared-timeslice-gpu
spec:
devices:
requests:
- name: gpu
exactly:
deviceClassName: gpu.nvidia.com
count: 1
config:
- requests: ["gpu"]
opaque:
driver: gpu.nvidia.com
parameters:
apiVersion: resource.nvidia.com/v1beta1
kind: GpuConfig
sharing:
strategy: TimeSlicing
timeSlicingConfig:
interval: Long
The trade-offs, stated plainly
- Time-slicing has no memory isolation. Match the slot count to the workload’s memory footprint, or use MIG.
- Per-container GPU metrics disappear. DCGM cannot attribute metrics to individual containers while time-slicing is active. GPU-level metrics survive, but you can no longer say which pod consumed what, which stings if cost allocation was the reason you started.
- Karpenter counts slots as cards. Karpenter treats each
nvidia.com/gpurequest as a physical GPU even with time-slicing on, so provisioning runs against a number that no longer means what it says. - Time-slicing and MPS cannot share a GPU. Time-slicing sets compute mode
DEFAULT, MPS requiresEXCLUSIVE_PROCESS. Both can live in one cluster, never on one device. Time-slicing also has no effect on a MIG instance; to share one of those, use MPS. - MIG is not free to change. Enabling MIG mode or altering the layout needs a GPU reset, which the GPU Operator performs by rebooting the node. MIG also disables NCCL and cross-GPU peer-to-peer, so multi-GPU training built on collective communication needs whole cards. On g5, g6 and g6e there is no MIG at all, and time-slicing is the only option.
- Alpha where it matters most. DRA time-slicing needs the
TimeSlicingSettingsfeature gate and dynamic MIG needsDynamicMIG, both off by default. Dynamic MIG also depends on partitionable devices (KEP-4815), enabled by default only from Kubernetes 1.36. - EKS Auto Mode opts you out. Auto Mode manages the device plugin and does not expose its configuration, so neither time-slicing nor MIG can be set there, and the DRA driver is unsupported. This is a self-managed Karpenter or managed node group decision.
Picking one
None of these mechanisms raises utilization on its own. They change how a device is divided. Whether the fleet is busy comes down to scheduling policy, how honestly requests are sized, and what happens to the node between bursts.
We met the same economics one device down, on a client’s CI estate. A browser vendor building Chromium for Windows, Linux and Android could reach 1200 vCPUs at peak, spinning up more than a hundred machines ten to twenty times a day for roughly twenty minutes each. Part of the answer was commercial: the infrastructure underneath moved to Azure, where partnership discounts applied. The larger part was structural. Self-hosted GitHub Actions runners on AKS scaling to dozens of concurrent executions and back to nothing, Windows builds containerized to run in the cluster, spot instances underneath, the whole estate in Terraform and Terragrunt. A fleet sized for the peak is paid for at the trough too, and no discount fixes that.
Accelerators make that mistake more expensive per hour. Start with allocation, because a device nobody owns is a device nobody right-sizes. Then pick the mechanism from what the workload needs isolated. Multi-tenant inference with unpredictable neighbours wants MIG. Researchers sharing a g6 for notebooks want time-slicing and a slot count that matches their model sizes. A platform that expects to keep changing shape wants DRA, with the feature-gate caveats written down where the next engineer will find them.
Facing this on your stack? Naviteq’s senior platform team does this for SaaS, FinTech, and Enterprise teams across the US, EU, and Israel. Let’s talk.