Skip to main content

Node taints

Syself Autopilot does not support durable node taints. A taint you set by hand does not survive, and there is no supported field to set one that sticks. Use labels and node affinity to control where pods run.

Why a taint does not stick

A taint on a Node repels pods: only a pod with a matching toleration (a pod-side field that says "I accept this taint") can schedule there. It is the inverse of a label, which attracts pods that opt in.

Syself Autopilot builds on Cluster API (CAPI), which creates and replaces nodes from templates, declarative blueprints describing everything a new node should be. The limitation sits in Cluster API itself: its templates carry labels but have no taint field, so a taint can never be part of the blueprint a node is rebuilt from. A node is replaced on a cluster upgrade, a health-check recovery, or a manual removal (see for what triggers each). Each new node starts clean, so a taint you add with kubectl taint is gone after the next replacement, and there is no supported way to make it persist.

Note

The missing taint field is being worked on upstream. Cluster API has an experimental proposal to propagate taints from the pool template to the node, so a taint would survive replacement. Syself is following that work closely and will support durable taints once the feature is tested and proven stable.

The control-plane taint is the one exception

Control-plane nodes carry node-role.kubernetes.io/control-plane:NoSchedule. Syself Autopilot sets it at registration, and it is built into the control-plane template, so it persists across every replacement. It comes from the platform, not from a setting you apply, which is why ordinary workloads never land on control-plane nodes. It is the only taint on the cluster, and you do not manage it.

Use labels and node affinity instead

Labels set in the Cluster manifest propagate to the Node object and survive replacement. Combine a label with a nodeSelector or node affinity on your pods, and you place pods exactly where you want, durably. See for the full rules, and for required-vs-preferred affinity.

Keeping other pods off a pool

Labels attract, they do not repel: a pod that sets no selector can still land on a labelled node. To reserve a pool, give it a role label, put a nodeSelector on the pods that belong there, and give every other workload its own pool to select, so nothing lands where it should not. For a boundary that does not depend on every pod being labelled correctly, a dedicated bare-metal pool is the hard separation; see .