Каждый, кому понадобилось хотя бы раз в жизни перенести OpenVZ контейнер на сервер с полноценной виртуализацией KVM, сталкивался с некоторыми проблемами:
- Большинство информации банально устарело и было актуально для уже давно прошедших EOL цикл ОС
- По разным ОС всегда предоставляется различная информация, и никогда не рассматриваются возможные ошибки при миграции
- Иногда приходится иметь дело с конфигурациями, которые то и дело не хотят работать после миграции
Когда переносишь 1 сервер всегда можно что-то исправить на ходу, а когда переносишь целый кластер?
В этой статье я постараюсь рассказать, как правильно мигрировать OpenVZ контейнер на KVM с минимальным даунтаймом и быстрым решением всех проблем.
Небольшой ликбез: что такое OpenVZ и что такое KVM?
Не будем углубляться в терминологию, а скажем в общих чертах:
OpenVZ — виртуализация на уровне операционной системы, развернуть можно даже на микроволновке, так как нет необходимости в наличии инструкций CPU и технологий виртуализации на хост-машине.
KVM — полноценная виртуализация, использующая всю мощь CPU и способная виртуализировать что угодно, как угодно, резать вдоль и поперек.
Вопреки расхожему мнению, что в среде хостинг-провайдеров OpenVZ оверселлится, а KVM нет — к счастью для последних, KVM нынче оверселлится ничуть не хуже своего собрата.
Что будем переносить?
В качестве подопытных для переноса пришлось использовать весь лес операционных систем, которые доступны на OpenVZ: CentOS (6 и 7 версии), Ubuntu (14, 16 и 18 LTS), Debian 7.
Предполагалось, что на бОльшей части контейнеров OpenVZ уже крутится какой-никакой LAMP, а у некоторых даже есть какой-то очень специфический софт. Чаще всего, это были конфигурации с панелью управления ISPmanager, VestaCP (и чаще всего, не обновляемые годами). Необходимо учесть и их запросы к переносу.
Миграция осуществляется со сохранением IP-адреса переносимого контейнера, будем считать что IP, который был у контейнера, сохраняется на VM и будет работать без проблем.
Перед переносом убедимся, что имеем всё на руках:
- Сервер OpenVZ, полный рут-доступ к хост-машине, возможность останавливать/монтировать/запускать/удалять контейнеры
- Сервер KVM, полный рут-доступ к хост-машине, со всеми вытекающими. Предполагается, что всё уже настроено и готово к работе.
Приступаем к переносу
Прежде чем начать перенос, обозначим термины, которые позволят не запутаться:
KVM_NODE — хост-машина KVM
VZ_NODE — хост-машина OpenVZ
CTID — контейнер OpenVZ
VM — виртуальный сервер KVM
Подготовка к переносу и создание виртуальных машин.
Шаг 1
Так как нам нужно куда-то переносить контейнер, то создадим VM с аналогичной конфигурацией на KVM_NODE.
Важно! Создавать VM нужно именно на той операционной системе, которая сейчас крутится на CTID. Например, если на CTID установлена Ubuntu 14, то и на VM нужно ставить Ubuntu 14. Минорные версии не важны и их несовпадение не столь критично, а вот мажорные — должны быть одинаковыми.
После создания VM, выполним обновление пакетов на CTID и на VM (не путать с обновлением ОС — её не обновляем, обновляем только пакеты и, если прилетит, версию ОС в пределах основной версии).
Для CentOS этот процесс выглядит безобидно:
# yum clean all
# yum update -y
И не менее безобидно для Ubuntu, Debian:
# apt-get update
# apt-get upgrade
Шаг 2
Устанавливаем на CTID, VZ_NODE и VM утилиту rsync:
CentOS:
# yum install rsync -y
Debian, Ubuntu:
# apt-get install rsync -y
Больше ничего не устанавливаем ни там, ни там.
Шаг 3
Производим остановку CTID на VZ_NODE командой
vzctl stop CTID
Монтируем образ CTID:
vzctl mount CTID
Переходим в папку /vz/root/CTID и выполняем
mount --bind /dev dev && mount --bind /sys sys && mount --bind /proc proc && chroot .
Под чрутом создаем файл /root/exclude.txt — он будет содержать список исключений, которые не попадут на новый сервер
/boot
/proc
/sys
/tmp
/dev
/var/lock
/etc/fstab
/etc/mtab
/etc/resolv.conf
/etc/conf.d/net
/etc/network/interfaces
/etc/networks
/etc/sysconfig/network*
/etc/sysconfig/hwconf
/etc/sysconfig/ip6tables-config
/etc/sysconfig/kernel
/etc/hostname
/etc/HOSTNAME
/etc/hosts
/etc/modprobe*
/etc/modules
/net
/lib/modules
/etc/rc.conf
/usr/share/nova-agent*
/usr/sbin/nova-agent*
/etc/init.d/nova-agent*
/etc/ips
/etc/ipaddrpool
/etc/ips.dnsmaster
/etc/resolv.conf
/etc/sysconfig/network-scripts/ifcfg-eth0
/etc/sysconfig/network-scripts/ifcfg-ens3
Подключаемся к KVM_NODE и запускаем наш VM, чтобы он работал и был доступен по сети.
Теперь всё готово к переносу. Поехали!
Шаг 4
Всё ещё находясь под чрутом, выполняем
rsync --exclude-from="/root/exclude.txt" --numeric-ids -avpogtStlHz --progress -e "ssh -T -o Compression=no -x" / root@KVM_NODE:/
Команда rsync выполнит перенос, надеемся, что ключи понятны — перенос осуществляется с сохранением симлинков, прав доступа, владельцев и групп и отключено шифрование для бОльшей скорости (можно было использовать какой-нибудь более быстрый cipher, но это не так принципиально в рамках данной задачи), также как отключено и сжатие.
После завершения выполнения rsync, выходим из-под chroot (нажатием ctrl+d) и выполняем
umount dev && umount proc && umount sys && cd .. && vzctl umount CTID
Шаг 5
Выполним несколько действий, которые помогут нам в запуске VM после переноса с OpenVZ.
На серверах с Systemd выполним команду, которая поможет нам залогиниться в обычной консоли, допустим, через VNC экран сервера
mv /etc/systemd/system/getty.target.wants/getty\@tty2.service /etc/systemd/system/getty.target.wants/getty\@tty1.service
На серверах CentOS 6 и CentOS 7 обязательно установим свежее ядро:
yum install kernel-$(uname -r)
Сервер может быть с него загружен, но после переноса оно может перестать работать или будет удалено.
На сервере CentOS 7 необходимо применить небольшой фикс для PolkitD, иначе сервер упадет в вечный бут:
getent group polkitd >/dev/null && echo -e "\e[1;32mpolkitd group already exists\e[0m" || { groupadd -r polkitd && echo -e "\e[1;33mAdded missing polkitd group\e[0m" || echo -e "\e[1;31mAdding polkitd group FAILED\e[0m"; }
getent passwd polkitd >/dev/null
&& echo -e "\e[1;32mpolkitd user already exists\e[0m" || { useradd -r -g polkitd -d / -s /sbin/nologin -c "User for polkitd" polkitd && echo -e "\e[1;33mAdded missing polkitd user\e[0m" || echo -e "\e[1;31mAdding polkitd user FAILED\e[0m"; }
rpm -Va polkit\* && echo -e "\e[1;32mpolkit* rpm verification passed\e[0m" || { echo -e "\e[1;33mResetting polkit* rpm user/group ownership & perms\e[0m"; rpm --setugids polkit polkit-pkla-compat; rpm --setperms polkit polkit-pkla-compat; }
На всех серверах, если был установлен mod_fcgid для Apache, выполним небольшой фикс с правами, иначе сайты, использующие mod_fcgid, будут падать с ошибкой 500:
chmod +s `which suexec` && apachectl restart
И последнее, пригодится для Ubuntu, Debian дистрибутивов. Эта ОС может упасть в вечный бут с ошибкой
looping too fast. throttling execution a little
неприятно, но легко фиксится, в зависимости от версии ОС.
На Debian 9 фикс выглядит так:
выполняем
dbus-uuidgen
если получаем ошибку
/usr/local/lib/libdbus-1.so.3: version `LIBDBUS_PRIVATE_1.10.8′ not found
проверяем наличие LIBDBUS
ls -la /lib/x86_64-linux-gnu | grep dbus
libdbus-1.so.3 -> libdbus-1.so.3.14.15
libdbus-1.so.3.14.15 <-- нужен этот
libdbus-1.so.3.14.16
если всё в порядке, выполняем
cd /lib/x86_64-linux-gnu
rm -rf libdbus-1.so.3
ln -s libdbus-1.so.3.14.15 libdbus-1.so.3
Если не помогает — пробуем второй вариант.
Второй вариант решения проблемы с throttling execution a little подходит практически для всех Ubuntu и Debian дистрибутивов.
Выполняем
bash -x /var/lib/dpkg/info/dbus.postinst configure
А для Ubuntu 14, Debian 7 дополнительно выполняем:
adduser --system --home /nonexistent --no-create-home --disabled-password --group messagebus
rm -rf /etc/init.d/modules_dep.sh
Что мы сделали? Восстановили messagebus, которого не хватало для запуска Debian/Ubuntu и удалили modules_dep, который пришел от OpenVZ и мешал загрузки многих модулей ядра.
Шаг 6
Перезагружаем VM, проверяем в VNC как идёт загрузка и в идеале — всё загрузится без проблем. Хотя, возможно, появятся некоторые специфические проблемы после миграции — но они выходят за рамки данной статьи и исправляются по мере появления.
Надеюсь, данная информация будет полезна! :)