Skip to content

Attach an NPU to a KubeVirt VM

Attach one ATOM™ or Rebel100™ NPU to a KubeVirt VM and verify it with rbln-smi inside the guest.

Use the VM passthrough configuration and complete the KubeVirt setup. If the Operator is not installed, follow Installing the NPU Operator.

1. Create the VM

Select the NPU family to use.

export NPU_PRODUCT='RBLN-CR13'
export NPU_RESOURCE='rebellions.ai/RBLN-CR13_PF'
export NPU_PRODUCT='RBLN-CA25'
export NPU_RESOURCE='rebellions.ai/RBLN-CA25_PF'

Adapt the node and PVC names to your environment. Set <VM_PASSWORD> to the password for console login as ubuntu.

Complete the permitted device configuration, then request an NPU by setting hostDevices.deviceName to the selected $NPU_RESOURCE.

kubectl apply -f - <<EOF
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: npu-vm
  namespace: npu-tutorial
spec:
  runStrategy: Always
  template:
    metadata:
      labels:
        kubevirt.io/domain: npu-vm
    spec:
      nodeSelector:
        kubernetes.io/hostname: "<VM_NODE_NAME>"
      domain:
        cpu:
          cores: 4
        resources:
          requests:
            memory: 8Gi
        devices:
          disks:
          - name: rootdisk
            disk:
              bus: virtio
          - name: cloudinit
            disk:
              bus: virtio
          interfaces:
          - name: default
            masquerade: {}
          hostDevices:
          - name: npu
            deviceName: ${NPU_RESOURCE}
      networks:
      - name: default
        pod: {}
      volumes:
      - name: rootdisk
        persistentVolumeClaim:
          claimName: npu-vm-disk
      - name: cloudinit
        cloudInitNoCloud:
          userData: |
            #cloud-config
            users:
              - name: ubuntu
                sudo: ALL=(ALL) NOPASSWD:ALL
                shell: /bin/bash
                lock_passwd: false
                plain_text_passwd: "<VM_PASSWORD>"
            growpart:
              mode: auto
              devices: ["/"]
            resize_rootfs: true
EOF

Create a ResourceClaim requesting one NPU of the selected product through the vfio-npu.rebellions.ai DeviceClass. Reference the claim in the VM's resourceClaims and hostDevices.

kubectl apply -f - <<EOF
apiVersion: resource.k8s.io/v1
kind: ResourceClaim
metadata:
  name: vm-npu
  namespace: npu-tutorial
spec:
  devices:
    requests:
    - name: npu
      exactly:
        deviceClassName: vfio-npu.rebellions.ai
        count: 1
        selectors:
        - cel:
            expression: 'device.attributes["npu.rebellions.ai"].productName == "${NPU_PRODUCT}"'
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
  name: npu-vm
  namespace: npu-tutorial
spec:
  runStrategy: Always
  template:
    metadata:
      labels:
        kubevirt.io/domain: npu-vm
    spec:
      nodeSelector:
        kubernetes.io/hostname: "<VM_NODE_NAME>"
      resourceClaims:
      - name: npu-claim
        resourceClaimName: vm-npu
      domain:
        cpu:
          cores: 4
        resources:
          requests:
            memory: 8Gi
        devices:
          disks:
          - name: rootdisk
            disk:
              bus: virtio
          - name: cloudinit
            disk:
              bus: virtio
          interfaces:
          - name: default
            masquerade: {}
          hostDevices:
          - name: npu
            claimName: npu-claim
            requestName: npu
      networks:
      - name: default
        pod: {}
      volumes:
      - name: rootdisk
        persistentVolumeClaim:
          claimName: npu-vm-disk
      - name: cloudinit
        cloudInitNoCloud:
          userData: |
            #cloud-config
            users:
              - name: ubuntu
                sudo: ALL=(ALL) NOPASSWD:ALL
                shell: /bin/bash
                lock_passwd: false
                plain_text_passwd: "<VM_PASSWORD>"
            growpart:
              mode: auto
              devices: ["/"]
            resize_rootfs: true
EOF

Wait for the VM to become ready, then check its running state.

$ kubectl wait -n npu-tutorial --for=condition=Ready vm/npu-vm --timeout=300s
virtualmachine.kubevirt.io/npu-vm condition met

$ kubectl get vm -n npu-tutorial npu-vm \
  -o 'custom-columns=NAME:.metadata.name,STATUS:.status.printableStatus,READY:.status.ready'
NAME     STATUS    READY
npu-vm   Running   true

Verify NPU allocation for the selected method.

Confirm that the virt-launcher Pod's compute container requests one NPU.

$ kubectl get pods -n npu-tutorial -l kubevirt.io/domain=npu-vm \
  -o json | \
  jq --arg resource "$NPU_RESOURCE" '.items[].spec.containers[] | select(.name=="compute") | .resources.limits[$resource]'
"1"

Check the NPU allocated to the vm-npu claim. Pool and device names depend on your environment.

$ kubectl get resourceclaim -n npu-tutorial vm-npu -o json | \
  jq '.status.allocation.devices.results | map({driver, pool, device})'
[
  {
    "driver": "npu.rebellions.ai",
    "pool": "node-rebel100",
    "device": "vfio-0000-27-00-0"
  }
]
$ kubectl get resourceclaim -n npu-tutorial vm-npu -o json | \
  jq '.status.allocation.devices.results | map({driver, pool, device})'
[
  {
    "driver": "npu.rebellions.ai",
    "pool": "node-atom",
    "device": "vfio-0000-23-00-0"
  }
]

Once the VM is Running and one NPU is allocated through the selected method, check the device inside the guest.

2. Verify the device in the guest

Connect to the guest console with virtctl console from a terminal on the management host.

Management host
virtctl console -n npu-tutorial npu-vm

At the login prompt, sign in as ubuntu with the password set when creating the VM. Press Enter if the screen is blank.

The remaining steps assume that you have installed a supported kernel and the RBLN Driver for the selected NPU family inside the guest by following the driver installation guide.

Check the passed-through PCI device, driver version, and NPU inside the guest.

Guest VM
$ lspci -nn -d 1eff:
09:00.0 Processing accelerators [1200]: Device [1eff:2130] (rev 02)
Guest VM
$ cat /sys/module/rebellions/version
3.5.1

$ rbln-smi -L
NPU 0 : RBLN-CR13 (UUID: NPU-34428712-d887-840b-a7b9-1c9e05807fc3)
Guest VM
$ lspci -nn -d 1eff:
09:00.0 Processing accelerators [1200]: Device [1eff:1250] (rev 03)
Guest VM
$ cat /sys/module/rebellions/version
3.4.1

$ rbln-smi -L
NPU 0 : RBLN-CA25 (UUID: NPU-54101eb9-509c-8fe6-ab27-8dd7f67cb5a3)

The check passes when the guest reports the driver version and one NPU.

Clean up

Log out of the guest, then press Ctrl+] to exit the console. Delete the VM from a terminal on the management host.

Management host
1
2
3
kubectl delete vm -n npu-tutorial npu-vm
kubectl wait -n npu-tutorial --for=delete vmi/npu-vm --timeout=180s
kubectl get pods -n npu-tutorial -l kubevirt.io=virt-launcher

If you used DRA, also delete the claim that was attached to the VM.

kubectl delete resourceclaim -n npu-tutorial vm-npu