Quick start for testing Hyperlight on Kubernetes without cloud infrastructure.
- Docker - Container runtime
- KIND - Kubernetes IN Docker (v0.20+, includes containerd 1.7+ with CDI support)
- kubectl - Kubernetes CLI
- /dev/kvm - KVM enabled on host (required for Hyperlight)
Note: The setup script automatically enables CDI (Container Device Interface) in KIND's containerd. CDI allows the device plugin to inject
/dev/kvminto containers that requesthyperlight.dev/hypervisorresources.
# Using Go
go install sigs.k8s.io/kind@latest
# Or download binary
curl -Lo ./kind https://kind.sigs.k8s.io/docs/user/quick-start/#installation
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind# Check if KVM is available
ls -la /dev/kvmIf not for more details on how to verify that KVM is correctly installed and permissions are correct, follow the guide here.
# 1. Create KIND cluster with local registry
just local-up
# 2. Build the device plugin
just plugin-build
# 3. Push to local registry
just plugin-local-push
# 4. Deploy to KIND
just plugin-local-deploy
# 5. Verify
just status| Component | Description |
|---|---|
| KIND cluster | Single-node cluster named hyperlight |
| Local registry | localhost:5000 for images |
| Node labels | hyperlight.dev/enabled=true, hyperlight.dev/hypervisor=kvm |
| /dev/kvm mount | Host KVM device mounted into KIND node |
# Check device plugin is running
just status
# Deploy a test pod
kubectl apply -f deploy/manifests/examples/test-pod-kvm.yaml
# Check the test pod
kubectl logs hyperlight-test-kvmOnce the device plugin is running, you can deploy the example Hyperlight application:
# Build the example app
just app-build
# Push to local registry
just app-local-push
# Deploy to KIND
just app-local-deploy
# Check it's running
kubectl get pods -l app=hyperlight-hello
# View logs
kubectl logs -l app=hyperlight-hello -fThe example app demonstrates security best practices:
scratchbase image (empty filesystem, ~2.7MB total)- Static musl binary (no runtime dependencies)
- Non-root user (UID 65534/nobody)
- Read-only root filesystem
- All capabilities dropped
- Seccomp RuntimeDefault profile
just app-undeploy# Remove cluster and registry
just local-downThe KIND config mounts /dev/kvm from the host. Ensure:
- KVM module is loaded:
lsmod | grep kvm - You have permissions:
ls -la /dev/kvm - KIND node has the mount:
docker exec hyperlight-control-plane ls -la /dev/kvm
Check the local registry is running:
docker ps | grep kind-registry
curl http://localhost:5000/v2/_catalog# Check pod status
kubectl get pods -n hyperlight-system
# Check logs
just logsKIND uses a modified manifest at deploy/local/device-plugin.yaml that differs from the AKS manifest at deploy/manifests/device-plugin.yaml.
Key difference: Sets terminationMessagePath: /tmp/termination-log
Why? KIND runs the kubelet inside a Docker container. When we mount host /dev to the pod's /dev directory, kubelet cannot create /dev/termination-log (the default path) inside the container, causing pod startup to fail with:
Error: failed to create containerd task: ...
open .../rootfs/dev/termination-log: read-only file system
Moving the termination log to /tmp avoids this conflict while keeping the /dev mount for hypervisor auto-detection.
This is a KIND-specific workaround. Cloud providers like AKS run kubelet directly on the host, so they don't have this issue.
- KVM only - MSHV is assumed not to be available on local Linux hosts
- Single node - KIND creates a single-node cluster
- No autoscaling - Unlike AKS, KIND doesn't autoscale
Once you've validated locally, deploy to Azure: