GPU Cluster Node — KAISER-LAPTOP (k3s agent)¶
This machine is a GPU worker node in a DIY two-GPU Kubernetes cluster. It runs
k3s as an agent inside WSL2 Ubuntu and joins a k3s server hosted on an
always-on Windows PC. A MacBook Pro is the client (kubectl / helm,
GitOps/CI). It runs no cluster workloads itself.
- Cluster runbook (all machines, full steps):
diy-cluster.md - Companion node: Windows PC — k3s server
Mac (client) Windows PC (server) THIS — laptop (agent)
kubectl + helm ──API──▶ WSL2 Ubuntu WSL2 Ubuntu
GitOps / CI k3s SERVER + GPU worker k3s AGENT + GPU worker
RTX 4070 Laptop, 8 GB
All Kubernetes nodes are Linux (WSL2 Ubuntu); the NVIDIA GPU is reached via WSL2 GPU passthrough. You never run Kubernetes on Windows directly.
Specs/state captured 2026-06-23. Re-run Appendix A after hardware/driver/OS changes.
1. Setup status — 2026-06-23¶
This node is live in the cluster. It joined as a k3s agent and advertises its GPU.
| Step | State |
|---|---|
| WSL2 + Ubuntu installed | Ubuntu, WSL version 2 |
| Windows NVIDIA driver + WSL GPU passthrough | nvidia-smi in WSL lists the RTX 4070 |
| NVIDIA Container Toolkit (in WSL) | v1.19.1 |
Mirrored networking (.wslconfig) |
verified, WSL hostname -I == host LAN IP |
| k3s agent, joined to the PC server | joined (k3s v1.35.5+k3s1, agent → https://192.168.18.2:6443) |
| NVIDIA runtime in k3s containerd | auto-detected by k3s (nvidia → /usr/bin/nvidia-container-runtime) |
NVIDIA device plugin (advertise nvidia.com/gpu) |
pod Running; registered nvidia.com/gpu with the kubelet |
Cluster node name: kaiser-laptop. See §5 for exactly
how it joined and how to verify or rejoin.
2. Hardware & OS specs¶
| Component | Detail |
|---|---|
| Make / model | Acer Predator PH16-71 (laptop) |
| Hostname | KAISER-LAPTOP |
| OS | Windows 11 Home, version 10.0.26200 (build 26200), 64-bit |
| CPU | Intel Core i7-13700HX (13th Gen): 16 cores / 24 threads, 2.1 GHz base |
| RAM | 16 GB (15.7 GiB usable) |
| Storage | Micron 3400 NVMe SSD, ~1 TB (954 GB) |
| Discrete GPU | NVIDIA GeForce RTX 4070 Laptop GPU |
| Integrated GPU | Intel UHD Graphics (iGPU; ignore for compute) |
GPU details (the part that matters)¶
| GPU property | Value |
|---|---|
| Device | NVIDIA GeForce RTX 4070 Laptop GPU |
| VRAM | 8 GB GDDR6 (8188 MiB reported by nvidia-smi) |
| Power cap | 55 W (laptop TGP-limited) |
| Driver version | 596.36 (Windows; provides the WSL CUDA stack) |
| CUDA driver capability | CUDA 13.2 (max version the driver supports) |
| Compute capability | 8.9 (Ada Lovelace, sm_89) |
| GPU UUID | GPU-12a01891-28e9-a7f2-df85-e3145dc0e261 |
| WDDM mode | Yes (consumer/laptop driver model) |
Cluster-planning caveats:
- 8 GB VRAM is the binding constraint for the whole cluster. Kubernetes sizes
by
nvidia.com/gpucount, not VRAM, so the model that lands on both nodes must fit 8 GB. Both cards are 8 GB here (this RTX 4070 Laptop and the PC's RTX 3060 Ti), so the nodes are evenly matched. Plan workloads around 8 GB (see §4). - 55 W TGP means sustained throughput is well below a desktop 4070. Expect thermal throttling on long runs; keep the laptop plugged in and on a hard surface.
- WDDM driver model (not TCC), normal for laptop NVIDIA GPUs. The desktop compositor always reserves a little VRAM. The GPU still passes through to WSL2 and to containers via the NVIDIA Container Toolkit.
3. Network state¶
| Setting | Value |
|---|---|
| Active interface | Wi-Fi: Killer Wi-Fi 6E AX1675i |
| Current IPv4 | 192.168.18.142 (Wi-Fi MAC 56-D5-10-EC-9C-FC); was .140 → .141, DHCP keeps reassigning |
Cluster node IP (k3s.io/internal-ip) |
192.168.18.142 |
| Subnet / gateway | 192.168.18.0/24, gateway 192.168.18.1 |
| Workgroup | WORKGROUP (not domain-joined) |
| Ethernet | Present but unplugged (self-assigned 169.254.x.x) |
| WSL2 networking | Mirrored: WSL shares the host IP 192.168.18.142 on the LAN |
Mirrored networking is the key enabler. By default WSL2 sits behind NAT and its
Linux IP isn't reachable from the LAN, which breaks multi-host k3s. The .wslconfig
on this machine sets networkingMode=mirrored, so the k3s agent in WSL is reachable
from the PC server and Mac at the host's LAN IP. Verified: hostname -I inside WSL
returns the same address Windows uses.
Give this node a stable IP. The address has now drifted .140 → .141 → .142
across reboots. That's harmless (the agent dials out to the server), but a static
lease removes the surprise. In the router (http://192.168.18.1) bind MAC
56-D5-10-EC-9C-FC to a fixed IP, or set a static IP in Windows. Wired Ethernet
to the same switch as the PC is worth it for a compute node: lower latency and far
steadier than shared Wi-Fi.
4. Model sizing constraint¶
The deployed vLLM model must fit the smaller of the two GPUs, which is this laptop's 8 GB. Good fits for 8 GB (weights + KV cache + overhead):
- 3B–4B at FP16 (~6–8 GB): comfortable, room for KV cache.
- 7B–8B quantized (AWQ / GPTQ INT4, ~5–6 GB weights): fits with usable KV cache.
- Avoid 7B+ at FP16 (~14 GB+); won't fit.
Start with Qwen/Qwen2.5-3B-Instruct (FP16) or a 7B-AWQ build, and set
--gpu-memory-utilization 0.90 --max-model-len 4096.
5. How this node joined¶
Joined 2026-06-23 with the PC server's LAN IP (192.168.18.2) and its node-token. In
this laptop's WSL2 Ubuntu (run as root to avoid an interactive sudo prompt):
curl -sfL https://get.k3s.io | K3S_URL=https://192.168.18.2:6443 \
K3S_TOKEN=<server-node-token> sh -
That was the only command needed on this node. Two things then happened on their own:
- k3s auto-detected the NVIDIA runtime. Because the NVIDIA Container Toolkit was
already installed, k3s wrote the
nvidiaruntime into its containerd config itself. The manualnvidia-ctk runtime configurestep older guides show was not required on k3sv1.35. - The device plugin came from the cluster. The
nvidia-device-pluginDaemonSet was already applied cluster-wide (from the PC), so it scheduled onto this node the moment it joined and registerednvidia.com/gpuwith the kubelet. Nothing tokubectl applyhere.
Verify from the Mac or PC (the agent has no kubeconfig of its own):
kubectl get nodes -o wide # kaiser-laptop should be Ready
kubectl get nodes -o custom-columns=NODE:.metadata.name,GPU:'.status.allocatable.nvidia\.com/gpu'
# kaiser-laptop should report nvidia.com/gpu: 1
Local health check on this node (WSL, as root):
systemctl is-active k3s-agent
journalctl -u k3s-agent -n 30 --no-pager
export CONTAINER_RUNTIME_ENDPOINT=unix:///run/k3s/containerd/containerd.sock
crictl ps | grep nvidia-device-plugin # should be Running
To leave/rejoin: /usr/local/bin/k3s-agent-uninstall.sh removes the agent cleanly;
re-run the join command above to re-add it. Full multi-machine procedure is in
diy-cluster.md.
Keep the node awake during runs. If the laptop sleeps, its node goes
NotReadyand pods reschedule. Plug in, set High Performance, and disable sleep (Admin PowerShell):powercfg /change standby-timeout-ac 0.
6. Optional — direct SSH access (admin convenience, not the cluster path)¶
The cluster control path is k3s over the LAN, not SSH. The Mac drives the
cluster with kubectl, not by shelling into this box. SSH is only worth setting up
if you want a remote terminal for housekeeping. If so (Admin PowerShell):
Add-WindowsCapability -Online -Name OpenSSH.Server~~~~0.0.1.0
Start-Service sshd; Set-Service -Name sshd -StartupType Automatic
nvidia-smi (ships with the driver, works in Windows and WSL) is the quick local
GPU check; in-cluster GPU metrics come from Prometheus scraping the workload, not
from SSH.
Appendix A — re-capturing specs¶
Refresh this doc after changes. On Windows (PowerShell):
Get-CimInstance Win32_ComputerSystem | Select Manufacturer,Model,TotalPhysicalMemory,Name,Workgroup
Get-CimInstance Win32_Processor | Select Name,NumberOfCores,NumberOfLogicalProcessors,MaxClockSpeed
Get-CimInstance Win32_OperatingSystem | Select Caption,Version,BuildNumber,OSArchitecture
nvidia-smi
Get-NetIPConfiguration | ? {$_.IPv4Address}
Get-NetAdapter | ? Status -eq 'Up' | Select Name,InterfaceDescription,LinkSpeed,MacAddress
Inside WSL2 Ubuntu (verifies passthrough + mirrored networking + cluster bits):