Replacing All OSD Drives on a Rook Node
Problem
All OSD drives on one node of a Rook-Ceph cluster must be replaced, for example to swap them for larger 7.6T drives. Every OSD on the node has to be removed, the disks wiped or swapped, and new OSDs created by the Rook operator. Then the same steps are repeated on the next node.
Doing this in the wrong order can cause an abrupt degraded state, a full cluster with all I/O blocked, or disks that Rook will not reuse because of stale LVM metadata.
All ceph commands below run in the Rook toolbox pod
(kubectl -n rook-ceph exec -it deploy/rook-ceph-tools -- bash) or through
the kubectl rook-ceph ceph ... plugin. See
Management and Troubleshooting Tools.
To remove OSDs or a node permanently, without replacing the drives, see How to Remove OSDs from a Rook Ceph Cluster Safely.
Things to Check Before You Start
Capacity
Removing a whole node from a 4-node cluster removes 25% of the raw capacity
until the new OSDs are in. The remaining 3 nodes must absorb that node's data
without crossing the nearfull or full ratio. If an OSD reaches the full
ratio, all writes to the affected pools stop.
ceph df
ceph osd df tree
ceph osd dump | grep ratio
As a rough check, the raw space used on the whole cluster must fit within the
raw capacity of the remaining nodes, below the nearfull ratio (default 0.85),
with headroom for uneven OSD fill. If it does not fit, stop and add capacity
first.
Pool layout
The data can only move to the remaining nodes if CRUSH can still place every
replica or chunk there. With a host failure domain, check that:
- Replicated pools have
size≤ the number of remaining hosts. - Erasure-coded pools have
k+m≤ the number of remaining hosts. An EC 2+2 pool on 4 hosts cannot rebuild onto 3 hosts, and its PGs stayundersizeduntil the node returns.
ceph osd pool ls detail
ceph osd erasure-code-profile get <profile>
OSDs on the node
ceph osd tree
ceph osd ls-tree <hostname>
Procedure
Work on one node at a time. Do not start the next node until the cluster is
HEALTH_OK and all PGs are active+clean.
Phase 1: Preparation and Evacuation
-
Cordon the node. Rook does not create OSDs on unschedulable nodes, so this stops the operator from recreating OSDs on the old disks while you work.
kubectl cordon <node> -
Check that the OSDs can be stopped. Run this before scaling anything down. If the OSDs are already down, the check cannot tell you anything useful.
ceph osd ok-to-stop osd.<id1> osd.<id2> ... osd.<idN>If it returns an error, find out which PGs would become inactive and fix that first.
-
Mark the OSDs
out. Ceph starts moving data to the other nodes while the current drives are still up and serving I/O, so redundancy is kept the whole time.ceph osd out osd.<id1> osd.<id2> ... osd.<idN>Ceph can recover if the OSDs simply go down, but then the cluster runs degraded until recovery is done. Marking them
outfirst avoids that. -
Wait for the data to move. Watch until there are no
backfilling,backfill_waitorremappedPGs and all PGs areactive+clean.watch ceph -s
Phase 2: OSD Removal and Cleanup
-
Confirm that the OSDs no longer hold data that is needed:
ceph osd safe-to-destroy osd.<id1> osd.<id2> ... osd.<idN>Do not continue until it reports that all OSDs are safe to destroy.
-
Scale the Rook operator down, so it does not reconcile the OSD deployments while you remove them:
kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=0 -
Scale down each OSD deployment:
kubectl -n rook-ceph scale deployment rook-ceph-osd-<id> --replicas=0 -
Purge each OSD from the cluster. This removes it from the CRUSH map, deletes its auth key and removes it from the OSD map.
ceph osd purge <id> --yes-i-really-mean-it -
Delete each OSD deployment:
kubectl -n rook-ceph delete deployment rook-ceph-osd-<id> -
Wipe the disks and clear the LVM metadata. Run this on the node itself. Rook creates OSDs with
ceph-volumeon LVM, andsgdiskandwipefsalone leave the device-mapper entries behind. Rook will then not treat the disk as clean.# Remove Ceph device-mapper (LVM) mappings
dmsetup ls | grep ceph | awk '{print $1}' | xargs -r dmsetup remove
rm -rf /dev/ceph-* /dev/mapper/ceph--*
# Zap each disk
sgdisk --zap-all /dev/sdX
wipefs -a /dev/sdX
dd if=/dev/zero of=/dev/sdX bs=1M count=100 oflag=direct,dsync
partprobe /dev/sdX
# Verify that no LVM or Ceph partitions remain
lsblkThe
dmsetupcommand removes every Ceph mapping on the node. That is correct here only because every OSD on the node is being removed.If the old drives are physically removed and will not be reused, wiping is only needed to clear the device-mapper entries and to sanitize the drives. New raw drives need no wiping.
Phase 3: Hardware Replacement and Reintegration
-
Physically swap the drives for the new ones.
-
If the
CephClusterresource lists devices by name or path understorage.nodes, update it to match the new drives. -
Uncordon the node and start the operator again:
kubectl uncordon <node>
kubectl -n rook-ceph scale deployment rook-ceph-operator --replicas=1 -
Rook runs the
rook-ceph-osd-prepare-<node>job, finds the new raw drives, and creates the new OSDs. Check that they areupandinwith the expected CRUSH weight (about 6.98 for a 7.6T drive):kubectl -n rook-ceph get pods -l app=rook-ceph-osd-prepare
ceph osd treeIf no new OSDs appear, check the logs of the prepare pod for that node.
-
Wait for
active+cleanandHEALTH_OKbefore you move on to the next node.
Does Rook Handle This with Managed PDBs?
When disruptionManagement.managePodBudgets: true is set in the
CephCluster resource, Rook creates and manages PodDisruptionBudgets (PDBs)
for the OSDs. They do not make this procedure safe on their own, and Rook
does not set the flags this procedure needs.
What Rook does
- In normal operation Rook keeps a single
rook-ceph-osdPDB that allows one OSD to be unavailable. - When OSDs in one failure domain (for example, one host) go down, Rook treats that failure domain as draining. It replaces the default PDB with per-failure-domain PDBs that allow disruptions only in the draining failure domain and block evictions everywhere else. This stops a second node from being drained at the same time.
- Rook sets
noouton the draining failure domain (ceph osd set-group noout <host>) forosdMaintenanceTimeoutminutes (default 30). This is meant for short maintenance such as a reboot, so Ceph does not start moving data for a node that will come back. - When the OSDs are back and the PGs are
active+clean(orpgHealthCheckTimeoutruns out, if set), Rook restores the default PDB.
Why this does not cover a drive replacement
- PDBs only act on evictions, such as
kubectl drain.kubectl cordon,kubectl scale --replicas=0andkubectl delete deploymentdo not go through the eviction API, so no PDB stops them. - Rook never runs
ceph osd ok-to-stop,safe-to-destroy,outorpurgefor you. Rook does not remove OSDs unless you enableremoveOSDsIfOutAndSafeToRemove, and that only applies to OSDs that are alreadyout. - The
nooutflag works against a permanent removal. It is right for a reboot but wrong when the data should move off the node. In this procedure the OSDs are markedoutby hand before they go down, sonoouthas no effect on them. But if you scale OSDs down without marking themoutfirst,nooutkeeps theminand the cluster stays degraded for up to 30 minutes before any recovery starts. - Rook does not set
norebalance,nobackfillor similar flags, and does not turn the balancer off.
What to check
After Phase 2, check that Rook did not leave a noout flag on the host and
remove it if needed:
ceph health detail | grep -i noout
ceph osd unset-group noout <hostname>
Check the OSD PDBs. While the node is being worked on, it is expected to see
the per-host PDBs instead of the default rook-ceph-osd PDB. After the new
OSDs are active+clean, the default PDB should be back:
kubectl -n rook-ceph get pdb
If the per-host PDBs remain, other nodes cannot be drained. Check
ceph -s for PGs that are not active+clean, and check the operator log.