Uninstall
Before uninstalling Testudo, decide whether you are deleting only the control plane, the CRDs, or backup data. These choices determine whether history and recovery data remain available.
Uninstall Modes
| Mode | Deletes | Keeps | Use Case |
|---|---|---|---|
| Control plane only | operator/server/web Deployments, Services, and Helm resources | CRDs, object storage data, remote Velero resources | Temporary shutdown or control-plane migration |
| Control plane with backups retained | Helm resources and some platform config | Object storage backup data | Stop the system but keep recovery data |
| Full cleanup | Helm resources, CRDs, Secrets, backup data | Nothing | Lab environment teardown |
Full cleanup is not recommended in production by default.
Pre-checks
kubectl -n disaster-system get disasteroperation
kubectl -n disaster-system get appbackups,apprestores
kubectl -n disaster-system get disasterdrills.testudo.softcdata.com
Confirm:
- No long-running operations are running.
- CRDs that must be retained are exported.
- Object storage bucket retention is decided.
- Remote Velero resources are decided.
- Console/API users are notified.
Uninstall Helm Release Only
helm uninstall testudo -n disaster-system
Check remaining resources:
kubectl -n disaster-system get all
kubectl get crd | grep testudo.softcdata.com
Whether CRDs are deleted depends on how the Chart packages CRDs. Use helm get manifest before uninstalling.
Delete Testudo CRDs During Uninstall
Helm does not delete CRDs installed from the chart crds/ directory by default. Normal install, upgrade, or control-plane-only uninstall does not require uninstallCleanup.enabled; enable it only when you explicitly want uninstall to delete Testudo CRDs and their CR instances. In that case, first upgrade the current release to a chart that contains the cleanup hook and enable uninstallCleanup.enabled:
helm repo update
helm upgrade testudo testudo/testudo-chart \
-n disaster-system \
--reuse-values \
--set uninstallCleanup.enabled=true
If you use an offline package or a private chart repository, replace testudo/testudo-chart with the same chart reference used for installation or upgrade. Do not uninstall an old release first and expect the new chart cleanup logic to run; Helm only runs hooks already stored in the current release.
Then uninstall:
helm uninstall testudo -n disaster-system --wait --timeout 10m
The cleanup hook runs the testudo-crd-cleanup Job before uninstall. It:
- Deletes the Testudo validating webhook so CR updates during cleanup are not blocked by the old webhook.
- Removes finalizers from Testudo CR instances.
- Deletes Testudo CRDs.
Deleting CRDs deletes all matching Testudo CR instance data. Before enabling this in production, confirm that those CRs are no longer needed or have been exported. uninstallCleanup.deleteVeleroCrds defaults to false; do not delete Velero CRDs while another Velero installation or backup data still depends on them.
If uninstall is stuck on the cleanup Job, inspect events and logs first:
kubectl -n disaster-system get job,pod | grep testudo-crd-cleanup
kubectl -n disaster-system describe job testudo-crd-cleanup
kubectl -n disaster-system logs job/testudo-crd-cleanup --all-containers
Common causes are an unpullable cleanup image or an image that does not contain /bin/sh and kubectl. The current chart default uses docker.io/dtzar/helm-kubectl:3.17.3 as the cleanup image. In offline environments, mirror this image to a registry the cluster can pull from and override these values:
uninstallCleanup:
enabled: true
kubectlImage:
repository: <registry.example.com>/dtzar/helm-kubectl
tag: "3.17.3"
If your cluster has many leftover CRDs or CR instances, or if the apiserver is slow, increase uninstallCleanup.timeoutSeconds further. This value controls both the per-CRD wait time and the Job deadline, so helm uninstall --wait --timeout must leave extra room as well.
If CRDs and historical CR instances are retained, the next installation may report errors similar to:
admission webhook "vdisasterinstance.kb.io" denied the request:
ModifierRuleRejected: load disasterConfig <name> failed:
DisasterConfig.testudo.softcdata.com "<name>" not found
This is usually not a failure of the new install itself. It means an old CR such as DisasterInstance remains with a finalizer and references a DisasterConfig that has already been deleted. When the operator tries to remove the finalizer, the update triggers webhook validation; the webhook cannot load the referenced object and rejects the update.
Retain Data
To retain recovery capability, keep:
- Object storage bucket and backup objects.
- Velero Backup/Restore metadata.
- Exported
StorageRepository,Cluster, andDisasterInstanceCRDs. - values files and image version records.
Dangerous Operations
These operations can cause irreversible data loss and require production approval:
kubectl delete crd <name>.testudo.softcdata.com
kubectl delete namespace disaster-system
mc rm --recursive --force <bucket/path>
Do not delete the object storage bucket without confirming backup retention policy.
Post-uninstall Verification
- Console entry no longer responds.
- Server API no longer responds.
- Business cluster workloads are not automatically deleted by control-plane uninstall.
- Object storage data is retained or deleted as intended.
- If CRDs are retained, reinstalling should allow the control plane to read existing state again.
If CRD cleanup was enabled, also confirm that Testudo CRDs are gone:
kubectl get crd | grep testudo.softcdata.com || true
kubectl -n disaster-system get job,pod | grep testudo-crd-cleanup || true