Skip to main content
RunBook Academy

← All break/fix scenarios in Backup & DR

intermediatebdr-snapshot~45 min

Fourteen days of hourly snapshots vanished with the array

Reported symptoms

  • At 02:14 an enclosure fault takes the primary array offline, and by 06:40 the vendor confirms the pool cannot be reconstructed
  • Nine production systems live on that array and all nine appear in the protection inventory as covered by hourly array snapshots retained for fourteen days
  • The recovery call opens on the assumption that 336 hourly recovery points are available to choose from
  • Forty minutes in, somebody asks which device the snapshots are stored on and nobody can name one that is not the failed array
  • The protection inventory has shown a green status for all nine systems for eleven consecutive months and has never been disputed
  • The only copy of any of the nine systems that survives is a monthly export of two of them, taken eleven days earlier for an audit and written to a separate host
  • The business had been told in writing that recovery to any hour within the last fourteen days was available on request

Evidence

  • · The storage configuration lists every hourly recovery point as a child dataset of the single pool that failed, so the pool inventory and the recovery-point inventory are the same list
  • · The protection inventory has columns for system, tier, protection method, schedule, retention and status, and no column for where the resulting copy is written
  • · The recovery objectives circulated to the business quote fourteen days at hourly granularity and name no failure model, so the sentence is true of an accidental deletion and false of a lost array
  • · The scheduler holds no job that writes any of the nine systems to a destination outside the array: no replication target, no repository, no export other than the monthly audit extract for two systems
  • · The array event log for the six hours before the fault shows hourly snapshot creations succeeding and retention expiries removing the oldest snapshot on schedule, with no ad-hoc destroy issued by any operator account
  • · The last two log entries before the array stopped responding are an enclosure communication failure and a pool suspension, ten seconds apart
  • · The executed LVM capture reproduces the same arrangement on a disposable device and shows that destroying the single physical volume removes origin and snapshot together
  • · The executed ZFS capture shows the same snapshot mechanism surviving the identical event when the snapshot has been replicated to a pool on a different device
Diagnosis and resolutionclick to reveal

Root cause

Two defects, and only the second one is fixable by buying something. **The immediate cause: a snapshot is an allocation inside the storage it protects.** Every snapshot technology in this estate records the blocks a dataset used at a point in time. Those blocks live in the same pool as the live data, are addressed by the same metadata, and are reachable only through the same storage stack. That is what makes a snapshot cheap and fast, and it is also what makes it worthless against loss of the pool. Fourteen days of hourly snapshots were fourteen days of references into a pool that no longer existed. **The control that should have caught it: the inventory was keyed on tool.** The protection inventory asked one question of each system, "what protects this?", and accepted a tool name as the answer. "Array snapshot, hourly, 14 days" is a complete answer to that question, so every row was legitimately green. The question the inventory never asked was "what does this survive?", and a system whose only copy lives on the array it runs from cannot be represented as a gap in a table with no column for the destination. The control was not bypassed or ignored. It was answering a question whose answer could not be wrong. The recovery objectives circulated to the business inherited that defect. A retention and a granularity with no failure model attached describes protection against deletion, corruption by an application, and a bad change, and describes nothing at all about hardware loss. Nobody who read it was misled about the number fourteen. They were misled about what it was fourteen days of.

Remediation

There is no restore in this incident, which is the point of it. The nine systems were rebuilt from configuration management and from whatever application-level exports existed; two of them recovered to an eleven-day-old audit extract and seven to their build state. Record the actual recovery point per system before anything else, because that number is the evidence the estate change is argued from. The structural remediation is to give every recovery point a second failure domain. The snapshot mechanism does not change; it gains a copy on independent storage: ```bash set -u SRC=rbdr-prod/ledger DST=rbdrbkp/ledger STAMP=$(date -u +%Y%m%dT%H%M%SZ) zfs snapshot "$SRC@rbdr-$STAMP" zfs send -i "@$(zfs list -H -o name -t snapshot -s creation "$SRC" | tail -2 | head -1 | cut -d@ -f2)" \ "$SRC@rbdr-$STAMP" | zfs receive "$DST" ``` The equivalent for an LVM origin is to mount the snapshot read-only and copy its contents into a repository on another machine, then remove the snapshot; the snapshot is the consistent view, not the copy. Then repair the inventory itself, which is the defect that will otherwise recreate this state on the replacement array. Add a destination column, a failure-domain column, and a last-proven-restore column, and make a row green only when the destination is not the protected storage.

Verification

Verification is a question asked of each system, not a job status: name the device the recovery point is stored on, and confirm it is not the device being protected. If the two names match, the row is a gap regardless of what its status column says. Concretely, for every Tier 1 system: - `zfs list -H -o name -t snapshot` on the backup pool returns the expected recovery points, and `zpool status` shows that pool on different physical devices from production. - A restore is performed from the off-array copy into isolated infrastructure and the restored data is compared by checksum against a value recorded before the restore, not against the source at restore time. - The recovery objectives document names a failure model for each stated number, and the fourteen-day figure is qualified by which failures it applies to. - A tabletop of the exact incident is run against the new inventory: mark the production array as destroyed and confirm that every Tier 1 row still names a readable device.

Prevention

**Apply the snapshot test to every row.** Take the storage the data lives on, assume it is gone, and ask what is still readable. A snapshot is not a backup until it has been copied somewhere with an independent failure domain; until then it is a second name for the same blocks. **Key the inventory on the failure model, not on the tool.** A protection inventory whose columns are tool, schedule and retention cannot express this defect, because every field is correctly filled in. Columns for destination, failure domain and last proven restore turn a green row into a falsifiable claim. **Never state a retention without a failure model.** "Fourteen days" is not a recovery capability. "Fourteen days of hourly recovery points against accidental deletion and application corruption, and forty-eight hours against loss of the array" is one, and it is the sentence the business needed in order to fund the second copy. **Alert on the replication, not on the snapshot.** A snapshot schedule that runs perfectly is not evidence of anything except that the array is healthy. The signal worth paging on is the age of the newest copy on the independent device. **Count recovery points per failure domain, not per estate.** Nine systems with 336 snapshots each on one array is one recovery point against hardware loss, and the arithmetic should be presented that way in every review.

Reported symptoms

At 02:14 an enclosure fault takes the primary array offline. It does not come back. At 06:40 the vendor confirms the pool cannot be reconstructed.

Nine production systems lived on that array. All nine appear in the protection inventory with the same entry: array snapshot, hourly, fourteen days retained, status OK. The status has been OK for eleven consecutive months.

The recovery call opens on the arithmetic that follows from that: fourteen days at hourly granularity is 336 recovery points per system, and the only decision is which hour to return to.

Forty minutes in, somebody asks which device those snapshots are stored on. Nobody can name one that is not the failed array.

Evidence provided

The storage configuration, first. Every recovery point in the estate is a child of the pool that failed.

Read-only / Safethe pool inventory and the recovery-point inventory are one list
$ zfs list -r -t all -o name,used,refer rbdr-prod
NAME                              USED  REFER
rbdr-prod                        7.41T   205K
rbdr-prod/vm-ledger              1.92T  1.44T
rbdr-prod/vm-ledger@hourly-0100  6.11G  1.44T
rbdr-prod/vm-ledger@hourly-0200  5.87G  1.44T
rbdr-prod/vm-billing             2.30T  1.71T
rbdr-prod/vm-billing@hourly-0100 9.02G  1.71T
rbdr-prod/vm-billing@hourly-0200 8.44G  1.71T

Illustrative output

Second, the control that reported this as protected.

Read-only / Safesix columns, none of which is the destination
$ column -t -s, rbdr-protection-inventory.csv
system        tier  protection_method  schedule  retention  status
rbdr-ledger   1     array snapshot     hourly    14 days    OK
rbdr-billing  1     array snapshot     hourly    14 days    OK
rbdr-idm      1     array snapshot     hourly    14 days    OK
rbdr-reports  3     array snapshot     hourly    14 days    OK

Illustrative output

Third, what the business was told, quoted from the recovery objectives circulated at the last service review:

Recovery points are retained for fourteen days at hourly granularity for
all Tier 1 systems. Recovery to any hour within that window is available
on request.

Fourth, the scheduler. There is no job writing any of the nine systems to a destination outside the array. The only export that leaves it is a monthly audit extract covering two systems.

Fifth, the array event log for the hours before the fault.

Read-only / Safescheduled expiries only, then the enclosure
$ grep -E 'snapshot|enclosure|pool' rbdr-array-events.log | tail -6
2026-08-15T01:00:03Z INFO  snapshot create rbdr-prod/vm-ledger@hourly-0100 ok
2026-08-15T01:00:04Z INFO  snapshot destroy rbdr-prod/vm-ledger@hourly-0100-14d retention ok
2026-08-15T02:00:03Z INFO  snapshot create rbdr-prod/vm-ledger@hourly-0200 ok
2026-08-15T02:00:04Z INFO  snapshot destroy rbdr-prod/vm-ledger@hourly-0200-14d retention ok
2026-08-15T02:14:01Z ERROR enclosure 0 lost communication with both controllers
2026-08-15T02:14:11Z ERROR pool rbdr-prod suspended: no healthy paths

Illustrative output

Sixth, the executed capture of the same arrangement on a disposable device.

Data-loss riskone physical volume held both, so one device took both
$ pvs; vgs; lvs
Both origin and snapshot are extents in ONE volume group on ONE PV.
pvs before:
PV         VG     PSize   
/dev/loop5 rbdrvg 1020.00m

Simulating permanent loss of the underlying device:
re-attached the same (now destroyed) backing store as /dev/loop5

--- what survived? ---
vgs:
lvs:

Work the evidence before reading on

  1. The inventory was accurate in every field it contained. What question was it answering, and what question did the incident ask?
  2. The event log shows snapshot destroy lines. Do they support or eliminate the theory that an operator removed the snapshots?
  3. The objectives document says fourteen days. Fourteen days of protection against what?
  4. If the estate had held 336 recovery points per system for eleven months, how many did it hold against the failure that actually occurred?

Root cause

The snapshots were allocations inside the storage they protected

A snapshot records the blocks a dataset occupied at a point in time. Those blocks stay in the pool that holds the live data, are addressed by the same metadata, and are reachable only through the same storage stack. That is what makes a snapshot near-instant and near-free at the moment it is taken, and it is the same property that removes it when the pool goes.

The executed LVM capture above is the estate in miniature: origin and snapshot were extents in one volume group on one physical volume, and after the backing device was destroyed both vgs and lvs printed nothing at all. Not a corrupted snapshot, not a partial one. No rows.

The inventory was keyed on tool rather than on failure model

The protection inventory asked each system one question — what protects this? — and accepted a tool name as the answer. “Array snapshot, hourly, 14 days” is a complete and correct answer to that question, so all nine rows were legitimately green and stayed green through eleven monthly reviews.

The question it never asked was what the system survives. With no column for where the copy lands, a system whose only copy lives on the array it runs from is unrepresentable as a gap. The control was not bypassed or overridden; it was answering a question whose answer could not come out wrong.

The recovery objectives inherited the defect. A retention and a granularity with no failure model attached describes protection against an accidental deletion or an application corrupting its own data, and describes nothing about hardware loss. Nobody was misled about the number. They were misled about what it counted.

Resolution

There is no restore in this incident, and that is the finding rather than a gap in the write-up. Two systems recovered to an eleven-day-old audit extract; seven were rebuilt from configuration management to their build state with no application data. Record the recovery point actually reached per system before anything else — that measurement is what the estate change is argued from.

The structural fix is not a different snapshot technology. It is a second failure domain for the same snapshots, and the ZFS capture shows the difference the copy makes under the identical event.

Data-loss riskproduction gone, the replicated points still readable
$ zpool import; zfs list -r -t all rbdrbkp
--- zpool import (can ZFS find anything to import?) ---
no pools available to import

--- can the 09:00 snapshot be reached? ---
cannot open 'rbdrprod': dataset does not exist

--- what the INDEPENDENT backup pool still holds ---
NAME                  USED  REFER
rbdrbkp               100M    24K
rbdrbkp/ledger        100M  50.1M
rbdrbkp/ledger@0900  50.0M  50.1M
rbdrbkp/ledger@0930     0B  50.1M

The snapshot mechanism in that capture is the same one the array used. What differs is that zfs send had already written the points to a pool on a different device, so losing production left them readable.

Then repair the inventory, which is the defect that would otherwise recreate this state on the replacement array: add destination, failure domain and last-proven-restore columns, and let a row be green only when the destination is not the storage being protected.

Verification

Ask each system a question rather than reading a status: name the device the recovery point is stored on, and confirm it is not the device being protected. Matching names mean the row is a gap whatever its status column says.

For every Tier 1 system, zfs list -H -o name -t snapshot against the backup pool returns the expected points, and zpool status shows that pool on different physical devices from production. A restore is then performed from the off-array copy into isolated infrastructure and compared by checksum against a value recorded beforehand, never against the source at restore time.

The revised objectives document names a failure model beside every number, and the fourteen-day figure states which failures it applies to.

Finally, run this incident as a tabletop against the new inventory: mark the production array destroyed and confirm every Tier 1 row still names a readable device. Nine rows that named the array before should now name something else.

Prevention

Apply the snapshot test to every row. Assume the storage the data lives on is gone, then ask what is still readable. A snapshot is not a backup until it has been copied somewhere with an independent failure domain.

Key the inventory on the failure model. Tool, schedule and retention were all correct here. Destination, failure domain and last proven restore are the columns that could have been wrong, which is why they are the ones worth having.

Never publish a retention without a failure model. Fourteen days is not a recovery capability; fourteen days against deletion and corruption, plus a stated figure against loss of the array, is one.

Alert on the age of the off-array copy, not on the snapshot schedule. A snapshot schedule running perfectly reports that the array is healthy, which is information the estate already has.

Count recovery points per failure domain. Nine systems holding 336 snapshots each on one array is one recovery point against hardware loss, and every review should present the arithmetic that way.