- Home
- Troubleshooting
- etcd membership control-plane add/remove issues
- 1. Stranded etcd member
1. Stranded etcd member#
Symptom. VerifyEtcdState reports the verdict hazard: EtcdMember CR missing
(VerdictHazardCRMissing) — etcd counts a member that no EtcdMember CR owns. The same section
applies when a clean host in scope of an add already has its peer address in the raw member list, and
when VerifyEtcdState (after a removal) reports a target still present in the raw member list.
What it means. etcd counts a member toward quorum that nothing owns: a replaced or reset host, a join that never finished, or a leave that did not complete. The quorum bar is raised by a member that can never vote.
This symptom covers two different situations with opposite repairs, and the phase does not tell them
apart — you have to. The two signals that would distinguish them are an empty etcd member name and
empty clientURLs. mkectl does fetch both — it reads etcd's own member/list API rather than
k0s etcd member-list — but its verdict logic keys only on "is there a raw member" and "is there a CR",
so the finding is identical in both situations. The k0s etcd member-list output you run by hand does
not carry clientURLs at all. Classify by hand, on the host that owns the peer address:
sudo ls <dataDir>/etcd/member/snap/db
| result | situation | repair |
|---|---|---|
| does not exist | the member was added to etcd but its etcd never started — nothing to lose | k0s etcd leave below is safe |
| exists | the host is a real member whose etcd has data; only its EtcdMember CR is missing (its k0s could not reach the kube-apiserver when it tried to register) |
do not k0s etcd leave — go to the recovery paragraph below instead |
If the host is unreachable or already gone (replaced, reimaged, wiped), it holds no data by definition and the first row applies.
Repair — first row only. From a healthy controller:
sudo k0s etcd leave --peer-address <peer-address>
sudo k0s etcd member-list --data-dir=<dataDir> # confirm the address is gone
This is destructive under the second row. k0s skips the join entirely when
<dataDir>/etcd/member/snap/dbexists, so removing the member of a host that still holds etcd data strands that host permanently — it will never rejoin, and its data is not recoverable through the normal flow. Re-check before running it, not after.
Repair — second row. The host is a live member; the missing CR is the only defect, and it is
self-healing. Restart k0s on that host once its kube-apiserver access is working
(sudo systemctl restart k0scontroller); EtcdMemberReconciler recreates the CR as soon as its local
etcd answers and the API is reachable. If the host is unrecoverable, treat it as a removal — take a
backup, then mkectl node remove --scope=controller+worker — rather than leaving it.
Then re-run the original mkectl node add / mkectl node remove. Both are idempotent.