How to Remove OSDs from a Rook Ceph Cluster Safely
Problem
One or more OSDs, or a whole OSD node, must be permanently removed from a Rook Ceph cluster.
Marking the OSDs out and deleting the Kubernetes worker is not enough on its
own. That skips the checks that make sure no data is lost, and it leaves
state behind in Ceph, in Rook and in Kubernetes:
- The cluster can be degraded, or lose data, if the node goes away before backfill is done.
- The node is still in the
CephClusterspec, so the operator keeps trying to reconcile it. - The empty host bucket stays in the CRUSH map.
- MON, MGR, MDS or RGW pods on the node only move after a timeout.
- A
nooutflag set by Rook, OSD prepare jobs and/var/lib/rookremain.
This article describes the full procedure.
All ceph commands below run in the Rook toolbox pod:
kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash
Before You Start
-
Check the cluster health. Do not start while PGs are not
active+clean:ceph status -
Find the OSDs to remove and the host they are on:
ceph osd tree
ceph osd ls-tree <hostname> -
Check capacity. The remaining OSDs must hold the removed OSDs' data and stay below the
nearfullratio (default 0.85). If an OSD reaches thefullratio, all writes to the affected pools stop.ceph df
ceph osd df tree
ceph osd dump | grep ratio -
If you are removing a whole node, check that CRUSH can still place all the data. With a
hostfailure domain, every replicated pool'ssizeand every erasure-coded pool'sk+mmust be no larger than the number of remaining hosts.ceph osd pool ls detail
Procedure
The steps are the same for one OSD, several OSDs or a whole node. Steps marked Node removal only apply only when the node itself is going away.
1. Stop Rook from Recreating the OSDs
Rook recreates an OSD on any disk it is allowed to use that still has OSD data on it. Before you remove anything, make sure Rook will not use the disks again:
-
If the
CephClusterresource lists the devices or the node understorage.nodes, remove those entries. -
If it uses
useAllNodes: trueoruseAllDevices: true, cordon the node so that Rook does not create OSDs on it:kubectl cordon <node>Wipe the disks (step 7) before you uncordon the node.
2. Check That the OSDs Can Be Stopped
Run this while the OSDs are still up:
ceph osd ok-to-stop osd.<id1> osd.<id2>
If it returns an error, fix that first.
3. Mark the OSDs Out and Wait for Backfill
Marking the OSDs out while they are still running moves their data to other
OSDs without the cluster ever becoming degraded.
ceph osd out osd.<id1> osd.<id2>
Wait until all PGs are active+clean:
watch ceph status
Then confirm that the OSDs no longer hold needed data:
ceph osd safe-to-destroy osd.<id1> osd.<id2>
Do not continue until all OSDs are reported as safe to destroy.
4. Stop the OSD Pods
purge-osd only removes OSDs that are down. Scale each OSD deployment to 0:
kubectl -n rook-ceph scale deployment rook-ceph-osd-<id> --replicas=0
Check that the OSDs show as down:
ceph osd tree down
5. Purge the OSDs
With the kubectl rook-ceph Krew plugin
The kubectl rook-ceph plugin
removes OSDs with one command. See
Management and Troubleshooting Tools
for how to install Krew. Then install the plugin:
kubectl krew install rook-ceph
Remove one OSD, or several OSDs as a comma-separated list:
kubectl rook-ceph rook purge-osd <id1>,<id2>
If Rook does not run in the rook-ceph namespace, add -n <cluster-ns> and
--operator-namespace <operator-ns>.
The plugin runs rook ceph osd remove inside the operator pod, so the operator
must be running. For each OSD it:
- Checks that the OSD is
down. It refuses to remove an OSD that isup. - Marks the OSD
out. - Runs
ceph osd safe-to-destroy. If the OSD is not safe to destroy yet, it retries every minute until it is. - Deletes the OSD deployment. For OSDs on PVCs, it also deletes the PVC and its prepare job.
- Runs
ceph osd purge. This removes the OSD from the CRUSH map and the OSD map and deletes its auth key. - Tries to remove the OSD's host from the CRUSH map. This only succeeds when the host has no OSDs left.
It does not change the CephCluster spec, wipe the disks, or remove the
Kubernetes node.
--force skips the safe-to-destroy check. Use it only for OSDs whose data
is already lost, for example a failed disk, and only if ceph status shows no
PGs that depend on them.
Without the plugin
Run these for each OSD:
ceph osd purge <id> --yes-i-really-mean-it
kubectl -n rook-ceph delete deployment rook-ceph-osd-<id>
Rook also ships the same procedure as a Kubernetes job
(deploy/examples/osd-purge.yaml in the Rook repository).
Check the result
ceph osd tree
kubectl -n rook-ceph get deployment -l app=rook-ceph-osd
The OSDs must not appear in either list.
6. Remove the Node (Node Removal Only)
-
Move the other Ceph daemons off the node. List what still runs there:
kubectl -n rook-ceph get pods -o wide --field-selector spec.nodeName=<node>Drain the node. Rook's OSD PodDisruptionBudgets allow one host at a time to be drained, so this works when no other host is being drained.
kubectl drain <node> --ignore-daemonsets --delete-emptydir-dataIf a MON ran on the node, wait for Rook to fail it over to another node and check that all MONs are in quorum:
ceph mon stat -
Remove the now-empty host bucket from the CRUSH map. If you used
purge-osd, it may already be gone. Check withceph osd tree.ceph osd crush rm <hostname>The command fails if the host still has OSDs. That is a useful last check.
-
Remove any
nooutflag that Rook set on the host while its OSDs were down:ceph health detail | grep -i noout
ceph osd unset-group noout <hostname> -
Delete the node from Kubernetes:
kubectl delete node <node>
7. Clean Up
-
Delete the leftover OSD prepare job:
kubectl -n rook-ceph delete job rook-ceph-osd-prepare-<node> -
If the disks or the node will be used again, wipe the disks and remove the LVM mappings on the node. Also remove
/var/lib/rook(or yourdataDirHostPath) if the whole node is leaving the cluster. See Replacing All OSD Drives on a Rook Node for the wipe commands. -
Check that the default OSD PodDisruptionBudget is back:
kubectl -n rook-ceph get pdbYou should see
rook-ceph-osd, not one PDB per host. -
Check the final state:
ceph status
ceph osd tree
Does Rook Do This Automatically?
Mostly no. Rook's managed PodDisruptionBudgets only block pod evictions. They
do not mark OSDs out, check safe-to-destroy or purge anything. When OSDs
go down, Rook sets noout on their host, which delays recovery. For details,
see
Does Rook Handle This with Managed PDBs?
The CephCluster setting removeOSDsIfOutAndSafeToRemove: true makes Rook
remove OSDs that are out and safe to destroy. It is off by default. Even when
it is on, you still mark the OSDs out yourself, and you still clean up the
node, CRUSH host and disks as described above.