@@ -103,8 +103,7 @@ container-registry, redis, mqtt, searxng, fizzy, nginx, jellyfin, nestmtx, homep
103103
104104Each app has:
105105- ` ReplicationSource ` - Defines backup schedule and retention
106- - ` ReplicationDestination ` - Dormant restore definition (no trigger)
107- - ` PVC ` - References ReplicationDestination via ` dataSourceRef `
106+ - ` ReplicationDestination ` - Dormant restore definition (triggered manually when needed)
108107- ` ExternalSecret ` - Pulls S3 credentials from 1Password
109108
110109### Database Backups (Native)
@@ -124,44 +123,54 @@ PostgreSQL databases use their native backup tools:
124123
125124## 3. Disaster Recovery
126125
127- ### Volume Populator Pattern (Automatic Restore)
126+ ### Defense Layers
128127
129- PVCs use the ** Volume Populator** pattern for automatic restore:
128+ - ** Layer 1 (Longhorn)** : Runtime replication across nodes - survives single node failure
129+ - ** Layer 2 (VolSync)** : S3 backups to RustFS - survives complete cluster loss
130130
131- ``` yaml
132- # In each app's PVC
133- spec :
134- dataSourceRef :
135- kind : ReplicationDestination
136- apiGroup : volsync.backube
137- name : <app>-restore
138- ` ` `
131+ ### Restoring a PVC (VolSync)
139132
140- **How it works:**
141- 1. PVC references a dormant ReplicationDestination (no trigger)
142- 2. When PVC is newly created (no existing Longhorn volume), Kubernetes uses the dataSourceRef
143- 3. VolSync automatically restores from S3 backup to populate the new PVC
144- 4. If Longhorn already has the data, dataSourceRef is ignored
133+ When you need to restore a PVC from backup:
145134
146- **This enables zero-intervention restore:**
147- - Deploy app → PVC created → auto-restore from S3 → app starts with data
148- - Longhorn replication is Layer 1 (node failure)
149- - S3 backup is Layer 2 (cluster loss)
150-
151- ### Manual Restore (if needed)
135+ 1 . ** Scale down the application** (to release the PVC):
136+ ``` bash
137+ kubectl scale deployment < app> -n < namespace> --replicas=0
138+ ```
152139
153- For manual restore scenarios, you can trigger the ReplicationDestination:
140+ 2 . ** Delete the existing PVC** (if corrupted/lost):
141+ ``` bash
142+ kubectl delete pvc < pvc-name> -n < namespace>
143+ ```
154144
145+ 3 . ** Trigger the ReplicationDestination** :
155146``` bash
156- # Add manual trigger to force restore
157147kubectl patch replicationdestination < app> -restore -n < namespace> \
158148 --type merge \
159149 -p ' {"spec":{"trigger":{"manual":"restore-' $( date +%s) ' "}}}'
150+ ```
160151
161- # Wait for restore to complete
152+ 4 . ** Wait for restore to complete** (creates a new PVC with restored data):
153+ ``` bash
162154kubectl get replicationdestination < app> -restore -n < namespace> -w
155+ # Look for: latestImage showing the restored snapshot
163156```
164157
158+ 5 . ** Rename/recreate the PVC** to match what the app expects, or update app to use the restored PVC name.
159+
160+ 6 . ** Scale up the application** :
161+ ``` bash
162+ kubectl scale deployment < app> -n < namespace> --replicas=1
163+ ```
164+
165+ ### Full Cluster Rebuild
166+
167+ After a complete cluster rebuild:
168+
169+ 1 . Deploy infrastructure (ArgoCD, External Secrets, Longhorn, VolSync)
170+ 2 . Deploy apps - PVCs will be created empty
171+ 3 . For each app needing data, trigger ReplicationDestination restore
172+ 4 . Apps will start with restored data
173+
165174### Restoring a Database
166175
167176** CloudNativePG:**
@@ -191,7 +200,7 @@ After a complete cluster rebuild:
191200| ---------| -------------------| ---------------|
192201| Backup tool | Longhorn built-in | VolSync + Restic |
193202| Backup schedule | RecurringJobs (tiered) | Tiered: hourly (critical) + daily (non-critical) |
194- | Restore method | Hardcoded restore-job.yaml | Volume Populator (automatic on PVC create) |
203+ | Restore method | Hardcoded restore-job.yaml | Trigger ReplicationDestination manually |
195204| Database backups | PVC snapshots (inconsistent) | Native WAL archiving (consistent) |
196205| Complexity | Multiple tiers, shell scripts | Declarative YAML per app |
197206
0 commit comments