Setting up USB Passthrough with Kubernetes
Sometimes, the only way to get a project working seamlessly is to give your workloads direct access to the hardware attached to your cluster nodes. In my case, I wanted to expose a USB Zigbee gateway, which I use with Home Assistant to connect with various sensors such as door and temperature sensors. The wrinkle is that my Home Assistant setup runs inside Kubernetes. This led me to explore a reliable and maintainable way to expose a specific USB device to a containerized workload.
If you are going down this path as well, let me walk you through the solution I used. Throughout this guide, you will see Terraform snippets provided for a more reproducible setup.
Introducing Akri: Exposing Devices to Kubernetes
The Akri project, which you can read more about at akri.sh, is exactly what I needed. Akri enables Kubernetes to discover and expose edge devices, such as USB peripherals and IP cameras, to pods. Even better, it ensures your workloads only schedule onto nodes where the matching devices actually exist, preventing frustrating deployment failures.
Installing Akri with Terraform
The Akri team maintains a Helm chart which is easy to deploy and configure. I highly recommend using Terraform for this, as infrastructure as code is not only best practice, it also keeps your intentions and configurations clear and version-controlled.
Here is an example Terraform configuration to install Akri with the udev discovery feature enabled, specifically targeting devices that use the cp210x
driver, which is what my Zigbee gateway uses:
resource "helm_release" "akri" {
name = "akri"
chart = "akri"
repository = "https://project-akri.github.io/akri/"
namespace = "akri"
create_namespace = true
atomic = true
# Enable udev discovery, required for USB devices
set {
name = "udev.discovery.enabled"
value = "true"
}
# Enable custom udev configuration
set {
name = "udev.configuration.enabled"
value = "true"
}
# Match devices using the cp210x driver
set {
name = "udev.configuration.discoveryDetails.udevRules[0]"
value = trimspace(<<-EOF
DRIVERS=="cp210x"
EOF
)
}
# Group multiple matching devices
set {
name = "udev.configuration.discoveryDetails.groupRecursive"
value = "true"
}
}
The key here is matching the right udev rule for your device. In my setup, the cp210x
driver is a perfect fit for the Zigbee coordinator. You may need to adjust this to match your situation.
Checking Device Discovery
Once Akri is installed, it will detect and create resources for discovered devices. You can list these with:
kubectl -n akri get instances.akri.sh
This will give output similar to:
NAME CONFIG SHARED NODES AGE
akri-udev-6b7706 akri-udev false ["homelab.srv.engineereverything.io"] 7d15h
Take note of the instance name. It will be unique to your device and setup.
If you wish to verify which device was found, view the details like this:
kubectl -n akri get instances.akri.sh akri-udev-6b7706 -o yaml
Look under the spec.brokerProperties
section. For my use case, seeing /dev/ttyUSB0
here told me Akri had found the USB Zigbee gateway correctly.
Making the Resource Available in Your Pod
Now comes the final step: requesting the device in your Home Assistant pod specification (or whatever workload needs USB access). Simply add the following block to your resources
section:
resources:
limits:
akri.sh/akri-udev-6b7706: "1"
requests:
akri.sh/akri-udev-6b7706: "1"
This requests the Akri discovered resource, ensuring your pod is scheduled on a node where the USB device is available.
After deploying, you should be able to verify the device is accessible inside your pod. For example, execute:
kubectl -n home-assistant exec -it home-assistant-0 -- ls -l /dev/ttyUSB0
I was delighted to see:
crw-rw---- 1 root dialout 188, 0 May 24 22:28 /dev/ttyUSB0
Wrapping Up
With Akri and some clear Kubernetes resource requests, you can cleanly expose USB devices, such as Zigbee gateways, to your containerized applications. This approach has made my Home Assistant deployment robust and reproducible, and I can now confidently add or replace devices without worrying about complex hostPath hacks or manual pod scheduling.
If you are managing hardware devices in your Kubernetes cluster, this workflow using Akri and Terraform makes things much more straightforward.