The nomad-driver-ch is a task driver for HashiCorp Nomad that enables orchestration of Intel Cloud Hypervisor virtual machines. This driver provides a modern, lightweight alternative to traditional hypervisor solutions while maintaining full compatibility with Nomad's scheduling and resource management capabilities.
🏃♂️ Lightweight Virtualization: Leverages Intel Cloud Hypervisor for minimal overhead VM orchestration
🔧 Dynamic Resource Management: CPU, memory, and disk allocation with Nomad's resource constraints
🌐 Advanced Networking: Bridge networking with static IP support and dynamic configuration
☁️ Cloud-Init Integration: Automatic VM provisioning with user data, SSH keys, and custom scripts
💾 Flexible Storage: Virtio-fs shared filesystems and disk image management with thin provisioning
🎮 VFIO Device Passthrough: GPU, NIC, and PCI device passthrough with allowlist-based security
🔒 Security Isolation: Secure VM boundaries with configurable seccomp filtering
📊 Resource Monitoring: Real-time VM statistics and health monitoring
🔄 Lifecycle Management: Complete VM lifecycle with start, stop, restart, and recovery capabilities
⚠️ IMPORTANT: Cloud Hypervisor has no bootloader. You MUST always provide both kernel and initramfs parameters in your task configuration, even when using full disk images. The driver will fail if either is missing.
⚠️ glibc requirements: The dynamically-linked release of Cloud Hypervisor requires glibc ≥ 2.34. If you are running on older distributions (Debian 11, Ubuntu 20.04, etc.) use the static binaries shown above or run inside a container/VM that ships a newer glibc.
VirtioFS daemon:
# Install virtiofsd for filesystem sharing
sudo apt-get install virtiofsd # Ubuntu/Debian# or
sudo yum install virtiofsd # RHEL/CentOS
2. Configure Bridge Networking
# Create bridge interface
sudo ip link add br0 type bridge
sudo ip addr add 192.168.1.1/24 dev br0
sudo ip link set br0 up
# Configure bridge persistence (systemd-networkd)
cat > /etc/systemd/network/br0.netdev <<EOF[NetDev]Name=br0Kind=bridgeEOF
cat > /etc/systemd/network/br0.network <<EOF[Match]Name=br0[Network]IPForward=yesAddress=192.168.1.1/24EOF
sudo systemctl restart systemd-networkd
job"basic-vm" {
datacenters=["dc1"]
group"app" {
task"vm" {
driver="ch"config {
image="/var/lib/images/ubuntu-22.04.img"hostname="app-server"# REQUIRED: kernel and initramfs (Cloud Hypervisor has no bootloader)kernel="/boot/vmlinuz-5.15.0"initramfs="/boot/initramfs-5.15.0.img"cmdline="console=ttyS0 root=/dev/vda1"
}
resources {
cpu=2000# 2 CPU coresmemory=2048# 2GB RAM
}
# Optional: allow sandbox/CI environments without binaries# skip_binary_validation = true
}
}
}
🧪 Running in CI or locally without KVM: set skip_binary_validation = true in the plugin config (or use the SDK helper when embedding the driver) so tests can run without Cloud Hypervisor binaries present. Production deployments should keep validation enabled to surface misconfiguration early.
network_interface {
bridge {
name="br0"ports=["http", "https"] # Port forwarding works with DHCP!
}
}
DHCP Support: The driver automatically discovers DHCP-assigned IP addresses by parsing dnsmasq lease files. This enables automatic port forwarding for DHCP-based VMs. The driver generates deterministic MAC addresses from task IDs to ensure consistent IP assignment.
Requirements for DHCP:
dnsmasq DHCP server running on the host
Lease file accessible at /var/lib/misc/dnsmasq.leases
VM must receive DHCP lease within the normal timeframe
How it works:
Driver generates deterministic MAC address from task ID
VM boots and gets DHCP lease with that MAC
Driver parses dnsmasq lease file to find IP for that MAC
Port forwarding rules are set up automatically using the discovered IP
# 1. Verify image format
qemu-img info /path/to/image.img
# 2. Check image paths configuration
nomad agent-info | grep -A 10 virt
# 3. Validate kernel/initramfs paths
ls -la /boot/vmlinuz* /boot/initramfs*# 4. Test Cloud Hypervisor directly
cloud-hypervisor --kernel /boot/vmlinuz --disk path=/path/to/image.img
Network Connectivity Issues
Symptoms:
VM has no network access
Cannot reach VM from host
Solutions:
# 1. Check bridge configuration
ip link show br0
brctl show br0
# 2. Verify TAP interface creation
ip link show | grep tap
# 3. Test bridge connectivity
ping 192.168.1.1 # Gateway IP# 4. Check iptables rules
iptables -L -v -n
Nomad Client:
log_level="DEBUG"enable_debug=true
# Check Cloud Hypervisor processes
ps aux | grep cloud-hypervisor
# Inspect VM via ch-remote
ch-remote --api-socket /path/to/api.sock info
# Monitor VM console output
tail -f /opt/nomad/data/alloc/<alloc-id>/<task>/serial.log
Task Configuration Specification
Complete HCL task configuration reference:
config {
# Required: VM disk image pathimage="/path/to/vm-image.img"# Optional: VM hostnamehostname="my-vm-host"# Optional: Operating system variantos {
arch="x86_64"# CPU architecturemachine="q35"# Machine typevariant="ubuntu20.04"# OS variant
}
# Optional: Cloud-init user datauser_data="/path/to/user-data.yml"# File path# ORuser_data=<<EOF # Inline YAML#cloud-config
packages:- nginx
EOF
# Optional: Timezone configurationtimezone="America/New_York"# Optional: Custom commands to runcmds=[
"apt-get update",
"systemctl enable nginx"
]
# Optional: Default user configurationdefault_user_authorized_ssh_key="ssh-rsa AAAAB3..."default_user_password="secure-password"# Optional: Storage configurationuse_thin_copy=true# Enable thin provisioning# Optional: Cloud Hypervisor specifickernel="/boot/custom-kernel"# Custom kernel pathinitramfs="/boot/custom-initrd"# Custom initramfs pathcmdline="console=ttyS0 quiet"# Kernel command line# Optional: Network interface configurationnetwork_interface {
bridge {
name="br0"# Bridge name (required)ports=["web", "api"] # Port labels to exposestatic_ip="192.168.1.100"# Static IP addressgateway="192.168.1.1"# Custom gatewaynetmask="24"# Subnet mask (CIDR)dns=["8.8.8.8", "1.1.1.1"] # Custom DNS servers
}
}
# Optional: VFIO device passthrough (coming very soon!)# vfio_devices = ["10de:2204"] # PCI device IDs# Optional: USB device passthroughusb_devices=["046d:c52b"] # USB vendor:product IDs
}
# Clone repository
git clone https://github.com/ccheshirecat/nomad-driver-ch.git
cd nomad-driver-ch
# Install dependencies
go mod download
# Run tests
go test ./...
# Build binary
go build -o nomad-driver-ch .# Install plugin
sudo cp nomad-driver-ch /opt/nomad/plugins/
Unit Tests:
Integration Tests:
# Requires Cloud Hypervisor installation
sudo go test -v ./virt/... -run Integration
We welcome contributions! Please see our Contributing Guide for details.
Quick Contribution Checklist
Fork the repository
Create a feature branch (git checkout -b feature/amazing-feature)
Write tests for your changes
Ensure all tests pass (go test ./...)
Run linting (golangci-lint run)
Commit with clear messages
Push to your fork
Create a Pull Request
Code Style: Follow Go conventions and use gofmt
Testing: Maintain >80% test coverage
Documentation: Update docs for user-facing changes
Compatibility: Maintain backward compatibility
Security: Never commit secrets or credentials
This project is licensed under the Mozilla Public License 2.0 - see the LICENSE file for details.
HashiCorp Nomad team for the excellent orchestration platform