Skip to content

Deletion and Teardown

Deleting a TerraformCluster, TerraformMachine or TerraformMachinePool means running Terraform’s destroy in a Job, then removing what CAPTF stored about the object. Most of the time nothing needs doing: you delete the Cluster Cluster API owns and everything follows. This chapter explains the order things happen in, what holds a deletion, how a deletion ends, and what is left behind when you short-circuit it. The step-by-step recoveries stay in the runbooks; this chapter is the model behind them.

The pages:

  1. This page: the rules in one table, and the pages that follow.
  2. Order and finalizers: who deletes what first, and when the finalizer comes off.
  3. The destroy Job: what runs, what does not gate it, and how it fails.
  4. Held deletions: missing or unreadable state, restore, and the abandon annotation.
  5. Terminating namespaces: deletions that need no Job, and the Secrets that go with the namespace.
  6. Cleanup and garbage collection: what the controller deletes, what Kubernetes deletes, and the RBAC sweep.
  7. clusterctl move: the delete that skips the delete path.
  8. Stripping a finalizer by hand: the consequences.
  9. My object will not delete: a flowchart from the symptom to the action.

In this section

The rules

A deleting object follows these rules, in this order. The first that applies decides the pass.

Situation What happens Page
The object or its Cluster is paused Nothing: a paused object runs only Job bookkeeping, so it neither destroys nor releases Order
A Job of the object is running The deletion waits for it; the destroy starts after Order
A TerraformCluster with machines or pools left DeletionBlocked=True/DependentsExist, no destroy yet Order
No state, and the object never applied The finalizer comes off at once Held
No state, and the object applied before Held: StateReadable=False/StateLost Held
State exists but cannot be read Held: StateCorrupt, StateEncrypted or StateInconsistent Held
Readable state A destroy Job runs; no gate or approval applies Destroy
The destroy succeeded Cleanup runs and the finalizer comes off Cleanup
The destroy failed or cannot start Retried with backoff, forever; the abandon annotation releases it Held

What the controller never does

  • It never drops the finalizer while a state Secret may still describe live resources, except on an explicit abandon.
  • It never destroys against a state it cannot read.
  • It never invents inputs to destroy with: the destroy renders from the durable inputs Secret (or, for a cluster or pool without one, the current inputs when they build).
  • It never skips the destroy because it failed. There is no skip-destroy annotation, only the abandon one.