You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Follow-up to #502, which lands GPU passthrough at the worker level. A pool requests N GPUs and every actor container gets all of them. The ActorTemplate containers have no say in the device layout, so device assignment is coupled to the worker.
Per Benjamin Elder (@BenTheElder) (review), device assignment should move into the ActorTemplate so it is decoupled from the worker and can control which containers in an actor receive the devices.
Use cases
Actors are pod-shaped (multiple containers, one gVisor sandbox, shared netns), so per-container device control unlocks:
Accelerator container plus CPU-only sidecar. The model or trainer container claims the accelerator (nvidia.com/gpu, amd.com/gpu, an FPGA); the logging, proxy, or metrics sidecar next to it claims none. Today every sidecar is handed the device nodes.
Security isolation. An untrusted or user-supplied sidecar is denied device access as defense in depth. Today it silently receives whatever the pod holds (/dev/nvidia*, an SR-IOV VF), widening the attack surface that feat: CDI-based NVIDIA GPU passthrough into gVisor actor containers #502 otherwise works to keep narrow.
Devices split across containers. On a multi-device node, worker containers each claim a distinct GPU for data-parallel or shard-per-container work over the shared netns.
Proposed API
Declare devices per-container using the standard Kubernetes resources shape, the same corev1.ResourceRequirements type the pool already uses. The pool reserves capacity; each container claims from it.
kind: WorkerPoolspec:
sandboxClass: gvisortemplate:
resources:
limits:
nvidia.com/gpu: "2"# pool reserves 2 GPUs on the node (unchanged; this is what schedules onto a GPU node)containers:
- name: trainerimage: pytorch@sha256:...resources:
limits:
nvidia.com/gpu: "2"# this container claims both
- name: sidecar-loggerimage: fluentbit@sha256:...# no gpu request, none injected (today it would wrongly get both)
One new field on Container:
// Resources for this container, including device-plugin resources such as// nvidia.com/gpu. Only nvidia.com/gpu is supported today.// +optionalResources*corev1.ResourceRequirements`json:"resources,omitempty"`
This reuses an existing type instead of inventing a devices selector, and:
is idiomatic: it matches vanilla Kubernetes per-container GPU requests;
is device-generic for free: extended resources already cover RDMA, FPGA, and others.
Scope
Add resources to ActorTemplate.Container.
CEL validation:
sum of container nvidia.com/gpu must not exceed the pool reservation;
reject device classes the runtime cannot yet inject. Only nvidia.com/gpu is injectable today; the field type stays vendor-neutral and the gate lifts per class;
extend the existing sandboxClass == 'gvisor' guard to the container level.
Plumb the per-container request through WorkerAssignment to ateom.
In ateom, partition the pod's assigned GPUs across the containers that request them, the way the device plugin does in real Kubernetes, instead of the unconditional per-container maybeInjectGPU. The partition must be deterministic, ordered by container.
Update the API guide.
Risks
Device identity is not stable across resume. CDI names are pod-local, so on restore the actor may land on different physical devices with new UUIDs and PCI IDs. Injection already re-runs on the restore path, so device paths are re-resolved. Remaining care:
an app that cached a device UUID or PCI ID before snapshot sees a different one after;
the container-to-device partition must be deterministic so a container keeps its ordinal across resume.
Pool reservation stays the scheduling knob. Keep the pool's resources.limits.nvidia.com/gpu as the reservation and validate that the containers' sum does not exceed it, rather than deriving the pool total from containers. Smaller change, single scheduling knob.
Out of scope
DRA. Dynamic Resource Allocation (resource.k8s.io, GA in 1.34) is the home for physical index pinning, topology co-allocation, and device sharing such as MIG and time-slicing. If those are needed, revisit through a DRA ResourceClaim rather than extending counts.
Non-GPU device classes. The surface allows them; the implementation lands with the first such device.
Snapshot and restore of live device state, such as a live CUDA context. Tracked separately by the cuda-checkpoint follow-up.
Problem
Follow-up to #502, which lands GPU passthrough at the worker level. A pool requests N GPUs and every actor container gets all of them. The
ActorTemplatecontainers have no say in the device layout, so device assignment is coupled to the worker.Per Benjamin Elder (@BenTheElder) (review), device assignment should move into the
ActorTemplateso it is decoupled from the worker and can control which containers in an actor receive the devices.Use cases
Actors are pod-shaped (multiple containers, one gVisor sandbox, shared netns), so per-container device control unlocks:
nvidia.com/gpu,amd.com/gpu, an FPGA); the logging, proxy, or metrics sidecar next to it claims none. Today every sidecar is handed the device nodes./dev/nvidia*, an SR-IOV VF), widening the attack surface that feat: CDI-based NVIDIA GPU passthrough into gVisor actor containers #502 otherwise works to keep narrow.Proposed API
Declare devices per-container using the standard Kubernetes
resourcesshape, the samecorev1.ResourceRequirementstype the pool already uses. The pool reserves capacity; each container claims from it.One new field on
Container:This reuses an existing type instead of inventing a
devicesselector, and:Scope
resourcestoActorTemplate.Container.nvidia.com/gpumust not exceed the pool reservation;nvidia.com/gpuis injectable today; the field type stays vendor-neutral and the gate lifts per class;sandboxClass == 'gvisor'guard to the container level.WorkerAssignmenttoateom.ateom, partition the pod's assigned GPUs across the containers that request them, the way the device plugin does in real Kubernetes, instead of the unconditional per-containermaybeInjectGPU. The partition must be deterministic, ordered by container.Risks
resources.limits.nvidia.com/gpuas the reservation and validate that the containers' sum does not exceed it, rather than deriving the pool total from containers. Smaller change, single scheduling knob.Out of scope
resource.k8s.io, GA in 1.34) is the home for physical index pinning, topology co-allocation, and device sharing such as MIG and time-slicing. If those are needed, revisit through a DRAResourceClaimrather than extending counts.cuda-checkpointfollow-up.References