containerd’s CDI device plugin is a surprisingly flexible way to get specialized hardware like GPUs into your containers, but it’s not just a simple toggle.

Let’s see it in action. Imagine you have a container that needs access to a specific NVIDIA GPU. Without CDI, you’d typically pass device IDs directly via the --gpus flag in Docker or a similar mechanism in other runtimes. CDI abstracts this.

First, you need to install the CDI specification and a CDI runtime plugin for your hardware. For NVIDIA GPUs, this usually means installing the nvidia-container-toolkit which includes an NVIDIA CDI plugin.

# Example: Installing nvidia-container-toolkit (commands will vary by OS/distro)
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit

Once installed, the NVIDIA plugin registers itself with containerd. You can see the available CDI devices by inspecting containerd’s configuration.

# Check containerd's CDI config directory
ls -l /etc/containerd/cri.conf.d/
# You should see files related to CDI, often managed by the hardware vendor's toolkit.

# Inspect the CDI device classes registered (example for NVIDIA)
crictl inspecti
# Look for entries like "nvidia.com/gpu"

Now, when you launch a container, you tell containerd to use a CDI device class. This is done via the containerd-shim configuration or through a higher-level orchestrator like Kubernetes. In Kubernetes, this translates to the devices.k8s.io/gpu resource.

Here’s a simplified Kubernetes Pod spec using CDI for GPU access:

apiVersion: v1
kind: Pod
metadata:
  name: gpu-test-pod
spec:
  containers:
  - name: gpu-container
    image: nvcr.io/nvidia/cuda:11.0-base-ubuntu20.04
    command: ["nvidia-smi"]
    resources:
      limits:
        # This is the Kubernetes representation that CDI translates
        nvidia.com/gpu: 1

When containerd receives this request, it consults its CDI configuration. It finds the nvidia.com/gpu device class and asks the NVIDIA CDI plugin to allocate and configure a GPU for the container. The plugin then uses its own mechanisms (like nvidia-container-runtime-hook) to set up the container’s environment, making the GPU visible and usable. This involves setting up device nodes, environment variables (like NVIDIA_VISIBLE_DEVICES), and potentially NVIDIA driver libraries within the container.

The core problem CDI solves is providing a standardized, vendor-agnostic interface for requesting specialized hardware. Instead of each runtime or orchestrator needing to know the nitty-gritty details of how to expose an NVIDIA GPU versus an AMD GPU versus a custom FPGA, they just ask for a device.nvidia.com/gpu or device.amd.com/gpu. The CDI plugin handles the rest.

The mental model is that CDI acts as a universal adapter. Your container runtime (containerd) talks to the CDI specification. The CDI specification then delegates the actual hardware provisioning to a vendor-specific CDI plugin. This plugin is the one that knows how to interact with the hardware driver and the container’s namespace.

Think of it this way: containerd doesn’t directly know how to configure an NVIDIA GPU. It knows how to talk to a CDI plugin. The NVIDIA CDI plugin knows how to talk to the NVIDIA driver and the container runtime hooks. Your Kubernetes node (or other orchestrator) tells containerd "I need one nvidia.com/gpu." Containd says "CDI plugin, can you give me one nvidia.com/gpu?" The plugin says "Sure, here’s how you configure the container for it."

The most surprising part for many is that the resources: limits: nvidia.com/gpu: 1 in Kubernetes isn’t a direct instruction to containerd itself to find a GPU. It’s a request that Kubernetes translates into a CDI device class name that containerd understands, which then gets passed to the vendor’s CDI plugin. The plugin is the one that actually maps that logical request to a physical device and configures the container’s execution environment.

The next hurdle is often managing multiple GPUs or different types of devices within a single container, which requires more advanced CDI configurations and potentially custom CDI plugins.

Want structured learning?

Take the full Containerd course →