Decommission a node — this REVOKES its transport access.
curl --request POST \ --url https://stratum.example.com/v1/admin/cluster/members/example/decommission \ --header 'Authorization: Bearer <token>' \ --header 'Content-Type: application/json' \ --data '{ "reason": "returned to vendor" }'. This is the revocation mechanism. The node-transport listener (cold migration, console relay, session relay) refuses a decommissioned node even though its certificate remains valid and cluster-signed, which is what closes the exposure of a removed node keeping a working credential for the remaining life of its leaf — up to a year, with no CRL and no OCSP.
The record is kept, not deleted: a refusal can then say who revoked the node, when, and why.
Refused (409) when it would break the cluster, because a wrong call here
partitions it: it will not leave fewer than two active members on a
multi-node cluster, since losing quorum is not a state you recover from by
waiting. A single-node install is exempt, or its only node could never be
retired. There is no “a node cannot decommission itself” guard: requests
arrive through the HA VIP, so which node serves a call is arbitrary, and a
guard keyed on it made the same request succeed or fail depending on routing.
Decommissioning the node you are talking to is allowed, and is undone by
readmit from any node.
A reason is required. An unexplained revocation is nearly useless six
months later, when the only record is a node id that stopped working.
What this does, and what it does not. Decommissioning changes the
member’s state to decommissioned, which (a) makes the node-transport
listener refuse it and (b) takes it out of the peer set (only joining and
active members are rendered into peer lists). Enforcement is the node
transport only: Postgres/Patroni, OpenBao and OVN authenticate on the same
leaf and do not consult membership. It does NOT remove the node from the
Postgres, OpenBao or OVN rafts. The cluster takes a node out of those rafts
automatically only for a FAILED JOIN (a join that did not finish); a
decommissioned member, and a dead or removed node, are not cleaned up
automatically. Remove a dead node’s raft membership separately (see the raft
recovery guide), and wipe or power off a node you retire. See.
Gates on cluster:DecommissionMember.
Authorizations
Section titled “Authorizations”Parameters
Section titled “Parameters”Path Parameters
Section titled “Path Parameters”Request Bodyrequired
Section titled “Request Bodyrequired”object
Why this node is being removed. Recorded and audited.
Example
returned to vendorResponses
Section titled “Responses”The node is decommissioned and will be refused at the transport.
A node’s cluster membership.
Membership is the cluster’s topology: every peer list a node renders
(Patroni, OpenBao and OVN raft peers, keepalived priorities, vmstorage
nodes, Alertmanager peers) is derived from the members in joining or
active, by a per-node reconciler, and every change bumps the membership
generation.
Membership also decides transport access: the node-transport listener refuses a peer that is not a member, even when its certificate is valid and cluster-signed. Decommissioning a node IS how you revoke it — there is no CRL.
Records are never deleted, only moved to decommissioned, so a refusal can
say who revoked the node, when, and why.
object
joining: admitted and installing (already in every peer list);
active; failed: a join that did not finish (out of every peer
list, taken back out of every raft it reached); removing;
decommissioned.
The node role.
The management address every peer list names.
Optional storage/overlay bindings, keyed by traffic class.
object
object
Declared labels; topology.rack is the rack.
object
The declared rack (labels["topology.rack"]).
Orders every peer list and the keepalived priorities (1 = the founder).
The membership generation this node reports it has rendered and applied (its own report). A member below the cluster’s generation is lagging.
The join step a failed member stopped in.
The last error line of that step.
When a failed member was taken back out of every raft it reached.
Why the node was decommissioned. Required when decommissioning.
Who decommissioned it — a user id, or stratum-installer for membership
the install declared.
Example
{ "nodeId": "n-msst0002", "state": "joining", "role": "hybrid", "mgmtIp": "192.0.2.12"}Bad request.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Authenticated but not authorized.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Resource not found.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}Conflicting state.
object
The findings of a rejected IAM policy document (custom and resource policies).
One finding of a rejected IAM policy document. A rejection lists every finding, so the author fixes the document in one round trip.
object
The finding, e.g. INVALID_DOCUMENT, UNKNOWN_ACTION, ACTION_NOT_APPLICABLE.
Index of the statement at fault; -1 for the document as a whole.
The offending action, where one is at fault (ACTION_NOT_APPLICABLE).
Field errors, for codes that carry them: each problem at its field
(see FieldError). Documented on the responses that set it, e.g.
approveNodeJoin’s INVALID_INPUT and JOIN_APPROVAL_REFUSED.
Absent otherwise.
One field’s problem, the stage-2 installer API’s shape.
field is the field’s path, message what is wrong with it.
object
The field’s path, e.g. links[0].interface, disks[1].confirm,
mgmt.address or role; empty for the whole request.
Structured facts about the refusal, for codes that carry them. The
shape is fixed per code and documented on the response that answers
it, e.g. IMAGE_POOL_MISMATCH (see ImagePoolMismatchDetails) and
IMAGE_IN_USE. Absent for codes that carry none.
object
Example
{ "issues": [ { "code": "ACTION_NOT_APPLICABLE", "action": "compute:CreateVpc" } ]}