Custom node taints are not a reliable placement tool on Syself Autopilot, so the supported pattern is a dedicated pool with a label instead. You cannot set a taint on a worker pool (the platform does not allow it), and a taint added by hand with `kubectl taint` is lost the moment the node is replaced, which happens on every upgrade and maintenance. > [!WARNING] > A `kubectl taint` on a node is silently erased on the next node replacement, and replacements are routine, not rare. ## The built-in taints on the platform The platform forces a few taints by default: - The **control-plane `NoSchedule` taint** keeps your workloads off control-plane nodes. It is why your pods land only on workers. You would tolerate it only to run something on the control plane on purpose, which is rare and usually a mistake for tenant workloads. - A transient **`node.cloudprovider.kubernetes.io/uninitialized` taint** sits on a brand-new node for a few seconds while the platform wires it up, then clears itself. You tolerate these only when a platform component must run everywhere. A logging or metrics DaemonSet uses `tolerations: [{operator: Exists}]` to land on control planes too. Your workloads most often have no reason to use them. ## Reserve a node the supported way To hold a class of hardware such as a GPU, a bare-metal server, or a client's dedicated capacity for one workload, use a pool label instead of a taint: 1. Put the dedicated servers in their own [worker pool](/docs/hetzner/apalla/servers-and-nodes/pools/node-pools-overview) and set a label in the pool's `metadata`. A pool label persists across node replacement; a `kubectl` label does not. 2. Point the workload at that pool with a `nodeSelector` or [node affinity](/docs/hetzner/apalla/workloads/placement/affinity-and-anti-affinity) on the label. 3. Do not deploy anything else that selects the pool. You control what runs there. ```yaml # The dedicated workload targets the pool's label spec: nodeSelector: autopilot.syself.com/gpu: "true" ``` > [!NOTE] > A label reliably pulls the **wanted** pod onto the dedicated nodes and survives node replacement, but it cannot keep other pods off, which is something a taint would do. In practice this rarely matters: you control what you deploy, and scarce hardware is guarded by its own resource accounting (a GPU through [`nvidia.com/gpu`](/docs/hetzner/apalla/workloads/specialized/run-gpu-workloads), a secure-runtime pod through its [runtime class](/docs/hetzner/apalla/workloads/secure/run-in-the-secure-runtime)), so an unmarked pod that lands there only uses CPU and memory, never the GPU or secure runtime you had reserved for other workloads. For a hard, enforced guarantee that nothing else can schedule onto a set of nodes, contact Syself. For the servers-side view of why pool taints are not exposed, see [Apply taints](/docs/hetzner/apalla/servers-and-nodes/scheduling/apply-taints).