You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
- 🏷️ **User-defined Node taints** - Declare taints in `spec.nodeTaints`; the controller applies them once the Node is Ready, tracks ownership, and reconciles drift
56
57
- 📊 **Multi-instance** - Horizontal scaling with consistent hashing
57
58
- 🔍 **Full observability** - Prometheus metrics and health checks
Copy file name to clipboardExpand all lines: docs/src/concepts/scheduled-machine.md
+60Lines changed: 60 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -119,6 +119,65 @@ Optional configuration applied to the created CAPI Machine.
119
119
| `nodeDrainTimeout` | `string` | No | `5m` | Timeout for draining the node before deletion. |
120
120
| `killSwitch` | `bool` | No | `false` | Operator-driven kill switch. Immediately remove machine if `true`; reset to `false` to return to scheduled service. |
121
121
| `killIfCommands` | `[]string` | No | `null` | Node-side process-match kill switch. When non-empty, the reclaim agent DaemonSet is installed on the backing node and watches `/proc` for any process whose `comm` or `cmdline` matches an entry. First match triggers `EmergencyRemove` + auto-disables the schedule. See [Emergency Reclaim](./emergency-reclaim.md). |
122
+
| `nodeTaints` | `[]NodeTaint` | No | `[]` | User-defined taints applied to the Kubernetes Node once it is Ready. The controller owns and reconciles only the taints it applied; admin-added taints on the same Node are left untouched. See [Node Taints](#node-taints) below. |
123
+
124
+
## Node Taints
125
+
126
+
`spec.nodeTaints`declares taints that must exist on the Kubernetes Node once
127
+
it joins the cluster and reports `Ready=True`. The controller patches them on
128
+
via server-side apply, tracks what it applied in `status.appliedNodeTaints`,
129
+
and reconciles drift on every Node change (event-driven via the Node watch —
130
+
no polling).
131
+
132
+
### Shape
133
+
134
+
```yaml
135
+
spec:
136
+
nodeTaints:
137
+
- key: workload
138
+
value: batch
139
+
effect: NoSchedule
140
+
- key: dedicated
141
+
value: ml
142
+
effect: NoExecute
143
+
```
144
+
145
+
| Field | Type | Required | Description |
146
+
|-------|------|----------|-------------|
147
+
| `key` | `string` | Yes | RFC-1123 qualified name. Max 253 chars total; name-part ≤ 63. Reserved prefixes (`5spot.finos.org/`, `kubernetes.io/`, `node.kubernetes.io/`, `node-role.kubernetes.io/`) are rejected at admission. |
148
+
| `value` | `string` | No | Optional value, ≤ 63 chars. Mutable — changing the value on an existing taint triggers an update, not an add/remove. |
149
+
| `effect` | `enum` | Yes | One of `NoSchedule`, `PreferNoSchedule`, `NoExecute`. Identity is the tuple `(key, effect)`. |
150
+
151
+
### Ownership model
152
+
153
+
Taint identity is `(key, effect)`; the `value` is mutable. The controller only
154
+
touches taints it previously applied (tracked in `status.appliedNodeTaints` and
155
+
recorded in the annotation `5spot.finos.org/applied-taints` on the Node).
156
+
157
+
- **Admin-added taint with the same `(key, effect)`**: surfaces as a
158
+
`TaintOwnershipConflict`condition. The controller refuses to overwrite.
159
+
- **Admin-added taint with a different `(key, effect)`**: ignored — left in
160
+
place on the Node across reconciles.
161
+
- **Spec shrinks (taint removed)**: the controller removes only taints it
162
+
previously applied. If the admin has mutated the value since we applied it,
163
+
the controller refuses to remove and surfaces a conflict.
164
+
165
+
### Status condition: `NodeTainted`
166
+
167
+
| status | reason | meaning |
168
+
|--------|--------|---------|
169
+
| `Unknown` | `NoNodeYet` | `status.nodeRef` is populated but the Node object is not yet materialised in the API server. |
170
+
| `False` | `NodeNotReady` | Node exists but `Ready != True`. Will re-reconcile on the Node watch event. |
171
+
| `False` | `PatchFailed` | k8s API returned an error on the last patch. Exponential backoff applies. |
172
+
| `False` | `TaintOwnershipConflict` | An admin taint collides with a declared `(key, effect)`. The controller refuses to overwrite until the spec changes. |
173
+
| `True` | `Applied` | All declared taints are present on the Node. |
174
+
175
+
### What it does not manage
176
+
177
+
- **Tolerations** — a Pod-side concern. Workloads must declare tolerations
178
+
themselves to schedule onto tainted Nodes.
179
+
- **Node labels** — separate feature with different conflict semantics.
180
+
- **Admin-added taints** — never removed or overwritten by the controller.
122
181
123
182
## Status Fields
124
183
@@ -135,6 +194,7 @@ The status subresource contains the current state:
135
194
| `infrastructureRef` | `ObjectReference` | Reference to created infrastructure resource |
136
195
| `nodeRef` | `NodeRef` | Reference to the Kubernetes Node (apiVersion, kind, name, uid) once provisioned |
| `appliedNodeTaints` | `[]NodeTaint` | Taints the controller has applied to the Node. Source of truth for ownership — only entries here are eligible for removal. See [Node Taints](#node-taints). |
138
198
| `lastScheduledTime` | `Time` | Last time machine was created |
139
199
| `nextActivation` | `Time` | Next scheduled activation time |
140
200
| `nextCleanup` | `Time` | Time when machine will be cleaned up |
0 commit comments