Add GPU nodes
Syself Autopilot runs NVIDIA GPU workloads on Hetzner bare-metal servers. The driver and everything a GPU pod needs are already on the node, so you never SSH in to install anything.
GPU-capable server types
GPUs are bare metal only. Order a Hetzner bare-metal server from the GEX line, or an auction server with a supported card. See Hetzner's GPU server matrix for the available models. There is no Hetzner Cloud GPU type.
Syself Autopilot enables GPU support only for cards on its allowlist:
- GeForce GTX 1080 and GTX 1080 Ti
- RTX 4000 SFF Ada and RTX 6000 Ada
- RTX PRO 6000 Blackwell (all three variants)
Any other NVIDIA card, including older or unlisted models, is treated as a plain display adapter and gets no GPU support.
Add a dedicated GPU pool
Register the GPU servers as bare-metal hosts and attach them as their own pool, following Add bare-metal servers . Give the pool a role label so you can steer workloads onto it:
- class: workeramd64baremetal
name: md-gpu
replicas: 2
metadata:
labels:
node-role.kubernetes.io/gpu: ""
variables:
overrides:
- name: workerHostSelectorBareMetal
value:
matchLabels:
hardware: gpu
Label the GPU hosts with hardware: gpu on their HetznerBareMetalHost objects, so workerHostSelectorBareMetal selects only them. See Add bare-metal servers for host labels.
Verify the device plugin and capacity
A node is a GPU node when Syself Autopilot labels it autopilot.syself.com/gpu=true, which it does only for cards on the supported allowlist. The NVIDIA device plugin is a managed cluster component that deploys only on these labelled nodes; it is the component that tells Kubernetes a node has GPUs, advertising the nvidia.com/gpu resource that pods request. No label means no device plugin and no schedulable GPU.
Confirm the node is recognized as a GPU node:
$ kubectl get nodes -L autopilot.syself.com/gpu
Then confirm the GPU is schedulable. The device plugin exposes each GPU as the nvidia.com/gpu resource, under both Capacity and Allocatable:
$ kubectl describe node <gpu-node> | grep nvidia.com/gpu
Capacity:
nvidia.com/gpu: 4
Allocatable:
nvidia.com/gpu: 4
Each physical card exposes four slices through time-slicing, so Capacity: 4 on a single-GPU server means one card, not four. A slice is an allocation token, not a quarter of the card, and pods that share a card share its memory with no quota between them. See Share a GPU across pods for when co-scheduling is safe and how to keep a card to one workload.
Note
Allocatable: 0 means the device plugin is missing or unhealthy, not that the GPU is busy. See GPU not scheduling .
Important
A GPU node is not something you fix by hand; the sealed OS has no package manager. If a GPU node does not come up as GPU-capable and the logs do not explain it, reprovision the node. See GPU not scheduling .
Request a GPU from a workload
apiVersion: v1
kind: Pod
metadata:
name: gpu-test
spec:
restartPolicy: Never
nodeSelector:
node-role.kubernetes.io/gpu: ""
containers:
- name: cuda-container
image: nvcr.io/nvidia/k8s/cuda-sample:vectoradd-cuda12.5.0
resources:
limits:
nvidia.com/gpu: 1
The nodeSelector is not required for scheduling. The nvidia.com/gpu request alone already steers the pod to a GPU node, because non-GPU nodes advertise no such resource. Set the nodeSelector anyway when you want the pod pinned to your dedicated pool, rather than to any GPU node in the cluster.
A request for nvidia.com/gpu: 2 or higher is rejected. The device plugin runs with failRequestsGreaterThanOne, so one GPU per container is the limit.
Keep other pods off the GPU nodes
The nodeSelector pulls GPU workloads onto the pool, but a label only attracts pods; it does not push others away. Syself Autopilot manages node labels through Cluster API and does not support node taints, so reserve GPU hardware structurally: keep the GPU servers in their own pool, and give every other workload its own pool to select with a nodeSelector, so nothing lands on the GPU nodes by accident. See Label nodes and assign roles .