Резервное копирование и восстановление

Как создавать резервные копии ресурсов VMInstance и VMDisk и управлять ими с помощью BackupJob и Plan.

Стратегии резервного копирования кластера и BackupClass настраиваются администраторами кластера. Если для вашего тенанта ещё нет BackupClass, попросите администратора выполнить руководство Velero Backup Configuration, чтобы настроить хранилище, стратегии и BackupClass.

В этом руководстве описывается резервное копирование и восстановление ресурсов VMInstance и VMDisk от лица пользователя-тенанта: запуск разовых и плановых резервных копий, проверка их статуса и восстановление из резервной копии с помощью RestoreJob.

Cozystack использует Velero под капотом для хранения резервных копий и снимков (snapshot) томов.

Предварительные требования

  • Дополнение Velero включено для вашего кластера (администратором).
  • Для пространства имён вашего тенанта доступен как минимум один BackupClass (предоставлен администратором).
  • kubectl и kubeconfig для кластера, резервную копию которого вы создаёте.

Список доступных BackupClass

BackupClass определяют, где и как хранятся резервные копии. Вы можете использовать только те, что созданы администраторами.

kubectl get backupclasses

Пример вывода:

NAME     AGE
velero   14m

Используйте имя BackupClass при создании BackupJob или Plan.

Резервное копирование VMInstance

Резервная копия VMInstance захватывает конфигурацию ВМ и все подключённые тома VMDisk.

Разовая резервная копия

Используйте BackupJob, когда нужно выполнить резервное копирование один раз — например, перед рискованным изменением.

apiVersion: backups.cozystack.io/v1alpha1
kind: BackupJob
metadata:
  name: my-vm-backup
  namespace: tenant-user
spec:
  applicationRef:
    apiGroup: apps.cozystack.io
    kind: VMInstance
    name: my-vm
  backupClassName: velero

Примените его и следите за статусом:

kubectl apply -f backupjob.yaml
kubectl get backupjobs -n tenant-user
kubectl describe backupjob my-vm-backup -n tenant-user

Когда BackupJob завершается успешно, он создаёт объект Backup с тем же именем (my-vm-backup). Это имя вы будете использовать при восстановлении.

Плановая резервная копия

Используйте Plan, чтобы выполнять резервное копирование по расписанию.

apiVersion: backups.cozystack.io/v1alpha1
kind: Plan
metadata:
  name: my-vm-daily
  namespace: tenant-user
spec:
  applicationRef:
    apiGroup: apps.cozystack.io
    kind: VMInstance
    name: my-vm
  backupClassName: velero
  schedule:
    cron: "0 2 * * *"   # Каждый день в 02:00

Примените его и проверьте:

kubectl apply -f plan.yaml
kubectl get plans -n tenant-user
kubectl describe plan my-vm-daily -n tenant-user

Каждый плановый запуск создаёт BackupJob (а при успехе — объект Backup), названный по имени Plan с суффиксом-временной меткой.

Резервное копирование VMDisk

Вы можете создать резервную копию VMDisk независимо — например, чтобы захватить конкретный диск без конфигурации ВМ.

apiVersion: backups.cozystack.io/v1alpha1
kind: BackupJob
metadata:
  name: my-disk-backup
  namespace: tenant-user
spec:
  applicationRef:
    apiGroup: apps.cozystack.io
    kind: VMDisk
    name: my-disk
  backupClassName: velero

Примените и проверьте статус:

kubectl apply -f backupjob-disk.yaml
kubectl get backupjobs -n tenant-user
kubectl describe backupjob my-disk-backup -n tenant-user

Проверка статуса резервного копирования

Список всех BackupJob в пространстве имён:

kubectl get backupjobs -n tenant-user

Опишите конкретный BackupJob, чтобы увидеть фазу и любые ошибки:

kubectl describe backupjob my-vm-backup -n tenant-user

Список созданных объектов Backup (по одному на каждый завершённый BackupJob):

kubectl get backups -n tenant-user

Список BackupJob, созданных некоторым Plan:

kubectl get backupjobs -n tenant-user -l backups.cozystack.io/plan=my-vm-daily

Восстановление VMInstance

Вы можете восстановить VMInstance как на месте (откат работающей ВМ), так и с нуля (после того как ВМ и её диски были удалены). Резервная копия VMInstance включает все подключённые тома VMDisk и их данные.

Сначала найдите объект Backup, из которого хотите восстановиться:

kubectl get backups -n tenant-user

Пример вывода:

NAME            AGE
my-vm-backup    2h

Создайте RestoreJob со ссылкой на этот Backup:

apiVersion: backups.cozystack.io/v1alpha1
kind: RestoreJob
metadata:
  name: restore-my-vm
  namespace: tenant-user
spec:
  backupRef:
    name: my-vm-backup

Примените его и проверьте ход выполнения:

kubectl apply -f restorejob.yaml
kubectl get restorejobs -n tenant-user
kubectl describe restorejob restore-my-vm -n tenant-user

RestoreJob проходит через PendingRunningSucceeded (или Failed). При успехе VMInstance и её VMDisk восстанавливаются до состояния, захваченного в резервной копии.

Проверка после восстановления

После успешного завершения RestoreJob убедитесь, что ВМ действительно работает:

# Проверьте, что VMInstance и VMDisk находятся в состоянии Ready
kubectl get vminstances,vmdisks -n tenant-user

# Проверьте, что VirtualMachineInstance запущен (а не только CR)
kubectl get vmi -n tenant-user

# Проверьте доступ по SSH
virtctl ssh -i ~/.ssh/my-key -l ubuntu vmi/vm-instance-my-vm -n tenant-user -c "ip a"

После того как вы убедились, что восстановление прошло успешно и ВМ работает корректно, вы можете удалить PVC *-orig-*, содержащие исходные данные, чтобы освободить хранилище:

# Список PVC -orig
kubectl get pvc -n tenant-user | grep -- '-orig-'

# Удалите их, когда они больше не нужны (замените на фактические имена PVC из списка выше)
kubectl delete pvc -n tenant-user <name>-orig-<hash>

Восстановление VMDisk на месте

Чтобы восстановить только VMDisk, не затрагивая конфигурацию ВМ.

kubectl get backups -n tenant-user
apiVersion: backups.cozystack.io/v1alpha1
kind: RestoreJob
metadata:
  name: restore-my-disk
  namespace: tenant-user
spec:
  backupRef:
    name: my-disk-backup

Примените и проверьте:

kubectl apply -f restorejob-disk.yaml
kubectl get restorejobs -n tenant-user
kubectl describe restorejob restore-my-disk -n tenant-user

Устранение неполадок

Если BackupJob или RestoreJob завершается в фазе Failed, проверьте поле message в его статусе:

kubectl get backupjob my-vm-backup -n tenant-user -o jsonpath='{.status.message}'
kubectl get restorejob restore-my-vm -n tenant-user -o jsonpath='{.status.message}'

Для получения деталей более низкого уровня проверьте логи Velero в управляющем кластере:

kubectl logs -n cozy-velero -l app.kubernetes.io/name=velero --tail=100

Исправление доступа по SSH (несоответствие MAC-адреса cloud-init после восстановления)

После восстановления VMInstance гостевая ОС может потерять сетевое соединение. Известно, что это происходит на Ubuntu Server, где cloud-init генерирует конфигурацию netplan, привязанную к MAC-адресу старой ВМ. После восстановления ВМ получает новый виртуальный NIC с другим MAC-адресом, но в гостевой ОС всё ещё остаётся старая конфигурация netplan, привязанная к предыдущему MAC — поэтому сетевой интерфейс так и не настраивается. Другие операционные системы, которые не привязывают сетевую конфигурацию к конкретному MAC-адресу, могут не быть подвержены этой проблеме.

Чтобы это исправить, обновите поле cloudInitSeed в спецификации VMInstance и перезапустите ВМ. Изменение seed генерирует новый SMBIOS UUID, из-за чего cloud-init воспринимает ВМ как новый экземпляр и заново выполняет сетевую настройку с правильным MAC-адресом.

# Задайте новое значение cloudInitSeed (любая строка, отличная от текущей)
kubectl patch vminstance my-vm -n tenant-user --type merge \
  -p '{"spec":{"cloudInitSeed":"reseed1"}}'

# Дождитесь согласования (reconcile) VMInstance
kubectl wait vminstance/my-vm -n tenant-user --for=condition=Ready --timeout=180s

# Перезапустите ВМ, чтобы новый seed вступил в силу
virtctl restart vm-instance-my-vm -n tenant-user

После перезапуска убедитесь, что у ВМ есть сетевое соединение:

# Проверьте, что VMI запущен
kubectl get vmi -n tenant-user

# Проверьте доступ по SSH
virtctl ssh -i ~/.ssh/my-key -l ubuntu vmi/vm-instance-my-vm -n tenant-user -c "ip a"