Перейти к содержимому
Главная страница » Восстановление сломанной Proxmox‑ВМ через примонтированный диск

Восстановление сломанной Proxmox‑ВМ через примонтированный диск

Сценарий: Linux‑ВМ (обычно Ubuntu/Debian) в Proxmox перестала пускать в систему — на консоли через VNC видно ошибки вида:

  • [FAILED] Failed to start D-Bus System Message Bus
  • ошибки PAM при логине (PAM Failure, abortingError in service module)

По SSH и сети попасть на гостевую систему нельзя, но на той же ноде Proxmox есть рабочая ВМ (rescue‑ВМ), куда можно зайти по SSH.

Ниже — пошаговая инструкция, как:

  1. Полностью восстановить систему, примонтировав диск сломанной ВМ к рабочей.
  2. Если это не нужно — просто спасти Docker‑контейнеры и их данные, а старую ВМ оставить/удалить.

Примеры команд:

  • сломанная ВМ: 7000
  • рабочая / rescue‑ВМ: 8000
  • нода Proxmox: pve
  • хранилище LVM: local-lvm

Подставьте свои ID и storage.

Бэкап и поиск диска ВМ

На хосте Proxmox:

# 1. Сделать бэкап ВМ (ОБЯЗАТЕЛЬНО)
vzdump 7000 --storage local --mode snapshot

# 2. Найти диск ВМ
qm config 7000 | grep -E 'scsi|virtio|sata'

Типичный вывод:

bootdisk: scsi0
scsi0: local-lvm:vm-7000-disk-0,size=100G

Запоминаем local-lvm:vm-7000-disk-0.

Отцепить диск от 7000 и прицепить к 8000

На Proxmox‑хосте:

# Остановить сломанную ВМ
qm stop 7000

# Отвязать диск от 7000 (НЕ удаляет данные на storage)
qm set 7000 --delete scsi0

# Прицепить диск к рабочей ВМ 8000 как scsi1
qm set 8000 --scsi1 local-lvm:vm-7000-disk-0

# Запустить рабочую ВМ
qm start 8000

Аналог через веб‑интерфейс:

  • для 7000: Hardware → Disk → Detach (НЕ Remove);
  • для 8000: Hardware → Add → Existing disk → vm-7000-disk-0 (например как scsi1).

Смонтировать диск сломанной ВМ в рабочей

Внутри ВМ 8000 (по SSH):

lsblk

Пример:

sda    ... 22G
├─sda1 ... /
└─sda15... /boot/efi
sdb    ... 98G
├─sdb1 ... 82G
├─sdb14
└─sdb15

Чаще всего корневая ФС сломанной ВМ — это sdb1:

mkdir -p /mnt/vm7000
mount /dev/sdb1 /mnt/vm7000

ls /mnt/vm7000
# должны увидеть стандартные каталоги: bin, etc, var, usr, home, ...

Если вместо обычных разделов там LVM (видны LVM2_membervg-.../lv-...), последовательность:

pvscan
vgscan
vgchange -ay                   # активировать VG
lvdisplay                      # найти LV с корнем, например /dev/vgname/root
mount /dev/vgname/root /mnt/vm7000

Вариант А: /etc живой — chroot и переустановка dbus/systemd/login

Если ls /mnt/vm7000/etc показывает нормальное дерево (passwdaptpam.d, куча файлов), /etc не разрушен. Тогда достаточно chroot и переустановки критичных служб.

В рабочей ВМ (8000):

mount --bind /dev  /mnt/vm7000/dev
mount --bind /proc /mnt/vm7000/proc
mount --bind /sys  /mnt/vm7000/sys

chroot /mnt/vm7000 /bin/bash

Внутри chroot:

mount -o remount,rw /
df -h

apt update
apt install --reinstall dbus systemd-sysv login

# по желанию обновить пароль root
passwd root
exit

Снаружи (в 8000):

umount /mnt/vm7000/dev
umount /mnt/vm7000/proc
umount /mnt/vm7000/sys
umount /mnt/vm7000

После этого можно возвращать диск в 7000 (см. 1.6).

Вариант Б: /etc почти пустой — восстанавливаем из рабочей ВМ

Типичная ситуация после повреждения диска: в /mnt/vm7000/etc только systemdlvm и пара каталогов, а aptpasswdpam.d и т.д. отсутствуют.

В рабочей ВМ (не в chroot):

ls -la /mnt/vm7000/etc
# видим 2–4 каталога, почти ничего нет

Сначала делаем бэкап того, что есть:

mkdir -p /mnt/vm7000/etc-broken-backup
cp -a /mnt/vm7000/etc/* /mnt/vm7000/etc-broken-backup/ 2>/dev/null || true

Теперь копируем из рабочей ВМ базовый набор конфигов:

# APT
cp -a /etc/apt /mnt/vm7000/etc/

# Пользователи и группы (root и юзеры будут как на рабочей ВМ)
cp /etc/passwd  /mnt/vm7000/etc/passwd
cp /etc/shadow  /mnt/vm7000/etc/shadow
cp /etc/group   /mnt/vm7000/etc/group
cp /etc/gshadow /mnt/vm7000/etc/gshadow

# NSS и PAM
cp /etc/nsswitch.conf /mnt/vm7000/etc/nsswitch.conf
cp -a /etc/pam.d /mnt/vm7000/etc/pam.d

# hosts и DNS
cp /etc/hosts       /mnt/vm7000/etc/hosts
cp /etc/resolv.conf /mnt/vm7000/etc/resolv.conf

Проверяем:

ls -la /mnt/vm7000/etc | head
# теперь видим apt/, passwd, shadow, pam.d, hosts и т.д.

Дальше — полноценный chroot и переустановка сервисов:

mount --bind /dev  /mnt/vm7000/dev
mount --bind /proc /mnt/vm7000/proc
mount --bind /sys  /mnt/vm7000/sys

chroot /mnt/vm7000 /bin/bash

Внутри:

mount -o remount,rw /
df -h

apt update
apt install --reinstall dbus systemd-sysv login

passwd root    # задать новый понятный пароль
exit

Снаружи:

umount /mnt/vm7000/dev
umount /mnt/vm7000/proc
umount /mnt/vm7000/sys
umount /mnt/vm7000

Важно: после копирования /etc/passwd и /etc/shadow локальные пользователи/пароли на восстановленной ВМ будут такими же, как на рабочей ВМ. После успешного логина имеет смысл привести их в порядок.

Вернуть диск обратно в исходную ВМ

На Proxmox‑хосте:

# Остановить рабочую ВМ, чтобы безопасно убрать диск
qm stop 8000
qm set 8000 --delete scsi1
qm start 8000

# Вернуть диск в 7000
qm set 7000 --scsi0 local-lvm:vm-7000-disk-0

# Запустить восстановленную ВМ
qm start 7000

Дальше подключаемся к 7000 по VNC и логинимся под root с паролем, который задавали в chroot. Проверяем:

df -h
systemctl status dbus
systemctl status ssh
ip a

Если ошибки Failed to start D-Bus System Message Bus и PAM Failure исчезли, а логин и сеть работают — ВМ спасена.

Восстановление только Docker‑контейнеров и данных

Бывает, что сам гостевой Linux уже не важен: проще поднять новую чистую ВМ и просто «переехать» туда со всеми контейнерами и томами Docker.

Идея:

  • смонтировать диск старой ВМ в новую;
  • скопировать /var/lib/docker и нужные bind‑mount‑каталоги;
  • запустить Docker на новой ВМ — контейнеры и данные окажутся на месте.

Подключить диск старой ВМ к новой Docker‑ВМ

На Proxmox‑хосте:

qm stop 7000
qm set 7000 --delete scsi0

qm set 8000 --scsi1 local-lvm:vm-7000-disk-0
qm start 8000

Смонтировать диск и проверить наличие Docker‑данных

Внутри новой Docker‑ВМ (8000):

lsblk        # ищем новый диск, чаще всего /dev/sdb

mkdir -p /mnt/vm7000
mount /dev/sdb1 /mnt/vm7000

ls /mnt/vm7000/var/lib/docker
# должны увидеть: containers, overlay2, volumes, image, tmp, ...

Остановить Docker на новой ВМ и сделать бэкап его текущих данных

systemctl stop docker docker.socket containerd 2>/dev/null || true

# бэкап существующего /var/lib/docker
mv /var/lib/docker /var/lib/docker.empty-$(date +%F-%H%M) 2>/dev/null || true
mkdir -p /var/lib/docker

Скопировать Docker‑данные со старой ВМ

rsync -a /mnt/vm7000/var/lib/docker/ /var/lib/docker/

(слэш в конце пути важен — копируется содержимое, а не вложенный каталог docker.)

Перенести bind‑mount‑каталоги (если были)

Если в docker run / docker compose использовались bind‑mount’ы (например /home/es_index/data/opt/.../srv/...), их тоже нужно перенести.

Посмотреть монтирования конкретного контейнера:

docker inspect <container_name> --format '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{ printf "\n" }}{{ end }}'

Пример:

/home/es_index/data -> /usr/share/elasticsearch/data

Тогда копируем данные с диска старой ВМ:

rsync -a /mnt/vm7000/home/es_index/ /home/es_index/

(Аналогично для других путей /opt/.../srv/... и т.п.)

Запустить Docker и проверить контейнеры

systemctl start docker
systemctl status docker --no-pager

docker ps
docker ps -a
docker volume ls

Если всё сделано правильно, вы увидите те же контейнеры и тома, что и на старой ВМ.

Частые проблемы с Elasticsearch в контейнере

Не хватает памяти (Java heap / mmap failed)

Лог:

There is insufficient memory for the Java Runtime Environment to continue.
Native memory allocation (mmap) failed to map 2147483648 bytes.

Решения:

  • увеличить RAM ВМ и/или лимит памяти контейнера;
  • уменьшить heap через ES_JAVA_OPTS:
docker stop es_port5418
docker rm es_port5418

docker run -d \
  --name es_port5418 \
  -e ES_JAVA_OPTS="-Xms1g -Xmx1g" \
  -e discovery.type=single-node \
  -p 9200:9200 \
  -v /home/es_index/data:/usr/share/elasticsearch/data \
  docker.elastic.co/elasticsearch/elasticsearch:8.15.0

Ошибка failed to obtain node locks / проблемы с node.lock

Лог:

failed to obtain node locks, tried [/usr/share/elasticsearch/data]
maybe these locations are not writable or multiple nodes were started on the same data path

Шаги:

  1. Смотрим, куда смонтированы данные ES:docker inspect es_port5418 --format '{{ range .Mounts }}{{ .Source }} -> {{ .Destination }}{{ printf "\n" }}{{ end }}' # пример: /home/es_index/data -> /usr/share/elasticsearch/data
  2. Чиним права на Source‑каталог:chown -R 1000:0 /home/es_index/data chmod -R u+rwX,g+rX,o-rwx /home/es_index/data docker restart es_port5418 docker logs -f es_port5418

Пользователь Elasticsearch в образе — uid 1000, поэтому владельцем data‑директории на хосте должен быть именно он.

Включить автозапуск контейнеров после ребута

Чтобы контейнеры автоматически стартовали после перезагрузки ВМ:

docker update --restart=always es_port5418 RabbitMQ paradedb portainer

Или в docker-compose.yml:

services:
  elasticsearch:
    restart: always
  rabbitmq:
    restart: always
  # ...

Безопасно отцепить диск старой ВМ от новой

Когда убедились, что Docker на новой ВМ работает без зависимости от старого диска, его можно отцепить.

Внутри 8000:

umount /mnt/vm7000

На Proxmox‑хосте:

qm stop 8000
qm set 8000 --delete scsi1
qm start 8000

Старая ВМ 7000 и её диск больше не участвуют в проде. Их можно:

  • либо оставить как холодный бэкап;
  • либо, после ещё одного vzdump‑бэкапа, полностью удалить.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *