Velero — Kubernetes Backup a Disaster Recovery
Velero (predtým Heptio Ark) je open-source nástroj pre zálohovanie, obnovu a migráciu Kubernetes klastrov. Spravuje ho VMware (teraz Broadcom) a je de-facto štandardom pre backup v ekosystéme CNCF. Kombinuje zálohy Kubernetes objektov (etcd nie je priamo potrebný) s konzistentným zálohovaním perzistentných volumes — buď cez CSI snapshots alebo cez agenta bežiaceho v pode (Restic/Kopia).
V roku 2020 sa Velero stal CNCF Incubating projektom. V produkcii ho používajú tisíce tímov naprieč managed (EKS, GKE, AKS) aj on-premise klastrami.
Prečo K8s backup nie je triviálny
Keď sa väčšina ľudí prvý raz stretne s Kubernetes, myslí si: stačí zálohovať etcd a som v suchu. To je nebezpečná ilúzia.
Čo etcd snapshot pokrýva (a čo nie)
etcd je distribuovaná key-value databáza, ktorá uchováva stav celého klastra — Deployments, Services, ConfigMaps, Secrets, RBAC objekty, PVC definície. Na prvý pohľad to vyzerá ako kompletný backup.
Problémy nastanú pri obnove:
- etcd snapshot je viazaný na konkrétnu verziu klastra — obnovenie snapshot-u z K8s 1.28 na K8s 1.30 klastruje ťažko (schémy API sa menia).
- Dáta v PersistentVolumes nie sú v etcd — etcd obsahuje iba PVC/PV definíciu (metadata), nie skutočné bloky dát na disku. Po obnovení etcd budete mať PVC, ktorá ukazuje na volume, ktorý môže fyzicky neexistovať alebo byť prepísaný.
- etcd snapshot zahŕňa celý klaster — nie je možné obnoviť iba jeden namespace, jednu aplikáciu alebo jeden Deployment. Je to všetko alebo nič.
- CRDs a ich inštancie — Custom Resource Definitions sú v etcd, no pri obnove musíte zaručiť správne poradie (CRD musí existovať pred jej inštanciou). Velero to rieši automaticky.
- Cross-cluster migrácia je nemožná cez etcd — etcd snapshot nie je prenosný medzi rôznymi klastrovými konfigurácami (iný sieťový plugin, iné certifikáty).
Stateful workloads — skutočný problém
Databázy (PostgreSQL, MySQL, MongoDB), message queues (Kafka, RabbitMQ), objektové úložiská (MinIO) a iné stateful aplikácie vyžadujú konzistentnú zálohu — teda zálohu, kde sú súbory na disku v stave, ktorý je konzistentný z pohľadu aplikácie. Ak zálohujem PostgreSQL za behu bez freeze/checkpoint, riskovím poškodený backup.
Velero rieši toto cez backup hooks — príkazy, ktoré sa spustia v pode pred a po zálohe (napr. pg_dump, FLUSH TABLES WITH READ LOCK).
Namespace-scoped resources a CRDs
Kubernetes má dva typy objektov: cluster-scoped (Nodes, PersistentVolumes, ClusterRoles, CRDs samotné) a namespace-scoped (Pods, Deployments, Services, PVCs). Kompletná záloha musí pokryť oboje v správnom poradí. Velero to robí automaticky.
Čo Velero zálohuje:
┌────────────────────────────────────────────────┐
│ Kubernetes API objekty (z etcd) │
│ ├── Namespace-scoped: Deploy, SVC, CM, PVC │
│ ├── Cluster-scoped: PV, ClusterRole, CRD │
│ └── Custom Resources (CRD inštancie) │
│ │
│ Volume data (mimo etcd) │
│ ├── CSI snapshot (block-level, rýchly) │
│ └── File system backup / Restic / Kopia │
└────────────────────────────────────────────────┘
Architektúra Velero
┌─────────────────────────────────────────────────────┐
│ Object Storage (S3 / MinIO / GCS / Azure Blob) │
│ ┌──────────────────────────────────────────────┐ │
│ │ backup-name/ │ │
│ │ ├── velero-backup.json (metadata) │ │
│ │ ├── resources/ (K8s objekty) │ │
│ │ └── volume-snapshots/ (snap refs / data) │ │
│ └──────────────────────────────────────────────┘ │
└───────────────────────┬─────────────────────────────┘
│
┌─────────▼──────────┐
│ Velero Server │ ← Deployment v `velero` namespace
│ (Control Plane) │
│ ├── Backup Ctrl │
│ ├── Restore Ctrl │
│ ├── Schedule Ctrl │
│ └── GC Ctrl │
└────────┬───────────┘
│
┌──────────────┼──────────────┐
│ │ │
┌───────▼──────┐ ┌─────▼──────┐ ┌────▼───────────────┐
│ BackupStorage│ │ VolumeSnap │ │ node-agent │
│ Location │ │ Location │ │ (DaemonSet) │
│ (S3 config) │ │ (CSI/cloud)│ │ Restic / Kopia FSB │
└──────────────┘ └────────────┘ └────────────────────┘
Velero Server
Velero server beží ako Deployment v namespace velero. Obsahuje niekoľko kontrolérov:
- Backup Controller — sleduje
BackupCRD, spúšťa backup process, uploaduje do object storage. - Restore Controller — sleduje
RestoreCRD, sťahuje backup z object storage, aplikuje objekty. - Schedule Controller — sleduje
ScheduleCRD, v správnom čase vytváraBackupobjekty. - GC Controller — maže expirované zálohy (na základe TTL) vrátane ich dát v object storage.
BackupStorageLocation (BSL)
BackupStorageLocation je CRD, ktorý definuje, kam sa zálohy ukladajú:
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
name: default
namespace: velero
spec:
provider: aws
objectStorage:
bucket: my-velero-backups
prefix: production-cluster
config:
region: eu-west-1
s3ForcePathStyle: "true" # pre MinIO
s3Url: "http://minio:9000" # pre on-premise MinIO
Velero podporuje viacero BSL naraz — môžete mať primary BSL v AWS S3 a secondary v on-premise MinIO pre air-gapped DR scenáre.
VolumeSnapshotLocation (VSL)
VolumeSnapshotLocation definuje, kde sú uložené volume snapshots (relevantné pre non-CSI pluginy alebo cloud-native snapshoty):
apiVersion: velero.io/v1
kind: VolumeSnapshotLocation
metadata:
name: aws-ebs
namespace: velero
spec:
provider: aws
config:
region: eu-west-1
Pre CSI snapshots (preferovaný moderný prístup) sa VSL nevyžaduje — snapshot je riadený cez Kubernetes VolumeSnapshot API.
Velero CLI
velero CLI komunikuje s klastrom cez Kubernetes API (nie priamo so serverom cez HTTP). Posielate Backup alebo Restore objekty a sledujete ich stav.
# Inštalácia CLI
curl -L https://github.com/vmware-tanzu/velero/releases/download/v1.14.0/velero-v1.14.0-linux-amd64.tar.gz | tar xz
mv velero-v1.14.0-linux-amd64/velero /usr/local/bin/
# Základné príkazy
velero backup get
velero restore get
velero schedule get
velero backup describe my-backup --details
velero backup logs my-backup
Dva režimy zálohovania volumes
Toto je kľúčové rozhodnutie pri každom Velero deployi. Existujú dva fundamentálne odlišné prístupy k zálohovaniu dát v PersistentVolumes.
CSI Snapshots (preferovaný)
CSI snapshots využívajú natívne Kubernetes VolumeSnapshot API (GA od K8s 1.20). Velero vytvorí VolumeSnapshot objekt, ktorý driver storage class (napr. AWS EBS CSI, GCE PD CSI, Longhorn, OpenEBS) vykoná na infraštruktúrnej úrovni — typicky ako copy-on-write snapshot na úrovni blokového zariadenia.
Výhody:
- Rýchly — snapshot na block level je väčšinou instantánny (CoW metadáta).
- Konzistentný — ak aplikácia podporuje crash-consistent stav, je to OK. Pre silnú konzistentnosť kombinujte s backup hooks.
- Natívny pre cloud — EBS, GCE PD, Azure Disk, Ceph RBD, Longhorn všetky podporujú CSI snapshots.
- Žiadny agent v pode — nepotrebujete node-agent DaemonSet.
Obmedzenia:
- Závisí na storage driver — ak váš storage class nepodporuje CSI snapshots, táto metóda nefunguje.
- Snapshot zostáva v rovnakom storage systéme — cross-region alebo cross-provider DR môže vyžadovať dodatočnú replikáciu.
- Nie pre cross-cluster migráciu — snapshot na EBS nemôžete použiť pri obnovení do GKE.
Konfigurácia pre CSI snapshots:
# Velero Backup s CSI snapshot aktivovaným
apiVersion: velero.io/v1
kind: Backup
metadata:
name: production-csi
namespace: velero
spec:
includedNamespaces:
- production
snapshotVolumes: true
# CSI snapshot sa aktivuje automaticky ak je CSI plugin nainštalovaný
# a storage class má provisioner s CSI snapshot support
defaultVolumesToFsBackup: false # nechceme Restic fallback
storageLocation: default
ttl: 720h # 30 dní
File System Backup — Restic / Kopia (Data Mover)
File System Backup (FSB) je prístup, kde Velero číta súbory priamo z PV cez node-agent DaemonSet. Historicky sa používal Restic, od Velero 1.12+ je preferovaný Kopia (rýchlejší, lepšia deduplikácia).
FSB workflow:
┌──────────────────────────────────────────────────┐
│ Node │
│ ┌─────────────────┐ ┌────────────────────┐ │
│ │ Aplikačný pod │ │ node-agent pod │ │
│ │ (napr. MySQL) │ │ (Restic / Kopia) │ │
│ │ Volume montovaný│◄──│ číta cez hostPath │ │
│ │ na /var/lib/db │ │ alebo shared mount│ │
│ └─────────────────┘ └────────┬───────────┘ │
└────────────────────────────────┬┘ │
│ upload deduplikovaných blokov
┌───────▼──────┐
│ Object Store│
│ (S3/MinIO) │
└──────────────┘
Výhody FSB:
- Storage-agnostic — funguje s akýmkoľvek PV, aj bez CSI snapshot support.
- Offsite data — dáta sú uploadované priamo do object storage (S3/MinIO), nie len snapshot na lokálnom storage.
- Cross-cluster DR — backup z AWS EKS môžete obnoviť do on-premise klastra alebo GKE.
- Deduplikácia — Kopia deduplikuje bloky naprieč zálohovacími behy.
Obmedzenia:
- Pomalší — čítanie súborov cez FS je pomalšie ako block snapshot.
- Vyžaduje node-agent DaemonSet — extra overhead na každom node.
- Konzistentnosť — ak aplikácia práve píše, môžete dostať nekonzistentný snapshot FS. Vždy kombinujte s backup hooks pre DB.
- Kopia vs Restic — Restic je legacy, Kopia je preferovaný od 1.12. Migrácia medzi nimi nie je automatická.
Aktivácia FSB:
apiVersion: velero.io/v1
kind: Backup
metadata:
name: production-fsb
namespace: velero
spec:
includedNamespaces:
- production
defaultVolumesToFsBackup: true # zapne FSB pre všetky PV
uploaderType: kopia # "restic" alebo "kopia"
storageLocation: default
ttl: 168h # 7 dní
Alebo selektívne cez anotáciu na pode:
# Pod anotácia — FSB iba pre konkrétny pod
metadata:
annotations:
backup.velero.io/backup-volumes: data-volume,config-volume
# alebo vylúčiť volume z FSB:
backup.velero.io/backup-volumes-excludes: cache-volume
Kedy použiť čo
| CSI Snapshots | FSB (Kopia) | |
|---|---|---|
| Rýchlosť | ✅ Sekundy | ⚠️ Minúty až hodiny |
| Storage-agnostic | ❌ Len CSI | ✅ Čokoľvek |
| Cross-cluster DR | ❌ | ✅ |
| Offsite dáta | ⚠️ Vyžaduje replikáciu | ✅ Priamo v S3 |
| Konzistentnosť | Crash-consistent | Crash-consistent (hooks = app-consistent) |
| Odporúčanie | Primárny backup v cloude | DR / cross-cluster / on-premise |
Zlaté pravidlo: Kombinujte oba. CSI snapshots pre rýchly lokálny backup, FSB do vzdialeneho S3 pre skutočné DR.
Inštalácia — Helm chart s MinIO
Najčistejší spôsob inštalácie Velero v produkcii je cez Helm.
Príprava MinIO (on-premise object storage)
# MinIO namespace a deployment (ak ho ešte nemáte)
kubectl create namespace minio
helm repo add minio https://charts.min.io/
helm install minio minio/minio \
--namespace minio \
--set rootUser=admin \
--set rootPassword=strongpassword123 \
--set persistence.size=500Gi \
--set mode=standalone
# Vytvorenie bucketu pre Velero
kubectl exec -n minio deploy/minio -- \
mc mb /data/velero-backups
Credentials Secret
# Súbor s credentials pre AWS/MinIO S3
cat > /tmp/velero-credentials << EOF
[default]
aws_access_key_id=admin
aws_secret_access_key=strongpassword123
EOF
kubectl create secret generic velero-s3-credentials \
--namespace velero \
--from-file=cloud=/tmp/velero-credentials
rm /tmp/velero-credentials
Helm install Velero
helm repo add vmware-tanzu https://vmware-tanzu.github.io/helm-charts
helm repo update
helm install velero vmware-tanzu/velero \
--namespace velero \
--create-namespace \
--version 7.2.1 \
--set-json 'configuration.backupStorageLocation[0].name="default"' \
--set-json 'configuration.backupStorageLocation[0].provider="aws"' \
--set-json 'configuration.backupStorageLocation[0].bucket="velero-backups"' \
--set-json 'configuration.backupStorageLocation[0].config.region="minio"' \
--set-json 'configuration.backupStorageLocation[0].config.s3ForcePathStyle="true"' \
--set-json 'configuration.backupStorageLocation[0].config.s3Url="http://minio.minio.svc.cluster.local:9000"' \
--set credentials.useSecret=true \
--set credentials.existingSecret=velero-s3-credentials \
--set-json 'initContainers=[{"name":"velero-plugin-for-aws","image":"velero/velero-plugin-for-aws:v1.10.0","volumeMounts":[{"mountPath":"/target","name":"plugins"}]}]' \
--set nodeAgent.enabled=true \
--set configuration.uploaderType=kopia \
--set metrics.enabled=true \
--set metrics.serviceMonitor.enabled=true
Overenie:
velero backup-location get
# NAME PROVIDER BUCKET/PREFIX PHASE LAST VALIDATED
# default aws velero-backups/ Available 2026-04-17 08:00:00
kubectl get pods -n velero
# velero-xxxxxxxxx-xxxxx 1/1 Running
# node-agent-xxxxx 1/1 Running (na každom node)
Inštalácia pluginov
Velero používa init container pattern pre pluginy — pri štarte sa plugin binary skopíruje do hlavného kontajnera:
# Helm values — viacero pluginov
initContainers:
- name: velero-plugin-for-aws
image: velero/velero-plugin-for-aws:v1.10.0
volumeMounts:
- mountPath: /target
name: plugins
- name: velero-plugin-for-csi
image: velero/velero-plugin-for-csi:v0.7.1
volumeMounts:
- mountPath: /target
name: plugins
Dostupné pluginy: velero-plugin-for-aws, velero-plugin-for-gcp, velero-plugin-for-microsoft-azure, velero-plugin-for-csi.
Zálohovanie — Backup CRD a Schedule
Jednorazový backup
# Backup celého klastra
velero backup create full-cluster-$(date +%Y%m%d)
# Backup konkrétneho namespace
velero backup create production-backup \
--include-namespaces production \
--ttl 168h
# Backup s label selectorom — len konkrétna aplikácia
velero backup create myapp-backup \
--include-namespaces production \
--selector app=myapp \
--ttl 72h
# Backup s vylúčením resources (napr. Pods sú efemérne, nepotrebujeme ich backupovať)
velero backup create production-backup \
--include-namespaces production \
--exclude-resources pods,events \
--ttl 720h
YAML manifest (GitOps)
apiVersion: velero.io/v1
kind: Backup
metadata:
name: production-daily
namespace: velero
labels:
app: velero
environment: production
spec:
includedNamespaces:
- production
- monitoring
- ingress-nginx
excludedResources:
- pods
- replicasets
- events
- events.events.k8s.io
# Volume backup — CSI preferovaný, FSB ako fallback
snapshotVolumes: true
defaultVolumesToFsBackup: false
storageLocation: default
ttl: 720h # 30 dní
# Metadata labels na backup objekte
labelSelector:
matchExpressions:
- key: backup-exclude
operator: DoesNotExist
Schedule — pravidelné zálohy
Schedule CRD definuje opakujúce sa zálohy s cron syntaxou:
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: production-daily
namespace: velero
spec:
schedule: "0 2 * * *" # každú noc o 2:00 UTC
template:
includedNamespaces:
- production
excludedResources:
- pods
- replicasets
- events
snapshotVolumes: true
defaultVolumesToFsBackup: false
storageLocation: default
ttl: 720h
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: production-hourly-config
namespace: velero
spec:
schedule: "0 * * * *" # každú hodinu — len konfigurácia, žiadne volumes
template:
includedNamespaces:
- production
snapshotVolumes: false
defaultVolumesToFsBackup: false
excludedResources:
- pods
- replicasets
- events
- persistentvolumeclaims
storageLocation: default
ttl: 168h
# Sledovanie stavu
velero schedule get
velero backup get --selector velero.io/schedule-name=production-daily
# Detail zálohy
velero backup describe production-daily-20260417020000 --details
Footgun: exclude-resources vs include-resources
Ak použijete --include-resources, Velero zálohuje iba tie resource typy. Ak zabudnete na niečo (napr. ConfigMaps), v backupe chýba. Bezpečnejšia stratégia je --exclude-resources — zálohujete všetko okrem toho, čo explicitne vylúčite. Vylúčte aspoň: pods, replicasets, events — sú efemérne a pri restore ich K8s znovu vytvorí z Deployment/ReplicaSet definícií.
Obnova — Restore
Základná obnova
# Obnova z konkrétneho backupu
velero restore create --from-backup production-daily-20260417020000
# Obnova s vlastným názvom
velero restore create my-restore \
--from-backup production-daily-20260417020000
# Sledovanie priebehu
velero restore describe my-restore
velero restore logs my-restore
Čiastočná obnova — jeden namespace
# Obnoviť iba jeden namespace z full-cluster backupu
velero restore create production-restore \
--from-backup full-cluster-20260417 \
--include-namespaces production
# Obnoviť konkrétne resources
velero restore create configmap-restore \
--from-backup full-cluster-20260417 \
--include-resources configmaps,secrets \
--include-namespaces production
Cross-cluster restore — DR scenár
Toto je najsilnejší usecase Velera — prenos aplikácie z jedného klastra do druhého, napríklad pri havárii alebo migrácii.
Predpoklady:
- Nový klaster má prístup k rovnakému
BackupStorageLocation(S3 bucket). - Velero je nainštalovaný v novom klastri s rovnakou verziou.
- Storage class s rovnakým menom existuje v novom klastri (alebo použijete namespace/storage class mapping).
# V novom klastri — pridanie BSL odkazujúceho na existujúci S3
cat <<EOF | kubectl apply -f -
apiVersion: velero.io/v1
kind: BackupStorageLocation
metadata:
name: dr-location
namespace: velero
spec:
provider: aws
objectStorage:
bucket: velero-backups
prefix: production-cluster
config:
region: eu-west-1
accessMode: ReadOnly # bezpečnostný princíp — nový klaster len číta
EOF
# Synchronizácia backupov z BSL (Velero stiahne metadata)
velero backup get
# Obnova s mapovaním namespace (ak chceme iný názov v novom klastri)
velero restore create dr-restore \
--from-backup production-daily-20260417020000 \
--namespace-mappings production:production-dr \
--restore-volumes=true
Mapovanie storage class pri restore
Ak nový klaster má iné storage classes, použite --restore-volume-storage-class-overrides (Velero 1.14+) alebo ConfigMap:
apiVersion: v1
kind: ConfigMap
metadata:
name: change-storage-class-config
namespace: velero
labels:
velero.io/plugin-config: ""
velero.io/change-storage-class: RestoreItemAction
data:
gp2: gp3 # v starom klastri bolo gp2, v novom chceme gp3
standard: premium-rwo
Restore a existujúce resources
Velero predvolene preskočí existujúce resources pri restore (neprepisuje). Toto správanie môžete zmeniť:
# Prepísať existujúce resources
velero restore create my-restore \
--from-backup my-backup \
--existing-resource-policy update
# Alebo v YAML
spec:
existingResourcePolicy: update # "none" (default) alebo "update"
Backup Hooks — konzistentné zálohy DB
Backup hooks umožňujú spustiť príkaz v pode pred (pre-hook) alebo po (post-hook) zálohe. Toto je kľúčové pre aplikácie, ktoré musia byť quiesced — databázy, message queues, cache systémy.
Anotácie na pode
Najjednoduchší spôsob — anotácie priamo na Pod template v Deployment:
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql
namespace: production
spec:
template:
metadata:
annotations:
# Pre-backup hook — uzamkne tabuľky
pre.hook.backup.velero.io/command: >
["/bin/bash", "-c",
"mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'FLUSH TABLES WITH READ LOCK;'"]
pre.hook.backup.velero.io/container: mysql
pre.hook.backup.velero.io/on-error: Fail
pre.hook.backup.velero.io/timeout: 60s
# Post-backup hook — odomkne tabuľky
post.hook.backup.velero.io/command: >
["/bin/bash", "-c",
"mysql -u root -p$MYSQL_ROOT_PASSWORD -e 'UNLOCK TABLES;'"]
post.hook.backup.velero.io/container: mysql
post.hook.backup.velero.io/on-error: Continue
post.hook.backup.velero.io/timeout: 30s
Hooks v Backup CRD
Pre viac kontroly — hooks definované priamo v Backup objekte:
apiVersion: velero.io/v1
kind: Backup
metadata:
name: production-with-hooks
namespace: velero
spec:
includedNamespaces:
- production
hooks:
resources:
- name: postgresql-pre-backup
includedNamespaces:
- production
labelSelector:
matchLabels:
app: postgresql
pre:
- exec:
container: postgresql
command:
- /bin/bash
- -c
- >
psql -U postgres -c "CHECKPOINT;"
psql -U postgres -c "SELECT pg_start_backup('velero', true);"
onError: Fail
timeout: 120s
post:
- exec:
container: postgresql
command:
- /bin/bash
- -c
- psql -U postgres -c "SELECT pg_stop_backup();"
onError: Continue
timeout: 60s
Footgun: hooks a timeout
Ak pre-hook zamkne databázu a timeout vyprší pred tým, ako Velero stihne zálohovať volume, Velero zruší backup a post-hook nemusí byť zavolaný (závisí na on-error). Výsledok: zamknutá databáza na produkčnom serveri. Nastavte on-error: Continue na post-hook vždy, a monitorujte backup duration.
Disaster Recovery Playbook
Scenár: kompletné zlyhanie klastra
Situácia: produkčný klaster je nedostupný (hardware failure, chybný upgrade, data center incident). Máte posledný Velero backup 3 hodiny starý.
DR Timeline:
T+0: Incident — klaster nedostupný
T+15: Potvrdenie, že nie je recoverable, rozhodnutie o DR
T+30: Provisionovanie nového klastra (Terraform/Pulumi/CLI)
T+60: Inštalácia Velero s BSL odkazujúcim na existujúci S3
T+90: velero backup sync (stiahnutie metadata zo S3)
T+100: velero restore create --from-backup last-good-backup
T+120: Overenie: všetky pods Running, databázy zdravé, smoke testy
T+150: DNS prepnutie / loadbalancer update
T+180: Incident uzatvorený, RTO ~3 hodiny
Prečo samotný etcd snapshot nestačí pre DR
Predstavte si, že váš EKS klaster vybuchne. S etcd snapshotom:
- Potrebujete rovnakú verziu Kubernetes.
- Potrebujete rovnaké CA certifikáty (inak etcd snapshot nie je valídny).
- Nedokážete obnoviť do iného cloud providera.
- PV dáta nie sú v snapshotre.
S Velero + FSB:
- Nový klaster môže byť iná verzia K8s (v rozumných medziach).
- Iný cloud provider — OK.
- Iná storage class — OK s mapovaním.
- PV dáta sú v S3 a Velero ich obnoví.
Produkčný DR checklist
# 1. Nový klaster je ready, kubectl funguje
kubectl get nodes
# 2. Inštalácia Velero (rovnaká verzia ako v source klastri!)
helm install velero vmware-tanzu/velero \
--namespace velero \
--create-namespace \
-f velero-values.yaml # rovnaké values, iná BSL (ReadOnly)
# 3. Sync backupov zo S3
velero backup sync --all
# 4. Výber backupu
velero backup get
# Zvoľte posledný úspešný backup
# 5. Restore
velero restore create dr-restore-$(date +%Y%m%d-%H%M) \
--from-backup production-daily-20260417020000 \
--restore-volumes=true \
--wait
# 6. Overenie
velero restore describe dr-restore-20260417-1500
kubectl get pods -A | grep -v Running | grep -v Completed
# 7. Smoke testy — aplikácie závislé na dátach
kubectl exec -n production deploy/myapp -- /app/healthcheck.sh
Multi-cluster stratégia a GitOps integrácia
Multi-cluster backup topológia
Pre organizácie s viacerými klastrami (dev/staging/production alebo multi-region) odporúčam nasledovnú topológiu:
┌──────────────────────────────────────────────────────────────┐
│ S3 Object Storage (primary region) │
│ ├── /prod-eu-west/ ← production EU backups │
│ ├── /prod-us-east/ ← production US backups │
│ └── /staging/ ← staging backups │
└─────────────────────┬────────────────────────────────────────┘
│
┌─────────────────┼─────────────────┐
▼ ▼ ▼
Production EU Production US Staging
(Velero write) (Velero write) (Velero write)
│
┌───────▼───────┐
│ DR Klaster │ ← ReadOnly BSL na prod backups
│ (standby) │ pripravený na restore
└───────────────┘
GitOps — Backup a Schedule CRD v Git
Velero CRDs sú Kubernetes objekty — patria do Git:
# gitops/velero/schedules/production-daily.yaml
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: production-daily
namespace: velero
annotations:
# ArgoCD ignoruje status field
argocd.argoproj.io/compare-options: IgnoreExtraneous
spec:
schedule: "0 2 * * *"
template:
includedNamespaces:
- production
excludedResources:
- pods
- replicasets
- events
snapshotVolumes: true
defaultVolumesToFsBackup: false
storageLocation: default
ttl: 720h
ArgoCD Application pre Velero konfiguráciu:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: velero-config
namespace: argocd
spec:
project: infrastructure
source:
repoURL: https://git.internal/infra
targetRevision: main
path: gitops/velero
destination:
server: https://kubernetes.default.svc
namespace: velero
syncPolicy:
automated:
prune: false # NIKDY nemazať Schedule automaticky!
selfHeal: true
Dôležité: prune: false pre Velero config. Nechtiacé zmazanie Schedule CRD = zastavenie záloh. Zmeny vždy cez PR + review.
Alternatívy a kontext
Kasten K10
Kasten K10 (Veeam) je komerčné enterprise riešenie. Poskytuje GUI, policy engine, compliance reporting a deep integráciu s databázami (automatické pg_dump, MongoDB consistent backup). Cena zodpovedá enterprise segmentu.
Kedy K10 namiesto Velero:
- Potrebujete GUI pre non-technical staff (compliance officer, DB admin).
- Máte enterprise SLA požiadavky s vendorskou podporou.
- Deep application-aware backup bez manuálneho pisania hooks.
Stash (AppsCode)
Stash je Kubernetes-native backup operator s bohatým operator modelom. Silný pre databázové zálohy (vlastné "Function" CRDs pre PostgreSQL, MySQL, MongoDB). Open-source tier je limitovaný, enterprise features sú platené.
Trilio for Kubernetes
Trilio (TrilioVault) je ďalšia komerčná alternatíva s dôrazom na multi-tenancy a namespace-granular backup policies. Populárny v OpenShift prostredí.
Etcd backup
Surový etcd backup (etcdctl snapshot save) má svoje miesto ako doplnok k Velero, nie ako náhrada:
- Záloha etcd = rýchly recovery ak ste omylom zmazali klaster-scoped resource (ClusterRole, CRD definícia).
- Netýka sa PV dát.
- Odporúčam: etcd backup každú hodinu (lightweight, rýchly) + Velero backup raz/dvakrát denne.
Rozhodovacia tabuľka
| Nástroj | Open-source | GUI | DB-aware hooks | Cross-cluster | Cena |
|---|---|---|---|---|---|
| Velero | ✅ | ❌ | Manuálne | ✅ | Zadarmo |
| Kasten K10 | ❌ | ✅ | ✅ Automatické | ✅ | Enterprise |
| Stash | Čiastočne | ✅ | ✅ | ✅ | Freemium |
| Trilio | ❌ | ✅ | ✅ | ✅ | Enterprise |
| etcd backup | ✅ | ❌ | ❌ | ❌ | Zadarmo |
Pre väčšinu tímov je Velero správna voľba — bezplatný, CNCF projekt, aktívna komunita, funguje so všetkými cloud providermi. K10 zvážte ak máte budget a chcete menej konfigurácie.
Monitoring — metriky, alerty a dashboardy
Velero exponuje Prometheus metriky z /metrics endpointu na porte 8085. Pri Helm inštalácii s metrics.serviceMonitor.enabled=true sa automaticky vytvorí ServiceMonitor pre Prometheus Operator.
Kľúčové metriky
# Počet úspešných backupov (counter)
velero_backup_success_total{schedule="production-daily"}
# Počet neúspešných backupov
velero_backup_failure_total{schedule="production-daily"}
# Čas trvania backupu v sekundách (histogram)
velero_backup_duration_seconds_bucket{schedule="production-daily"}
# Posledný čas úspešného backupu (unix timestamp)
velero_backup_last_successful_timestamp{schedule="production-daily"}
# Stav BackupStorageLocation (1=available, 0=unavailable)
velero_backup_storage_location_info{storage_location="default",phase="Available"}
# Počet úspešných restore operácií
velero_restore_success_total
# Počet zlyhaných restore
velero_restore_failed_total
Alertmanager pravidlá
# prometheus/rules/velero.yaml
apiVersion: monitoring.coreos.com/v1
kind: PrometheusRule
metadata:
name: velero-alerts
namespace: monitoring
labels:
prometheus: kube-prometheus
role: alert-rules
spec:
groups:
- name: velero
interval: 5m
rules:
# Backup zlyhalo
- alert: VeleroBackupFailed
expr: |
increase(velero_backup_failure_total[1h]) > 0
for: 5m
labels:
severity: critical
annotations:
summary: "Velero backup zlyhal"
description: "Schedule {{ $labels.schedule }} — backup zlyhal v poslednej hodine."
# Backup sa nevykonal dlhšie ako 26 hodín (missed schedule)
- alert: VeleroBackupNotRecent
expr: |
(time() - velero_backup_last_successful_timestamp{schedule="production-daily"}) > 93600
for: 10m
labels:
severity: critical
annotations:
summary: "Velero backup je starší ako 26 hodín"
description: "Posledný úspešný backup bol pred {{ $value | humanizeDuration }}."
# BSL nedostupný
- alert: VeleroBackupStorageUnavailable
expr: |
velero_backup_storage_location_info{phase!="Available"} == 1
for: 5m
labels:
severity: warning
annotations:
summary: "Velero BackupStorageLocation nedostupný"
description: "BSL {{ $labels.storage_location }} nie je v stave Available."
# Dlhý backup — indikátor problémov
- alert: VeleroBackupTakingTooLong
expr: |
velero_backup_duration_seconds_sum / velero_backup_duration_seconds_count > 3600
for: 0m
labels:
severity: warning
annotations:
summary: "Velero backup trvá príliš dlho"
description: "Priemerný čas backupu je {{ $value | humanizeDuration }}."
Grafana dashboard
Importujte komunitný dashboard ID 15469 ("Velero") alebo 11055. Zobrazuje:
- Backup/restore success rate
- Backup duration trend
- BSL stav
- Počet záloh per schedule
# Overenie metrík
kubectl port-forward -n velero svc/velero 8085:8085
curl -s http://localhost:8085/metrics | grep velero_backup
Produkčné odporúčania
Retention a TTL stratégia
Nedávajte všetkým backupom rovnaké TTL. Odporúčaná stratégia:
Hourly config backup: TTL 48h (len K8s objekty, žiadne volumes)
Daily full backup: TTL 30d (objekty + volumes)
Weekly full backup: TTL 90d (manuálne spúšťané alebo Schedule)
Monthly archive: TTL 365d (pre compliance)
Immutable S3 buckety — Object Lock
Jeden z najväčších bezpečnostných rizík: útočník (alebo omylom oprávnený user) zmaže zálohy. Ochrana: S3 Object Lock s Compliance režimom.
# AWS CLI — aktivácia Object Lock na S3 buckete
aws s3api create-bucket \
--bucket velero-backups \
--region eu-west-1 \
--create-bucket-configuration LocationConstraint=eu-west-1
aws s3api put-object-lock-configuration \
--bucket velero-backups \
--object-lock-configuration '{
"ObjectLockEnabled": "Enabled",
"Rule": {
"DefaultRetention": {
"Mode": "COMPLIANCE",
"Days": 30
}
}
}'
Po aktivácii Object Lock nemôžete zmazať zálohy pred uplynutím retencie — ani root IAM user, ani útočník s admin prístupom. Toto je kritické pre ransomware odolnosť.
RBAC pre Velero
Velero server potrebuje rozsiahle oprávnenia (číta všetky resources v klastri). Obmedzte prístup ku Velero CRDs pre bežných používateľov:
# Prístup pre backup operátora (view backups, create manual backups)
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: velero-backup-operator
rules:
- apiGroups: ["velero.io"]
resources: ["backups", "restores", "schedules"]
verbs: ["get", "list", "watch", "create"]
- apiGroups: ["velero.io"]
resources: ["backups/status", "restores/status"]
verbs: ["get", "list", "watch"]
---
# Zakázať mazanie backupov pre všetkých okrem velero-admin
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: velero-backup-admin
rules:
- apiGroups: ["velero.io"]
resources: ["*"]
verbs: ["*"]
Testovanie restore — chaos-style
Najčastejšia chyba: zálohy existujú, ale nikto ich nikdy netestoval. Backup, ktorý ste netestovali, nie je backup — je to nádej.
Odporúčam:
- Týždenný automatický restore test do staging namespace:
#!/bin/bash
# restore-test.sh — spúšťať cron jobbom každú nedeľu
BACKUP=$(velero backup get \
--selector velero.io/schedule-name=production-daily \
-o json | jq -r '.items | sort_by(.metadata.creationTimestamp) | last | .metadata.name')
velero restore create test-restore-$(date +%Y%m%d) \
--from-backup "$BACKUP" \
--include-namespaces production \
--namespace-mappings production:production-dr-test \
--restore-volumes=false \
--wait
# Smoke test
kubectl wait -n production-dr-test deploy --all --for=condition=Available --timeout=300s
echo "Restore test OK: $BACKUP"
# Cleanup
kubectl delete namespace production-dr-test
Raz za kvartál: skutočný full DR test — nový klaster, kompletná obnova, smoke testy, meranie RTO.
Dokumentujte RTO/RPO na základe skutočných meraní, nie odhadov.
Veľkosť a performance
Pre veľké klastre s veľa PV:
- Paralelizácia:
velero backup create --parallel-files-upload 10(Kopia). - Exclude veľké dočasné dáta: Kafka logy, Elasticsearch indexes (majú vlastný backup mechanizmus) — Velero nie je správny nástroj pre multi-terabytové dáta cez FSB.
- Incremental backups: Kopia robí inkrementálne zálohy automaticky (hash-based dedup).
- BSL bandwidth: Uistite sa, že sieťové spojenie na S3 nie je úzkym hrdlom počas backup okna.
Zhrnutie
Velero je dnes de-facto štandard pre Kubernetes backup, pretože:
- Pokrýva K8s objekty aj volume dáta v jednom nástrojom.
- Funguje cross-cluster — kľúčové pre skutočný DR.
- Integruje sa s GitOps (CRD-based konfigurácia).
- Je cloud-agnostic — AWS, GCP, Azure, on-premise MinIO.
- Je zadarmo a aktívne vyvíjaný pod CNCF.
Najdôležitejšie pravidlo: backup bez testovaného restore je zbytočný. Nastavte automatické restore testy do staging, merajte skutočné RTO, a aspoň raz za kvartál urobte full DR cvičenie na novom klastri. Iba tak budete vedieť, že váš disaster recovery plán skutočne funguje.