🟡 Intermediate

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:

  1. 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).
  2. 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ý.
  3. 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č.
  4. 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.
  5. 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 Backup CRD, spúšťa backup process, uploaduje do object storage.
  • Restore Controller — sleduje Restore CRD, sťahuje backup z object storage, aplikuje objekty.
  • Schedule Controller — sleduje Schedule CRD, v správnom čase vytvára Backup objekty.
  • 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:

  1. Nový klaster má prístup k rovnakému BackupStorageLocation (S3 bucket).
  2. Velero je nainštalovaný v novom klastri s rovnakou verziou.
  3. 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:

  1. Potrebujete rovnakú verziu Kubernetes.
  2. Potrebujete rovnaké CA certifikáty (inak etcd snapshot nie je valídny).
  3. Nedokážete obnoviť do iného cloud providera.
  4. PV dáta nie sú v snapshotre.

S Velero + FSB:

  1. Nový klaster môže byť iná verzia K8s (v rozumných medziach).
  2. Iný cloud provider — OK.
  3. Iná storage class — OK s mapovaním.
  4. 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:

  1. 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
  1. Raz za kvartál: skutočný full DR test — nový klaster, kompletná obnova, smoke testy, meranie RTO.

  2. 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.


Ďalšie čítanie