Skip to content

Injecting hardware failures

Hardware failure is the hardest thing to test for, because you cannot arrange it on demand — there is no way to ask a production GPU to fall off the bus so you can see whether your remediation drains the node.

Declare it instead:

spec:
  faults:
    - nodeSelector: {rack: a}
      gpus: 1
      effect: Evict        # the card is gone; the job must move
      xid: 79              # reported on DCGM_FI_DEV_XID_ERRORS

Effects

Evict models device loss and uncorrectable ECC. The workload running on that GPU is thrown off and its ResourceClaim released, so it can be rescheduled onto healthy hardware — which is the behaviour a remediation or requeueing system under test actually needs to exercise.

Unschedulable models a card that still runs but must take no new work, such as one with a row remap pending a reboot.

The XID

The xid surfaces on DCGM_FI_DEV_XID_ERRORS, which is the signal most remediation watches. It also rides along on the device taint value, so kubectl get resourceslice explains why a device is out of service without anyone scraping metrics.

Composition with occupancy

Faults and occupancy are independent declarations applied lowest-index-first, and a fault wins where they overlap — so "three busy, one faulted" means the failure happened to a GPU that was working.

Repairing a fleet is just removing the entry, which makes a pending job schedulable again.

Verified, not assumed

The mechanism was chosen from a spike rather than from documentation. A NoExecute DRA device taint was verified live to evict a running workload and clear its claim allocation — that deallocation is what lets the job reschedule — with a negative control confirming an identical untainted pod survives the same wait.

See the fault injection spike findings.