Skip to content

Commit 92a191e

Browse files
committed
Update backup-restore.md
1 parent 4309fab commit 92a191e

1 file changed

Lines changed: 101 additions & 3 deletions

File tree

docs/backup-restore.md

Lines changed: 101 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -140,23 +140,121 @@ volsync-backup/
140140
│ └── snapshots/ # Snapshot metadata
141141
```
142142
143+
## Critical Implementation Details
144+
145+
### Kyverno Policy: Operations Filter (Race Condition Fix)
146+
147+
**Problem:** Without an operations filter, Kyverno intercepts ALL PVC operations including DELETE, preventing PVC deletion.
148+
149+
**Solution:** All rules must include `operations: [CREATE]`:
150+
151+
```yaml
152+
match:
153+
any:
154+
- resources:
155+
kinds:
156+
- PersistentVolumeClaim
157+
operations:
158+
- CREATE # CRITICAL: Only trigger on create, not delete
159+
selector:
160+
matchExpressions:
161+
- key: backup
162+
operator: In
163+
values: ["hourly", "daily"]
164+
```
165+
166+
### External Secrets: mergePolicy (Template + Data Merge)
167+
168+
**Problem:** Kyverno uses `{{ }}` syntax, External Secrets uses `{{ }}` syntax. They conflict.
169+
170+
**Solution:** Use `mergePolicy: Merge` to combine:
171+
- `template.data` - RESTIC_REPOSITORY (Kyverno substitutes namespace/pvc-name)
172+
- `data` section - Credentials fetched from 1Password
173+
174+
```yaml
175+
target:
176+
name: "volsync-{{request.object.metadata.name}}"
177+
creationPolicy: Owner
178+
template:
179+
engineVersion: v2
180+
mergePolicy: Merge # CRITICAL: Merge template with fetched data
181+
data:
182+
# Kyverno substitutes these variables at generate time
183+
RESTIC_REPOSITORY: "s3:http://192.168.10.133:30292/volsync-backup/{{request.object.metadata.namespace}}/{{request.object.metadata.name}}"
184+
data:
185+
# External Secrets fetches these from 1Password and merges them
186+
- secretKey: AWS_ACCESS_KEY_ID
187+
remoteRef:
188+
key: rustfs
189+
property: k8s-admin-access-key
190+
- secretKey: AWS_SECRET_ACCESS_KEY
191+
remoteRef:
192+
key: rustfs
193+
property: k8s-admin-secret-key
194+
- secretKey: RESTIC_PASSWORD
195+
remoteRef:
196+
key: rustfs
197+
property: restic_password
198+
```
199+
200+
**Result:** Secret contains all 4 required fields:
201+
- `RESTIC_REPOSITORY` - from template (Kyverno-substituted)
202+
- `AWS_ACCESS_KEY_ID` - from 1Password
203+
- `AWS_SECRET_ACCESS_KEY` - from 1Password
204+
- `RESTIC_PASSWORD` - from 1Password
205+
206+
### Kyverno RBAC Requirements
207+
208+
Kyverno needs permissions to generate ExternalSecrets and VolSync resources:
209+
210+
```yaml
211+
# infrastructure/controllers/kyverno/rbac-patch.yaml
212+
rules:
213+
- apiGroups: [""]
214+
resources: ["secrets"]
215+
verbs: ["get", "list", "watch", "create", "update", "delete"]
216+
- apiGroups: ["external-secrets.io"]
217+
resources: ["externalsecrets"]
218+
verbs: ["get", "list", "watch", "create", "update", "delete"]
219+
- apiGroups: ["volsync.backube"]
220+
resources: ["replicationsources", "replicationdestinations"]
221+
verbs: ["get", "list", "watch", "create", "update", "delete"]
222+
```
223+
143224
## Troubleshooting
144225

145226
### PVC Stuck in Pending
146227
1. Check if ReplicationDestination exists: `kubectl get replicationdestination -n <namespace>`
147228
2. Check pvc-plumber logs: `kubectl logs -n volsync-system -l app.kubernetes.io/name=pvc-plumber`
148229
3. Check VolSync mover pod: `kubectl get pods -n <namespace> | grep volsync`
149230

231+
### PVC Stuck in Terminating (Race Condition)
232+
**Symptom:** PVCs won't delete, Kyverno keeps intercepting patches.
233+
234+
**Cause:** Missing `operations: [CREATE]` filter in Kyverno policy.
235+
236+
**Fix:** Ensure all rules have `operations: [CREATE]` in match clause.
237+
238+
### Secret Missing Credentials
239+
**Symptom:** VolSync fails with "access_key: placeholder" or missing credentials.
240+
241+
**Cause:** `mergePolicy: Replace` (default) overwrites fetched data with template.
242+
243+
**Fix:** Add `mergePolicy: Merge` to ExternalSecret template.
244+
245+
**Verify:** `kubectl get secret volsync-<pvc-name> -n <namespace> -o json | jq '.data | keys'`
246+
Should show: `["AWS_ACCESS_KEY_ID", "AWS_SECRET_ACCESS_KEY", "RESTIC_PASSWORD", "RESTIC_REPOSITORY"]`
247+
150248
### Backup Not Running
151249
1. Check ReplicationSource: `kubectl get replicationsource -n <namespace>`
152250
2. Check secret exists: `kubectl get secret -n <namespace> | grep volsync`
153251
3. Check ExternalSecret status: `kubectl get externalsecret -n <namespace>`
154252

155253
### Test pvc-plumber
156254
```bash
157-
kubectl port-forward -n volsync-system svc/pvc-plumber 8080:80
158-
curl http://localhost:8080/exists/karakeep/data-pvc
159-
# Expected: {"exists":true} or {"exists":false}
255+
kubectl run -n volsync-system test --rm -it --image=curlimages/curl --restart=Never -- \
256+
curl -s http://pvc-plumber.volsync-system.svc.cluster.local/exists/karakeep/data-pvc
257+
# Expected: {"exists":true,"keyCount":1} or {"exists":false}
160258
```
161259

162260
## Excluded Namespaces

0 commit comments

Comments
 (0)