Backup and Restore
Kaniop uses Kanidm’s native logical backup format. The operator configures the online backup scheduler on exactly one primary node and stores local artifacts under /data/backups on the Kanidm PVC.
spec:
backup:
schedule: "0 2 * * *"
versions: 7
Local backups require PVC-backed storage and one replicaGroup with primaryNode: true. Kaniop intentionally does not claim PITR semantics or a globally atomic point-in-time cut across replicated writable nodes.
Restore
Restore is an explicit destructive operation represented by KanidmRestore. Obtain the target UID with kubectl get kanidm <name> -o jsonpath='{.metadata.uid}', select an existing backup basename from /data/backups, and use the same pinned Kanidm image as the target. latest and untagged images are rejected.
apiVersion: kaniop.rs/v1beta1
kind: KanidmRestore
metadata:
name: my-idm-restore
spec:
targetRef:
name: my-idm
uid: <kanidm-uid>
source:
local:
fileName: backup.json.gz
restoreImage: kanidm/server:1.10.0
The controller validates the request, marks the target in maintenance, scales all Kanidm pods down, runs kanidmd database restore, verifies the database offline, discards stale secondary PVC data, starts the restored primary, rebuilds replicas through normal Kanidm replication, and only then resumes ordinary Kaniop reconciliation. A failure after database mutation is fail-closed: the restore remains Failed and the target remains marked as restoring.
Restoring a historical database is followed by GitOps reconciliation. Declaratively managed Kaniop resources can therefore be recreated or changed after recovery.
S3 and infrastructure snapshots
Kaniop does not implement a separate S3 uploader. Native S3-compatible shipping remains deferred until Kanidm exposes its supported upstream interface. CSI/Velero snapshots can be used as an independent disaster-recovery layer, but they are not represented as equivalent to a Kanidm-native logical backup.
Operations Runbook
Pre-restore checklist
Before creating a KanidmRestore:
- Verify the target UID matches the running Kanidm CR:
kubectl get kanidm <name> -o jsonpath='{.metadata.uid}' - List available local backups from the primary pod:
kubectl exec -n <namespace> <kanidm-primary-pod> -- ls -la /data/backups/ -
Confirm the pinned image matches the backup’s Kanidm version. The restore image must be an exact digest or tag (no
latest). - Ensure no other active restore targets the same Kanidm:
kubectl get kanidmrestore -n <namespace> - Verify PVC storage is persistent (not
emptyDir) and the Kanidm has exactly one primary replica group.
Performing a local restore
# 1. Get target UID
KANIDM_UID=$(kubectl get kanidm my-idm -o jsonpath='{.metadata.uid}')
# 2. Apply the restore
kubectl apply -f - <<EOF
apiVersion: kaniop.rs/v1beta1
kind: KanidmRestore
metadata:
name: my-idm-restore
namespace: default
spec:
targetRef:
name: my-idm
uid: ${KANIDM_UID}
source:
local:
fileName: backup.json.gz
restoreImage: kanidm/server:1.10.0
EOF
# 3. Monitor progress
kubectl get kanidmrestore my-idm-restore -w
kubectl describe kanidmrestore my-idm-restore
Post-restore verification
After the restore reaches Completed:
- Confirm all Kanidm pods are running and ready:
kubectl get pods -l app.kubernetes.io/instance=<kanidm-name> - Verify Kanidm is serving authentication:
kubectl exec -n <namespace> <kanidm-primary-pod> -- kanidmd verify - Check that Kaniop reconciliation has resumed:
kubectl get kanidmpersonaccount,kanidmgroup,kanidmoauth2client,kanidmserviceaccount -n <namespace> - Verify the maintenance annotation has been removed:
kubectl get kanidm <name> -o jsonpath='{.metadata.annotations}'
Failure recovery
Restore fails before database mutation
If the restore fails during validation, quiesce, or preflight checks, the controller automatically restores the original replica counts and removes the maintenance annotation. No manual intervention is required.
Restore fails after database mutation
If the restore fails after databaseMutationStarted becomes true, the Kanidm target remains offline and marked as restoring. This is a fail-closed state by design.
Recovery steps:
- Diagnose the failure from the restore status and events:
kubectl describe kanidmrestore <name> kubectl get events -n <namespace> --field-selector involvedObject.name=<name> -
If the database is corrupted beyond automatic recovery, create a new restore from a known-good backup.
- As a last resort, delete the
KanidmRestoreand recreate the Kanidm CR from scratch. The finalizer prevents deletion until the database is verified and service recovery is resolved.
Operator restart during restore
The controller persists phase state. After an operator restart, reconciliation resumes from the last persisted phase. No manual intervention is required unless the restore was in a transient Job phase—check that the Jobs complete successfully.
Prometheus alerts
When metrics.prometheusRules.enabled is set to true, the following backup/restore alerts are available:
| Alert | Severity | Condition | Action |
|---|---|---|---|
KaniopBackupStale |
critical | Backup age exceeds 24h | Verify backup schedule and Kanidm primary health |
KaniopBackupFailures |
warning | Multiple backup failures in 15m | Check Kanidm logs and PVC space |
KaniopRestoreFailures |
critical | Restore operation failed | Check restore status and events |
KaniopRestoreStuck |
critical | Restore running > 1 hour | Check Jobs and operator logs |
KaniopBackupRepositoryNotReady |
warning | Repository not ready for 5m | Verify credentials and endpoint |
KaniopBackupDiscoveryStale |
warning | Discovery not succeeded recently | Check repository connectivity |
KaniopRestoreBreakGlassUsed |
critical | Break-glass override used | Review audit log for authorization |
KaniopBackupGCDeferred |
warning | GC deferred for 30m | Check Object Lock or retention policy |
Individual alerts can be disabled or overridden via metrics.prometheusRules.overrides:
metrics:
prometheusRules:
enabled: true
overrides:
KaniopBackupStale:
disabled: true