The DaemonSet manifests that make k3s nodes advertise GPUs as the nvidia.com/gpu resource (that is, tell the cluster how many GPUs they have). The server source ships two of them in scripts/serving/; apply only one. For the install steps, see Prepare k3s and GPUs.

The default manifest is the one from the open-source k8s-device-plugin project at v0.19.3 with a single runtimeClassName: nvidia line added. The blocks below are generated from the server repository's files (scripts/gen-device-plugin.ts). The original comments are left out; the tables below explain each part.

The two manifests

DefaultTime-sliced
Filescripts/serving/nvidia-device-plugin.ymlscripts/serving/nvidia-device-plugin-timeSlicing.yml
Slots advertised1 per GPUreplicas per GPU (8 by default)
ObjectsDaemonSetConfigMap, DaemonSet
WhenYou have several GPUs and giving each pod one GPU is enoughYou have one or two GPUs but need to run several training and serving workloads together

Both DaemonSets have the same name. The time-sliced manifest is the default one plus a ConfigMap and what it takes to read it: the CONFIG_FILE environment variable, a volume and a mount.

Default: nvidia-device-plugin.yml

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: nvidia-device-plugin-ds
    spec:
      runtimeClassName: nvidia
      tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      priorityClassName: "system-node-critical"
      containers:
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.19.3
        name: nvidia-device-plugin-ctr
        env:
          - name: FAIL_ON_INIT_ERROR
            value: "false"
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        volumeMounts:
        - name: device-plugin
          mountPath: /var/lib/kubelet/device-plugins
      volumes:
      - name: device-plugin
        hostPath:
          path: /var/lib/kubelet/device-plugins

Time-sliced: nvidia-device-plugin-timeSlicing.yml

apiVersion: v1
kind: ConfigMap
metadata:
  name: nvidia-device-plugin-config
  namespace: kube-system
data:
  config.yaml: |-
    version: v1
    flags:
      migStrategy: none
    sharing:
      timeSlicing:
        renameByDefault: false
        failRequestsGreaterThanOne: true
        resources:
        - name: nvidia.com/gpu
          replicas: 8
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: nvidia-device-plugin-daemonset
  namespace: kube-system
spec:
  selector:
    matchLabels:
      name: nvidia-device-plugin-ds
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      labels:
        name: nvidia-device-plugin-ds
    spec:
      runtimeClassName: nvidia
      tolerations:
      - key: nvidia.com/gpu
        operator: Exists
        effect: NoSchedule
      priorityClassName: "system-node-critical"
      containers:
      - image: nvcr.io/nvidia/k8s-device-plugin:v0.19.3
        name: nvidia-device-plugin-ctr
        env:
          - name: FAIL_ON_INIT_ERROR
            value: "false"
          - name: CONFIG_FILE
            value: /etc/nvidia-device-plugin/config.yaml
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
        volumeMounts:
        - name: device-plugin
          mountPath: /var/lib/kubelet/device-plugins
        - name: plugin-config
          mountPath: /etc/nvidia-device-plugin
          readOnly: true
      volumes:
      - name: device-plugin
        hostPath:
          path: /var/lib/kubelet/device-plugins
      - name: plugin-config
        configMap:
          name: nvidia-device-plugin-config

DaemonSet fields

FieldValueMeaning
Namenvidia-device-plugin-daemonset (namespace kube-system)The app's GPU slots (GPU 슬롯) screen looks up the plugin by this name. If you installed it under a different name or namespace, set GEO_MLOPS_KUBERNETES_DEVICE_PLUGIN_NAME and GEO_MLOPS_KUBERNETES_DEVICE_PLUGIN_NAMESPACE
runtimeClassNamenvidiaThe line added to the original manifest. The default k3s runtime is not nvidia, so without this line the plugin cannot see the GPU and reports zero
tolerationsnvidia.com/gpu, NoScheduleLets the plugin run on GPU nodes that carry a taint of the same name
priorityClassNamesystem-node-criticalTreats the plugin as an essential node component, so it is scheduled ahead of other pods even when the node is short on resources
Imagenvcr.io/nvidia/k8s-device-plugin:v0.19.3Needs v0.18.2 or later. Unified-memory GPUs answer the GPU memory query with Not Supported; earlier versions treat that as fatal and advertise no GPUs at all
FAIL_ON_INIT_ERRORfalseOn an initialization error (no GPU found and so on), the container waits instead of exiting, so it does not restart in a loop
securityContextNo privilege escalation, all capabilities droppedKeeps the container's privileges to a minimum
device-plugin volume/var/lib/kubelet/device-plugins on the hostThe socket directory used to talk to the kubelet
CONFIG_FILE (time-sliced only)/etc/nvidia-device-plugin/config.yamlPath of the time-slicing config. Without this variable the ConfigMap is mounted but ignored
plugin-config volume (time-sliced only)ConfigMap nvidia-device-plugin-configMounted read-only at /etc/nvidia-device-plugin. The app's GPU slots (GPU 슬롯) screen also finds the ConfigMap the DaemonSet mounts and shows its time-slicing settings

Time-slicing settings

The keys in config.yaml of the ConfigMap nvidia-device-plugin-config.

KeyValueMeaning
versionv1Config file format version
migStrategynoneMIG (hardware GPU partitioning) is not used. Works with time-slicing alone on GPUs that do not support MIG
renameByDefaultfalseKeeps the resource name nvidia.com/gpu. With true it becomes nvidia.com/gpu.shared, and you must change the resource name that training and serving request (GEO_MLOPS_SERVING_GPU_RESOURCE, default nvidia.com/gpu) to match
failRequestsGreaterThanOnetrueA pod that requests two or more slots is rejected immediately. Two slots are not two GPUs; if allowed, the pod would really run on a single GPU
name under resourcesnvidia.com/gpuThe resource to time-slice
replicas under resources8How many slots to advertise per GPU. It is only an advertised number, so spare slots cost nothing. Set it comfortably above the number of pods you run at once

There is a single config file, pointed to directly by CONFIG_FILE. Different settings per node would need the plugin's config-manager sidecar, which this manifest does not include.

Applying and changing

Apply one manifest, then check the slots advertised per node. With time-slicing, that is the number of GPUs × replicas.

sudo k3s kubectl apply -f /opt/geo-mlops/scripts/serving/nvidia-device-plugin-timeSlicing.yml
sudo k3s kubectl get nodes -o custom-columns='NAME:.metadata.name,ALLOC:.status.allocatable.nvidia\.com/gpu'
  • Switching to the other manifest: apply that file. The DaemonSet name is the same, so the existing DaemonSet is updated and the plugin pods restart.

  • Switching from time-sliced to default: the ConfigMap nvidia-device-plugin-config stays behind. Nothing uses it, so you can delete it with sudo k3s kubectl -n kube-system delete configmap nvidia-device-plugin-config.

  • Changing only replicas: only the ConfigMap changes and the DaemonSet does not, so the plugin does not restart. Roll it out after applying.

    sudo k3s kubectl apply -f /opt/geo-mlops/scripts/serving/nvidia-device-plugin-timeSlicing.yml
    sudo k3s kubectl -n kube-system rollout restart ds/nvidia-device-plugin-daemonset
  • Air-gapped networks: import the image nvcr.io/nvidia/k8s-device-plugin:v0.19.3 into k3s beforehand (Air-gapped installation).

Written for the platform as of 2026-10-02.

© MLOps Central Platform