Ошибки сети гостевой Windows в виртуальной машине KVM

в 19:46, , рубрики: Песочница, метки: ,

В статье «Запуск Windows под Linux KVM» описан баг QEMU-KVM «подвисания гостевой сети при интенсивном трафике» (см. п. «Зависания сети»). По моему опыту интенсивность трафика гостевой машины не играет особенной роли, но ошибка проявляется при большой нагрузке на хост-систему.

Предложенное в статье решение и ссылки на аналогичные «костыли» помогают только в некоторых случаях. Ошибка авторов таких решений в том, что они инициализируют заново только драйвер виртуальной ОС, тогда как причина сбоя находится в самом KVM.

Попробовав разные варианты, я остановился на простом и эффективном решении: отключение и подключение виртуального интерфейса средствами KVM. При отказе сети виртуальной машины скрипт выполняет две команды virsh: detach interface и attach interface.

К сожалению, иногда возникает ситуация, что выполнение команды detach interface «зависает», в этом случае приходится принудительно завершать KVM, а иногда и перезагружать сервер (в случае, когда процесс KVM превращается в «зомби» и модуль kvm не удаётся выгрузить из ядра).

Кроме того, эксплуатация виртуальных машин показала, что чаще всего подвисания возникают при использовании на хост-машине моста с физическим интерфейсом. Разместив виртуальную машину в отдельной подсети, я избавился от частых подвисаний сети VM. При этом, разумеется, пришлось настраивать маршрутизацию.

В результате теперь на нескольких обслуживаемых мной серверах достаточно стабильно работают виртуальные Windows Server разных версий.

Приложение

Пример скрипта для контроля за работой виртуальной сети и передёргивания интерфейса виртуальной машины.

SCRIPTNAME=="$(basename $0)"
VMNAME="srv12"
VMIP="192.168.9.5"
VMIFMAC="52:54:00:f8:37:3f"
VMIFMODEL="virtio"
VMNETNAME="routed"
VMNETDETACH="detach-interface ${VMNAME} network --mac '${VMIFMAC}'"
VMNETATTACH="attach-interface srv12 network ${VMNETNAME} --mac '${VMIFMAC}' --model ${VMIFMODEL}"

VMRUN=$(sudo virsh dominfo srv12 | egrep -q "State:s+running")
if [ "${VMRUN}" -eq 1 ];then
  PINGVM=$(ping -c 10 -w 1 -W 1 ${VMIP} | sed -n 's/.*, ([1-9][0-9]*) received,.*/1/p')
  if [ "${PINGVM:-0}" -le 0 ];then
    logger -s -p daemon.warning -t "${SCRIPTNAME}" "${VMNAME} network is down: ${VMIP} unreachable, try to restart virtual interface"
    sudo virsh ${VMNETDETACH}
    sudo virsh ${VMNETATTTACH}
    logger -s -p daemon.warning -t "${SCRIPTNAME}" "${VMNAME} virtual interface reloaded"
  fi
fi

Поделиться

* - обязательные к заполнению поля