м. Київ, вул. Кирилівська 102

15 серпня 2026 р.

Резервне копіювання Kubernetes через Velero

Резервне копіювання Kubernetes через Velero

Резервна копія Kubernetes — це не архів каталогу з YAML-файлами. Стан застосунку розподілений між об’єктами API, persistent volumes, CustomResourceDefinition, Secret, ConfigMap та зовнішніми сервісами. Якщо зберегти лише маніфести, після аварії можна відтворити Deployment, але втратити дані PVC. Якщо покладатися тільки на snapshot диска, не буде гарантованої копії Namespace, RBAC, Service та конфігурації контролерів. Velero об’єднує ці частини в керований процес backup і restore.

У цій інструкції налаштуємо Velero 1.18 для кластера Kubernetes, підключимо S3 як незалежне сховище, увімкнемо node-agent для копіювання файлових даних, створимо ручну й регулярну копії та перевіримо відновлення в окремий namespace. Приклад використовує AWS S3, але та сама логіка працює із сумісним object storage та офіційним плагіном відповідного провайдера.

Перед змінами зафіксуйте цільові RPO і RTO. RPO визначає, скільки даних допустимо втратити між двома копіями, а RTO — скільки часу є на повернення сервісу. Саме ці значення задають частоту schedule, retention, місткість bucket і регулярність навчальних відновлень. Якщо кластер підтримує критичні сервіси, резервування варто включити до загального процесу DevOps-супроводу інфраструктури, а не залишати одноразовою командою адміністратора.

Що саме копіює Velero і яку схему обрати

Velero читає ресурси через Kubernetes API та зберігає їхній опис у BackupStorageLocation. Це дає змогу повернути Namespace, Deployment, StatefulSet, Service, Ingress, Secret, ConfigMap, RBAC та custom resources. Самі дані томів обробляються окремим механізмом: snapshot провайдера, CSI Snapshot Data Movement або File System Backup через node-agent.

Snapshot швидкий і зручний для великих дисків, але часто залишається в тому самому обліковому записі та регіоні. Він не завжди захищає від видалення cloud account або помилки політики доступу. File System Backup читає змонтовану файлову систему й передає дані в object storage через Kopia. Така копія повільніша, зате її можна тримати окремо від основного storage. Для важливих даних доречно поєднати cloud snapshots для швидкого локального restore з незалежною копією в bucket.

Velero не робить застосунок автоматично консистентним. Для PostgreSQL, MySQL, Elasticsearch та інших систем перед backup потрібен application-aware крок: дамп, flush, freeze або hook, узгоджений із документацією конкретного продукту. Crash-consistent копія диска може відновитися технічно, але база після запуску все одно потребуватиме recovery. Не забудьте також окремо зберігати декларативні manifest-и й Helm values у Git: backup доповнює керований CI/CD-процес, а не замінює його.

До початку перевірте поточний context, доступ до cluster-wide ресурсів, наявність StorageClass і версію Kubernetes:

bash
kubectl config current-context
kubectl auth can-i '*' '*' --all-namespaces
kubectl get nodes -o wide
kubectl get storageclass

Bucket створіть в іншому failure domain, увімкніть шифрування, versioning, lifecycle та заборону публічного доступу. Обліковому запису Velero надайте лише потрібні права до окремого bucket або prefix і до snapshot API. Ключі не вставляйте в shell history або manifest-и репозиторію.

Встановлення Velero та підключення S3

Для Linux x86_64 встановіть зафіксовану версію CLI. Перед копіюванням binary за потреби звірте checksum із release assets. Якщо робоча станція має іншу архітектуру, завантажте відповідний архів.

bash
export VELERO_VERSION="v1.18.2"
curl -fLO "https://github.com/vmware-tanzu/velero/releases/download/${VELERO_VERSION}/velero-${VELERO_VERSION}-linux-amd64.tar.gz"
tar -xzf "velero-${VELERO_VERSION}-linux-amd64.tar.gz"
sudo install -m 0755 "velero-${VELERO_VERSION}-linux-amd64/velero" /usr/local/bin/velero
velero version --client-only

Створіть локальний credentials-файл поза Git. Значення нижче є лише формою файлу; використайте окремий IAM principal або workload identity. Після встановлення видаліть локальну копію секрету безпечним способом відповідно до політики робочої станції.

bash
umask 077
mkdir -p "$PWD/.velero-private"

printf '%s\n' \
  '[default]' \
  'aws_access_key_id=REPLACE_ME' \
  'aws_secret_access_key=REPLACE_ME' \
  > "$PWD/.velero-private/credentials-velero"

Версія AWS plugin `v1.14.x` сумісна з Velero `v1.18.x`. Команда нижче встановлює server, BackupStorageLocation, snapshot location і node-agent. Прапорець `--default-volumes-to-fs-backup` задає файлову копію томів за замовчуванням; якщо потрібні тільки CSI або EBS snapshots, приберіть його та налаштуйте політику томів свідомо.

bash
export BUCKET="company-k8s-backups"
export REGION="eu-central-1"

velero install \
  --provider aws \
  --plugins velero/velero-plugin-for-aws:v1.14.0 \
  --bucket "$BUCKET" \
  --backup-location-config "region=$REGION" \
  --snapshot-location-config "region=$REGION" \
  --secret-file "$PWD/.velero-private/credentials-velero" \
  --use-node-agent \
  --default-volumes-to-fs-backup \
  --wait

Для MinIO або іншого S3-compatible endpoint до backup location зазвичай додають `s3ForcePathStyle=true` і `s3Url=https://...`, але точний набір параметрів залежить від провайдера та TLS. Якщо endpoint підписаний приватним CA, передайте CA bundle штатним параметром Velero, а не вимикайте перевірку сертифіката.

Переконайтеся, що Deployment, DaemonSet і location готові:

bash
kubectl -n velero get deploy,daemonset,pods
velero backup-location get
velero snapshot-location get
kubectl -n velero logs deploy/velero --tail=100

Статус BackupStorageLocation має бути `Available`, а pod node-agent — працювати на кожному Linux node, де розміщені потрібні volumes. Для block volumes або окремих платформ node-agent може потребувати privileged mode; застосовуйте його лише після перевірки вимог драйвера й політик безпеки.

Створення першої резервної копії

Спочатку зробіть контрольний backup одного namespace, а не всього кластера. Так простіше перевірити selectors, volumes і час виконання. У прикладі namespace називається `demo`, а TTL становить 168 годин.

bash
velero backup create demo-manual-$(date +%Y%m%d-%H%M) \
  --include-namespaces demo \
  --default-volumes-to-fs-backup \
  --ttl 168h0m0s \
  --wait

velero backup get

Збережіть фактичне ім’я та перегляньте детальний результат. Статус `Completed` ще не означає, що всі томи скопійовані: важливі поля — warnings, errors, PodVolumeBackups і перелік включених ресурсів.

bash
export BACKUP_NAME="REPLACE_WITH_BACKUP_NAME"

velero backup describe "$BACKUP_NAME" --details
velero backup logs "$BACKUP_NAME"
kubectl -n velero get podvolumebackups
kubectl -n velero get backuprepositories

Перевірте об’єкти безпосередньо в bucket: для кожного backup мають існувати metadata та архів ресурсів, а для FSB — repository з даними Kopia. Контроль лише через CLI кластера недостатній, бо помилкова bucket policy або lifecycle може видалити фактичні дані пізніше.

Для повного cluster backup команда може не містити `--include-namespaces`, але включати все без аналізу небезпечно. Виключіть ephemeral namespace, великі кеші та ресурси, які відтворює інший control plane. Для застосунків із базами даних додайте перевірені hooks або створюйте логічний dump у persistent volume перед запуском Velero.

Розклад, retention і контроль результатів

Регулярну копію створюйте через Schedule. Cron у Velero інтерпретується в UTC, тому зафіксуйте це в runbook. Приклад запускається щодня о 02:30 UTC, охоплює namespace `demo`, використовує FSB і зберігає кожну копію 30 днів.

bash
velero schedule create demo-daily \
  --schedule="30 2 * * *" \
  --include-namespaces demo \
  --default-volumes-to-fs-backup \
  --ttl 720h0m0s

velero schedule get
velero schedule describe demo-daily

Одразу створіть backup із нового schedule, щоб не чекати наступного cron-вікна:

bash
velero backup create --from-schedule demo-daily --wait
velero backup get

Retention має покривати не тільки оперативне відновлення. Практична схема може містити щоденні копії за 14–30 днів, тижневі за кілька місяців і довший архів за регуляторною потребою. Налаштуйте object lock або інший immutable-механізм там, де це підтримується, але спочатку перевірте взаємодію з видаленням backup і repository maintenance. Невірно заданий lock здатен заблокувати штатне очищення й непомітно збільшувати витрати.

Створіть моніторинг для failed і partially failed backup, віку останньої успішної копії, тривалості, вільного місця та помилок repository maintenance. Графік без сповіщення не захищає від тижнів невдалих запусків. Стан кластера зручно зіставляти з уже налаштованим моніторингом Kubernetes через Prometheus та Grafana.

Щонайменше раз на місяць перевіряйте список копій, доступність location і журнали:

bash
velero backup-location get
velero backup get
kubectl -n velero get backuprepositories
kubectl -n velero logs deploy/velero --since=24h

Тестове відновлення без ризику для робочого namespace

Backup вважається придатним тільки після restore test. Не починайте перевірку з відновлення поверх робочого namespace: наявні ресурси можуть бути пропущені або змінені не так, як очікується. Безпечніше зробити namespace mapping `demo:demo-restore` у тому самому тестовому кластері або, ще краще, у чистому ізольованому кластері.

bash
export BACKUP_NAME="REPLACE_WITH_COMPLETED_BACKUP"
export RESTORE_NAME="demo-restore-$(date +%Y%m%d-%H%M)"

velero restore create "$RESTORE_NAME" \
  --from-backup "$BACKUP_NAME" \
  --namespace-mappings demo:demo-restore \
  --wait

velero restore describe "$RESTORE_NAME" --details
velero restore logs "$RESTORE_NAME"
kubectl -n demo-restore get all,pvc

Після появи pod-ів перевірте не тільки Kubernetes status. Виконайте health check сервісу, прочитайте контрольний запис із бази, порівняйте кількість об’єктів, переконайтеся в доступності змонтованих файлів і проведіть короткий функціональний тест. Для StatefulSet перевірте порядок старту та прив’язку PVC. Для operators переконайтеся, що потрібні CRD і controller уже доступні в цільовому кластері.

Якщо restore виконується після повної втрати кластера, спочатку підготуйте сумісну версію Kubernetes, CSI driver, StorageClass, DNS, identity та Velero з доступом до того самого bucket. Секрети доступу до backup не повинні існувати лише всередині втраченого кластера. Зберігайте recovery procedure й break-glass credentials у захищеному зовнішньому контурі.

Після тесту видаліть ізольовані ресурси лише коли зібрані результати перевірки:

bash
kubectl delete namespace demo-restore
velero restore delete "$RESTORE_NAME" --confirm

Видалення об’єкта Restore не видаляє backup. Видаляти саму копію слід командою Velero, щоб контролер коректно обробив пов’язані дані й snapshots, а не ручним стиранням випадкових ключів у bucket.

Типові помилки та висновок

Найпоширеніша помилка — прирівняти `Completed` до перевіреної можливості відновлення. Backup може містити Kubernetes resources, але не дані PVC; може завершитися з warnings; може бути недоступним через втрачений ключ; або відновлюватися довше за цільовий RTO. Потрібні автоматичний контроль результату й регулярний restore drill.

Друга помилка — зберігати копії в тому самому failure domain без versioning, immutability та окремого доступу. Компрометація адміністративного облікового запису тоді знищує і workload, і backup. Третя — не врахувати application consistency. Snapshot активної бази не дорівнює перевіреному логічному dump або координованому backup hook.

Також часто забувають перевірити CustomResourceDefinition, cluster-scoped ресурси, StorageClass і сумісність CSI. Restore в namespace з наявними об’єктами створює хибне відчуття успіху, а надто широкий cluster backup переносить непотрібні токени, leases, events і тимчасові ресурси. Include та exclude правила мають бути задокументовані й протестовані.

Робочий контур Velero складається з п’яти частин: незалежний object storage; чітко обраний спосіб копіювання volumes; schedule відповідно до RPO; моніторинг кожного запуску; регулярне відновлення в ізольоване середовище. Додайте до цього Git як джерело manifest-ів, окремі дампи для stateful-систем і захищений disaster recovery runbook.

Після першого успішного тесту виміряйте фактичні RPO та RTO, зафіксуйте відповідального, дату наступного drill і процедуру ротації credentials. Лише відтворюваний процес із доказом читання даних після restore можна вважати резервним копіюванням, а не набором файлів у bucket.

📞