ADG Оставить заявку
Блог Инфраструктура 5 мин чтения

KVM live migration с iSCSI-томом: виртуалка переезжает без простоя

Запускаем live migration между двумя KVM-хостами с общим iSCSI-томом. Разбираем сетевые требования, ловушки с MAC-адресами и что пошло не так с первого раза.

Контекст момента

KVM + libvirt утверждается как enterprise-альтернатива VMware при использовании с общим СХД

Один из клиентских стендов на сопровождении мы наконец перевели с VMware ESXi на KVM. Причина прозаичная: лицензия на vMotion стоила отдельных денег, а задача была простая - уметь перекладывать виртуалки между двумя хостами без остановки во время регламентных работ. KVM + libvirt + общий iSCSI-том решают ту же задачу без доплаты за функцию. Вот как это устроено и где мы споткнулись.

Схема стенда

Два физических хоста - kvm-node1 и kvm-node2, оба CentOS 7, libvirt 1.2.x из репозитория. СХД отдаёт один iSCSI-том, который подключён на обоих хостах и смонтирован как пул virsh pool-define-as с типом disk. Виртуальный диск лежит на этом общем томе - это обязательное условие для live migration, иначе придётся тащить данные через сеть целиком, что уже не live, а offline.

Сетевых интерфейсов на хостах три: management (ssh + virsh), migration (для передачи памяти), storage (iSCSI). Смешивать их в один - можно, но тогда при миграции трафик памяти и iSCSI будут делить полосу, и в нагруженный момент получишь таймаут.

Команда и что происходит

virsh migrate --live --persistent \
  --migrate-disks '' \
  vm-name \
  qemu+ssh://kvm-node2/system

--live - миграция без остановки. --persistent - конфиг VM прописывается на целевом хосте, иначе после перезагрузки node2 виртуалка туда не вернётся. --migrate-disks '' - явно говорим «не тащить диски», потому что они уже на общем хранилище.

virsh последовательно делает следующее: открывает соединение с libvirt на целевом хосте, создаёт там домен в приостановленном состоянии, начинает копировать оперативную память (dirty-page tracking), когда дельта становится достаточно маленькой - на доли секунды замораживает исходную VM, досылает остаток памяти, переключает выполнение на целевом хосте. С точки зрения пользователя - небольшая задержка сети, и всё.

На практике у нас получалось от 2 до 8 секунд «заморозки» в зависимости от того, насколько активно VM писала в память в момент миграции. Нагруженная Java-JVM с большой кучей - самый плохой вариант.

Сетевые требования: что проверить до запуска

Имена хостов должны резолвиться симметрично. libvirt по умолчанию передаёт исходный хост по hostname, и целевой должен его видеть. Простой способ убедиться - на каждом хосте прописать оба имени в /etc/hosts, не надеяться на DNS.

Порты libvirt должны быть открыты. Миграция идёт на порты 49152-49215 (диапазон по умолчанию в libvirt). Firewall на обоих хостах должен разрешать этот диапазон между migration-интерфейсами. Мы поначалу разрешили только 16509 (libvirt API) и получили «migration failed» без внятной причины в логе - пришлось smcap на портах ловить.

iSCSI-том должен быть подключён на обоих хостах одновременно. Кажется очевидным, но: если инициатор на node2 не залогинен в target в момент миграции - VM запустится на новом хосте без диска. Проверить: iscsiadm -m session на обоих хостах перед миграцией. Для работы с удалённым хостом нужен SSH доступ к обоим узлам.

Ловушка с MAC-адресами

Вот здесь мы потеряли полчаса. После успешной миграции виртуалка на node2 была доступна по SSH, ping шёл, всё выглядело хорошо - а потом клиент сообщил, что его скрипты, которые ходят на VM по имени хоста, перестали работать.

Проблема: сеть в гостевой ОС. На CentOS 6 в гостевой машине NetworkManager при первом старте привязывает сетевой интерфейс к MAC-адресу и записывает в /etc/udev/rules.d/70-persistent-net.rules. Если MAC меняется - ядро называет интерфейс по-другому (eth1 вместо eth0), старая конфигурация не применяется, и NIC остаётся без адреса.

У нас MAC не менялся - мы сохранили ту же конфигурацию VM. Но проблема всплыла потому, что на node2 в сети стоял коммутатор с port security: он запомнил MAC на порту node1 и не хотел пускать тот же MAC с порта node2. Убедили сетевиков поднять mac-address-table aging-time до значения меньше времени миграции или вовсе отключить port security на migration VLAN. После этого миграция стала работать прозрачно.

Второй сценарий с MAC - когда libvirt при создании VM генерирует MAC автоматически. Если перед миграцией выгрузить XML домена (virsh dumpxml), перенести на другой хост и создать заново через virsh define - новый MAC не будет сгенерирован, он возьмётся из XML. Но если кто-то создал VM руками на обоих хостах с разными MAC - будет именно эта история с переименованием интерфейсов в гостевой ОС.

Что с virt-manager

virsh достаточно для работы, но для визуального контроля у нас поднят virt-manager на отдельной машине с SSH-туннелями к обоим хостам. Смотреть на консоль VM во время миграции и видеть как она «переезжает» - приятно, особенно когда объясняешь клиенту что сейчас будет. Прогресс миграции там показывается в реальном времени.

Итог

Live migration на KVM с iSCSI работает и решает задачу. Сетевая подготовка занимает больше времени, чем сама настройка libvirt: симметричный DNS/hosts, правильные firewall-правила, проверка iSCSI-сессий, договорённость с сетевиками про port security. Сама команда virsh migrate - строчка в скрипте. MAC-адреса в гостевых ОС - отдельный класс проблем, который не зависит от KVM как такового, но всплывает именно при миграции и заставляет отлаживать в трёх слоях одновременно.

Для клиентов, где vMotion был основным аргументом в пользу VMware, KVM с iSCSI закрывает эту потребность. Остальные доводы за VMware - отдельный разговор.

Контакт

Нужна такая же инженерная работа?

Опишите задачу и контекст. Ответим в течение рабочего дня, при необходимости подпишем NDA.