Wolf
Roman Grossi
Tobishua
Digital nomad and originality

Небольшой пост о том как настроить роутинг IPv6 с хоста на виртуалки в KVM с помощью virsh и чтобы при перезагрузке сети минимизировать даунтайм или вообще избежать его.

К сожалению, при рестарте сети, которая является основной для виртуального сервере не обойтись без даунтайма, но есть способы как минимизировать его или полностью избежать, а именно:

  1. Минимизируем даунтайм - перезагружаем сеть и переподключаем виртуалки с помощью bash-скрипта

  2. Избегаем даунтайма - создаём новую сеть для IPv6

Изначально имеем следующее:

  • Физический сервер с libvirt, virsh, qemu и вот этим вот всем

  • Некоторое количество guest-серверов на которых нужно настроить IPv6

  • Некоторая IPv6 подсеть (я буду рассматривать на примере своей 2a01:4f8:172:13cd::/64 от Hetzner)

Теперь разберём каждый вариант настройки подробнее.

Роутинг IPv6 без даунтайма

Первым делом настройте IPv6 на хосте (если ещё этого не сделали):

Заходим в редактирование интерфейсов

nano /etc/network/interfaces

Нам нужно, чтобы на хосте остался только один IPv6 адрес (/128 маска сети). Для этого изменяем/добавляем к основному интерфейсу конфигурацию IPv6:

iface eth0 inet6 static
       address 2a01:4f8:172:13cd::2
       netmask 128
       gateway fe80::1

Перезапускаем интерфейс:

ifdown eth0 && ifup eth0

Если интерфейс не упал и нас не выкинуло из SSH, то создаём где-нибудь (я предпочитаю /tmp) xml-файл с конфигурацией сети для libvirt:

nano /tmp/ipv6.xml

Примерно с вот таким содержимым:

<network connections='2'>
 <name>ipv6</name>
 <uuid>d1d119da-f8fd-4804-878d-5e5271ffadc3</uuid>
 <forward mode='nat'/>
 <bridge name='virbr1' stp='on' delay='0'/>
 <mac address='52:54:00:c6:e6:17'/>
 <ip family='ipv6' address='2a01:4f8:172:13cd::2' prefix='64'>
 </ip>
</network>

Что значит этот конфиг:
<name>ipv6</name> - название сети
<uuid>d1d119da-f8fd-4804-878d-5e5271ffadc3</uuid> - UUID сети. Можно сделать с помощью uuidgen
<forward mode='nat'/> - роутим через NAT
<bridge name='virbr1' stp='on' delay='0'/> - конфиг моста. Вот тут осторожно. Если вдруг на сервере уже есть мост с таким названием, то всё, всё пропало! Так что лучше проверить через ifconfig; stp - избегаем петель; delay - форвардим без задержек
<mac address='52:54:00:c6:e6:17'/> - слишком очевидно, чтобы объяснять, но всё же: 1. В сети не может быть двух одинаковых MAC-адресов; 2. Можно задать случайный, который отличается от MAC-адресов виртуалок
<ip family='ipv6' address='2a01:4f8:172:13cd::2' prefix='64'> - шлюз нашей IPv6 сети и префикс - 64, то есть роутим всё оставшееся на виртуалки

После того как файл создан, создадим из него сеть вот этой командой:

virsh net-create /tmp/ipv6.xml

Отлично! Теперь можно прицепить эту сеть на гостевую машину:

virsh attach-interface guest-name network ipv6 --mac 52:54:00:dd:4a:c5 --model virtio

guest-name - название виртуального сервера (hint: virsh list)

ipv6 - название сети (hint: virsh net-list)

52:54:00:dd:4a:c5 - MAC-адрес со стороны гостевой машины

virtio - модель интерфейса, можно поставить rtl8139, это не принципиально

Подцепилось? Хорошо, теперь настраиваем IPv6 в гостевой ОС

Смотрим список интерфейсов:

ifconfig -a

и ищем тот, которого нет в /etc/network/interfaces.

Настраиваем интерфейс:

nano /etc/network/interfaces

Конфиг примерно такой:

auto ens3
iface ens3 inet6 static
       address 2a01:04f8:0172:13cd:dead:babe:dead:face #Простите, не удержался
       netmask 64
       gateway 2a01:04f8:0172:13cd::2

Ну и поднимаем интерфейс:

ifup ens3

Вжух! Всё работает! (по крайне мере должно)

Роутинг IPv6 с даунтаймом

Теперь поговорим, как настроить IPv6 в уже существующей сети, например в default. Как я и писал выше, даунтайма в этом случае не избежать, но мы минимизируем его.

Для начала отредактируем сеть

virsh net-edit default

и добавим перед </network> конфиг для IPv6, примерно такой:

<ip family='ipv6' address='2a01:4f8:172:13cd::2' prefix='64'>

выше я уже описывал, что всё это значит.

После этого сотворим немного волшебства с помощью вот этого bash-скрипта:

#!/bin/bash

set -e  
set -u

NET_NAME=default  
NET_HOOK=/etc/libvirt/hooks/qemu

virsh net-destroy $NET_NAME  
virsh net-start $NET_NAME

VMS=$( virsh list | tail -n +3 | head -n -1 | awk '{ print $2; }' )

for m in $VMS ; do
   echo "$m"
   MAC_ADDR=$(virsh domiflist "$m" |grep -o -E "([0-9a-f]{2}:){5}([0-9a-f]{2})")
   NET_MODEL=$(virsh domiflist "$m" | tail -n +3 | head -n -1 | awk '{ print $4; }')

   set +e
   virsh detach-interface "$m" network --mac "$MAC_ADDR" && sleep 3
   virsh attach-interface "$m" network $NET_NAME --mac "$MAC_ADDR" --model "$NET_MODEL"
   set -e

   $NET_HOOK "$m" stopped && sleep 3
   $NET_HOOK "$m" start

done  

Он сделает всё за нас, а именно:

  1. Перезагрузит сеть default

  2. Переподключит сеть к каждому из виртуальных серверов

  3. Сделает так, чтобы виртуалки смогли подняться

После этого можно приступить к настройке IPv6 в гостевой операционной системе, она будет такой же как и в случае конфигурации IPv6 без даунтайма.

Комментарии к этому хорошему посту: