Skip to content

RAID Array Recovery - arkk NAS

This runbook combines the original recovery guide with the additional degraded-start steps discovered during recovery when the array appeared as inactive and members were marked as spares (S).

Array: /dev/md0 (RAID5, 5 disks, ~15TB usable)


Current Situation Template

Use this section to record real-time state during incidents.

  • Array status from cat /proc/mdstat
  • Failed disk device and serial number
  • Replacement disk device and serial number
  • Any observed I/O errors from dmesg

Pre-Recovery Checklist

  • [ ] Backup critical data if possible
  • [ ] Cold spare drive ready (same size or larger)
  • [ ] Record serial number of the replacement drive
  • [ ] Confirm maintenance window and power-off plan
  • [ ] Keep commands in a shell history log during recovery

Device Mapping Checklist (Fill Before Destructive Steps)

Do this once per recovery session and reuse the same values through Steps 5-9.

  1. Capture disk inventory by serial:
lsblk -o NAME,SERIAL,SIZE,MODEL,TYPE
sudo mdadm --detail /dev/md0
  1. Fill this table:
Purpose Example Your value Verified by serial?
New replacement disk (whole disk) /dev/sdf [ ]
New replacement partition /dev/sdf1 [ ]
Known-good member for partition clone /dev/sdb [ ]
Failed/removed slot number 3 [ ]
  1. Export variables to reduce typo risk:
export NEW_DISK=/dev/sdX
export NEW_PART=${NEW_DISK}1
export GOOD_DISK=/dev/sdY
  1. Sanity check before running write operations:
echo "NEW_DISK=$NEW_DISK NEW_PART=$NEW_PART GOOD_DISK=$GOOD_DISK"
lsblk -o NAME,SERIAL,SIZE,MODEL "$NEW_DISK" "$GOOD_DISK"

Only proceed when serial numbers match your worksheet.


Recovery Steps

Step 1: Verify Current State Before Shutdown

ssh arkk
cat /proc/mdstat
sudo mdadm --detail /dev/md0
lsblk -o NAME,SERIAL,SIZE,MODEL
sudo smartctl -i "$NEW_DISK" 2>/dev/null | grep "Serial Number" || true

Confirm data is currently accessible if possible:

ls -la /mnt/arkk

Step 2: Unmount and Stop Array

sudo umount /mnt/arkk || true
sudo mdadm --stop /dev/md0 || true
cat /proc/mdstat

Step 3: Power Down

sudo shutdown -h now

Step 4: Physical Disk Swap

  1. Disconnect power.
  2. Locate failed disk by serial number, not SATA port.
  3. Remove failed disk and install replacement.
  4. Reconnect and boot.

Step 5: Verify New Disk Detection

ssh arkk
lsblk -o NAME,SERIAL,SIZE,MODEL
sudo smartctl -H "$NEW_DISK"

If the replacement drive was previously used, old RAID metadata can exist. That is handled below.

Step 6: Start Array (Degraded) - Updated Procedure

If /proc/mdstat shows md0 : inactive ... (S), metadata is present but the array is not running yet.

Step 6a: Stop inactive assembly first

sudo mdadm --stop /dev/md0

Step 6b: Assemble degraded, read-only, and force-run

Use all candidate RAID member partitions for this host, excluding devices with no md superblock.

sudo mdadm --assemble --readonly --force --run /dev/md0 /dev/sd[a-f]1

Notes: - --force may be required when one member has stale Events. - If a replacement disk is currently marked spare, degraded read-only start can still succeed for recovery.

Step 6c: Validate array is truly active

cat /proc/mdstat
sudo mdadm --detail /dev/md0

Expected degraded recovery shape: - md0 : active (read-only) raid5 - [5/4] [UUU_U] or equivalent

Step 6d: Mount read-only for data extraction

sudo mkdir -p /mnt/arkk
sudo mount -o ro /dev/md0 /mnt/arkk

If mount fails, verify if filesystem is on a partitioned md node:

lsblk -f
sudo blkid /dev/md0 /dev/md0p1

Then mount /dev/md0p1 if required.

Step 6e: If assembly still fails

Check metadata consistency and event counters:

sudo mdadm --examine /dev/sd[a-z]1 | egrep -i "Array UUID|Raid Level|Raid Devices|Device Role|Events|State"

Check kernel logs for read/I/O failures:

dmesg -T | egrep -i "md0|I/O error|raid|sd[a-f]" | tail -n 100

Common causes: - Omitted required member in assemble command - Stale member rejected without --force - True disk I/O error on one of the remaining members

Step 7: Clean Replacement Drive Metadata (if needed)

cat /proc/mdstat
lsblk "$NEW_DISK"
sudo mdadm --examine "$NEW_PART" || true
sudo mdadm --zero-superblock "$NEW_PART" || true
sudo wipefs -a "$NEW_DISK"

Step 8: Partition Replacement Disk

Copy partition layout from a known-good member disk.

sudo sfdisk -d "$GOOD_DISK" | sudo sfdisk "$NEW_DISK"
lsblk "$NEW_DISK"

Step 9: Add New Disk to Array

sudo mdadm --manage /dev/md0 --add "$NEW_PART"
cat /proc/mdstat

Step 10: Monitor Rebuild

watch -n 5 cat /proc/mdstat
sudo mdadm --detail /dev/md0

Step 11: Verify Completion

cat /proc/mdstat
sudo mdadm --detail /dev/md0

Target state: - [5/5] [UUUUU] - State : clean

Step 12: Persist Assembly at Boot

sudo cp /etc/mdadm/mdadm.conf /etc/mdadm/mdadm.conf.backup

# Check if md0 is already defined to avoid duplicate ARRAY lines.
grep -E "^ARRAY /dev/md0" /etc/mdadm/mdadm.conf

# If md0 is not present, append scan output.
sudo mdadm --detail --scan | sudo tee -a /etc/mdadm/mdadm.conf

# If md0 is already present, replace that ARRAY line manually with fresh scan output.
# sudo mdadm --detail --scan
# sudo editor /etc/mdadm/mdadm.conf

sudo update-initramfs -u

When the array is degraded, prioritize extraction first.

  1. Keep the array read-only for the entire backup (assemble/mount ro).
  2. Mount the array read-only on arkk and export it to the backup host.
  3. Pull data to the backup host. Two transports are supported:
  4. NFS over a direct link (preferred here): mount the array on the backup host over a dedicated/bonded Ethernet link and rsync from the local mountpoint (no ssh overhead). This is how the 2026 incident backup runs.
  5. rsync over SSH: when no direct mount is available.
  6. Copy selectively — skip regenerable/redownloadable data and thin periodic training checkpoints, so only irreplaceable data consumes rescue capacity.
  7. Re-run the copy to catch partials (rsync skips already-complete files).
  8. Verify the copy, then rebuild parity (never rebuild before the backup is verified — a resilver runs with zero redundancy).

Selective-copy helper scripts in this repo (docs/machines/arkk/scripts/): - run_backup.sh — runs both passes in order with logging and preflight checks - rsync_selected_from_arkk.sh + targets.txt / excludes.txt — bulk selective copy - thin_checkpoints_from_arkk.sh + checkpoint_dirs.txt — thinned checkpoint ladder

For the incident-specific keep/drop plan and run procedure, see BACKUP_TRIAGE_2026.md.


Troubleshooting Quick Reference

New disk not detected

echo "- - -" | sudo tee /sys/class/scsi_host/host*/scan
dmesg -T | tail -n 100

mdadm add fails

sudo mdadm --examine "$NEW_PART"
sudo mdadm --zero-superblock "$NEW_PART"
sudo mdadm --manage /dev/md0 --add "$NEW_PART"

Array will not start

sudo mdadm --assemble --readonly --force --run /dev/md0 /dev/sd[a-f]1
sudo mdadm --examine /dev/sd[a-f]1 | grep -i Events

Reference

  • mdadm manual: man mdadm
  • SMART manual: man smartctl