Ga naar hoofdinhoud

Velero (preview)

lionbackup wordt een opslagdoel voor Velero, het back-uptool voor Kubernetes. Daarvoor is er een plugin die lionbackup als BackupStorageLocation-provider registreert, en een kleine controller in het cluster die elke voltooide back-up als één versleuteld bestand naar een lionbackup-project uploadt. Beide zijn beschikbaar als bèta 0.2.0-beta.1: om uit te proberen in een testcluster, nog niet als uw enige back-up.

Preview: nog geen volumedata

Wat bij lionbackup aankomt, is de spool: Kubernetes-manifests, metadata en logs van de back-up. De inhoud van volumes (PVC's) wordt nog niet geback-upt; een PVC komt als definitie terug, maar leeg. Blijf voor volumedata op een andere weg vertrouwen.

Wat de preview vandaag doet, en wat niet​

Werkt vandaagOntbreekt nog
Velero draait volledig tegen een spool in het cluster: back-up en herstel van manifests, sync, GC, backup deleteVolumedata: PVC-inhoud wordt niet vastgelegd (de node-agent van Velero kent alleen s3, azure, gcs en bestandssysteem)
Ondertekende URL's: velero backup logs en describe --details werken, back-ups eindigen CompletedHerstelimport: de bundel komt van buiten het cluster terug in de spool (client met leestoken)
Upload: de controller bundelt backups/<naam>/ tot één .lbk, uploadt die met een schrijftoken en annoteert de back-up met de file_idCapture- en hersteljobs voor volumes; herhaling alleen als "over 10 minuten opnieuw"

Een Failed back-up betekent dat er niets is geschreven; meestal klopt dan de eigenaar van de spoolmap niet (zie stap 1). Een PartiallyFailed komt alleen nog voor als de controller of het gedeelde URL-geheim ontbreekt (stap 4).

Uitproberen​

U hebt een testcluster nodig, kubectl, de Velero-CLI (getest met Velero 1.18.3), een lionbackup-project met een schrijftoken en de lionbackup-client op uw werkstation voor het sleutelpaar. De plugin-image is zonder aanmelding op te halen.

1. De spoolmap aanmaken​

Velero schrijft naar een map op de node die als hostPath (of als PVC) in de Velero-pod wordt gemount. De officiële Velero-image draait als gebruikers-ID 1002; fsGroup geldt niet voor een hostPath, dus de map moet van dat ID zijn. Anders mislukt elke back-up met permission denied, terwijl alle objecten toch als geback-upt worden gemeld; de fout staat alleen in status.failureReason.

mkdir -p /var/lib/lionbackup/spool
chown -R 1002:1002 /var/lib/lionbackup/spool
chmod 775 /var/lib/lionbackup/spool

2. Velero met de plugin installeren​

velero install \
--provider lionbackup.cloud/lionbackup \
--plugins git.prod.lionbackup.cloud/lionbackup/velero-plugin-lionbackup:0.2.0-beta.1 \
--bucket spool \
--no-secret \
--use-volume-snapshots=false \
--backup-location-config spoolPath=/var/lib/lionbackup/spool \
--wait

--no-secret is juist: de plugin zelf heeft geen inloggegevens nodig. Het schrijftoken hoort in het Secret van de controller (stap 4), nooit op de BackupStorageLocation.

3. De spool in de Velero-pod mounten​

kubectl -n velero patch deployment velero --type=json -p '[
{"op":"add","path":"/spec/template/spec/volumes/-","value":{"name":"lionbackup-spool","hostPath":{"path":"/var/lib/lionbackup/spool","type":"DirectoryOrCreate"}}},
{"op":"add","path":"/spec/template/spec/containers/0/volumeMounts/-","value":{"name":"lionbackup-spool","mountPath":"/var/lib/lionbackup/spool"}}
]'
kubectl -n velero rollout status deploy/velero --timeout=180s
kubectl -n velero get backupstoragelocation default

Zonder deze stap leeft de spool in het bestandssysteem van de pod en is hij na de volgende herstart weg. De BackupStorageLocation hoort daarna Available te melden.

4. Controller en Secret​

De controller draait in dezelfde image als gebruiker 1002, met de spool alleen-lezen gemount en het Secret onder /etc/lionbackup. Hij heeft drie dingen nodig: het schrijftoken van het project, een willekeurig URL-geheim dat hij met de Velero-pod deelt, en de publieke sleutel voor de versleuteling. Genereer het sleutelpaar op uw werkstation; de privésleutel komt nooit in het cluster, en zonder die is er geen herstel.

lionbackup --generate-key --key-name ./velero
kubectl -n velero create secret generic lionbackup-velero \
--from-literal=token=<WRITE-TOKEN> \
--from-literal=url-secret="$(head -c 32 /dev/urandom | base64)" \
--from-file=key.pub=./velero.pub

Sla het volgende manifest op als controller.yaml. Het bevat ServiceAccount, Role, RoleBinding, Service en Deployment; de werkmap /work moet de grootste back-upmap van de spool kunnen bevatten.

---
apiVersion: v1
kind: ServiceAccount
metadata:
name: lionbackup-velero-controller
namespace: velero
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: lionbackup-velero-controller
namespace: velero
rules:
- apiGroups: ["velero.io"]
resources: ["backups"]
verbs: ["get", "list", "watch", "patch"]
- apiGroups: ["velero.io"]
resources: ["backupstoragelocations"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: lionbackup-velero-controller
namespace: velero
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: lionbackup-velero-controller
subjects:
- kind: ServiceAccount
name: lionbackup-velero-controller
namespace: velero
---
apiVersion: v1
kind: Service
metadata:
name: lionbackup-velero-controller
namespace: velero
spec:
selector:
app.kubernetes.io/name: lionbackup-velero-controller
ports:
- name: http
port: 8080
targetPort: http
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: lionbackup-velero-controller
namespace: velero
labels:
app.kubernetes.io/name: lionbackup-velero-controller
spec:
replicas: 1
strategy:
type: Recreate
selector:
matchLabels:
app.kubernetes.io/name: lionbackup-velero-controller
template:
metadata:
labels:
app.kubernetes.io/name: lionbackup-velero-controller
spec:
serviceAccountName: lionbackup-velero-controller
securityContext:
runAsUser: 1002
runAsGroup: 1002
runAsNonRoot: true
containers:
- name: controller
image: git.prod.lionbackup.cloud/lionbackup/velero-plugin-lionbackup:0.2.0-beta.1
command: ["/plugins/velero-plugin-lionbackup"]
args: ["controller"]
ports:
- name: http
containerPort: 8080
env:
- name: VELERO_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: LIONBACKUP_SPOOL_PATH
value: /var/lib/lionbackup/spool
- name: LIONBACKUP_KEYFILE
value: /etc/lionbackup/key.pub
- name: LIONBACKUP_WORKDIR
value: /work
- name: LIONBACKUP_TOKEN
valueFrom:
secretKeyRef:
name: lionbackup-velero
key: token
- name: LIONBACKUP_VELERO_URL_SECRET
valueFrom:
secretKeyRef:
name: lionbackup-velero
key: url-secret
readinessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 3
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: "2"
memory: 1Gi
volumeMounts:
- name: lionbackup-spool
mountPath: /var/lib/lionbackup/spool
readOnly: true
- name: lionbackup-secret
mountPath: /etc/lionbackup
readOnly: true
- name: work
mountPath: /work
volumes:
- name: lionbackup-spool
hostPath:
path: /var/lib/lionbackup/spool
type: Directory
- name: lionbackup-secret
secret:
secretName: lionbackup-velero
items:
- key: key.pub
path: key.pub
- name: work
emptyDir:
sizeLimit: 10Gi

Pas het daarna toe, geef het URL-geheim ook aan de Velero-deployment en zet project en zone op de BackupStorageLocation:

kubectl apply -f controller.yaml
kubectl -n velero set env deployment/velero \
LIONBACKUP_VELERO_URL_SECRET="$(kubectl -n velero get secret lionbackup-velero -o jsonpath='{.data.url-secret}' | base64 -d)"
kubectl -n velero patch backupstoragelocation default --type=merge -p \
'{"spec":{"config":{"lbProject":"<PROJECT-UUID>","lbZone":"de01-1","lbEnvironment":"prod"}}}'
kubectl -n velero rollout status deploy/velero --timeout=180s
kubectl -n velero rollout status deploy/lionbackup-velero-controller --timeout=180s

Zonder token of sleutel logt de controller alleen wat hij zou uploaden (observe-only). Verdere config-sleutels van de BackupStorageLocation: lbCompressionMethod (ZSTD), lbCompressionLevel (5), lbChunksizeMb (64), lbUploadRateLimitMbit (0 = onbeperkt).

De ondertekende URL's wijzen naar de controller-Service in het cluster, dus velero backup logs en describe --details werken waar die Service bereikbaar is. Draait de Velero-CLI buiten het cluster, stuur dan de poort door (kubectl -n velero port-forward svc/lionbackup-velero-controller 8080:8080) en zet controllerURL op de BackupStorageLocation op http://localhost:8080; de handtekening dekt alleen pad en vervaltijd, niet de host.

5. Back-up​

velero backup create demo-1 --include-namespaces demo-app --wait
velero backup logs demo-1 | tail -n 3
kubectl -n velero get backup demo-1 \
-o jsonpath='{.status.phase} {.metadata.annotations.lionbackup\.cloud/file-id}{"\n"}'

Verwacht Completed, en velero backup logs levert het log via de ondertekende URL van de controller. Kort daarna draagt het Backup-object de annotatie lionbackup.cloud/file-id: de identificatie van het geüploade bestand in het project, dezelfde die --list van de client toont. Mislukt de upload, dan staat de reden in het log van de controller en probeert hij het na tien minuten opnieuw.

6. Herstel vanuit lionbackup​

De weg terug begint buiten het cluster, met een leestoken en de privésleutel; beide blijven zo buiten het cluster. De client haalt de bundel op, u kopieert de back-upmap naar de spool van het doelcluster en Velero pikt hem op bij de volgende sync van de BackupStorageLocation:

lionbackup --config read.yaml --list
lionbackup --config read.yaml --restore <FILE-ID> --identity ./velero.key --target ./restored
# ./restored/…/backups/demo-1/ -> <spoolPath>/spool/backups/demo-1/ des Zielclusters
velero restore create demo-restore --from-backup demo-1 --wait

Manifests, deployments, ConfigMaps en PVC-definities komen terug. De data in de volumes niet; dat is de gedocumenteerde grens van de preview.

Wat volgt​

De volgende stap back-upt de inhoud van volumes: een job per PVC op de node van de pod streamt het volume als archief naar de spool, een bijbehorende hersteljob vult het terug, en een init-container houdt de applicatie vast tot het volume er weer is. Daar komt een controller-endpoint bij dat een bundel via file_id rechtstreeks in de spool terughaalt. Tot dan geldt de opmerking bovenaan deze pagina.