Под капотом · Виртуализация · Сеть

Мост на хосте: ВМ в общей ЛВС

Пользователь собирает на хосте мост и подключает к нему ВМ, чтобы она попала в ту же ЛВС. Для этого он вводит несколько команд:

Команда
ip link add br0 type bridge
ip link set eno1 master br0
ip addr flush dev eno1
ip addr add 192.168.10.5/24 dev br0
ip link set br0 up
virsh attach-interface vm1 --type bridge --source br0 \
    --model virtio --config
libvirt API virDomainAttachDeviceFlags()

После выполнения команд ВМ получает адрес в подсети хоста и ведёт себя как обычная машина в сети.

  • Команда ip link add создаёт мост br0 - программный коммутатор второго уровня;
  • Команда ip link set eno1 master br0 делает физический порт портом моста;
  • Команда ip addr flush снимает с eno1 адрес, который там больше не нужен;
  • Команда ip addr add переносит адрес хоста на br0;
  • Команда ip link set br0 up поднимает мост;
  • Команда attach-interface добавляет ВМ интерфейс типа bridge и tap на мосту.
  • пользователь 1. Пользователь создаёт мост на хосте
    ip link add br0 type bridge
    ip link set br0 up

    Мост - устройство ядра: это коммутатор на кадрах Ethernet, а не программа и не демон.

  • сеть 2. Ядро получает новый коммутатор
    br0: bridge, STP выключен по умолчанию
    таблица MAC (FDB) пока пуста

    Мост пересылает кадры по MAC-адресам и учится им сам; IP-адреса ему не нужны.

  • пользователь 3. Пользователь делает физический порт портом моста
    ip link set eno1 master br0
    ip addr flush dev eno1
    ip addr add 192.168.10.5/24 dev br0

    После этого у eno1 не может быть своего адреса: он стал портом, а адрес хоста живёт на br0.

  • сеть 4. Хост и внешняя сеть соединяются
    br0: 192.168.10.5/24
    eno1: master br0, без адреса

    Для коммутатора в ЛВС ничего не изменилось: MAC хоста по-прежнему один, просто теперь он у моста.

  • libvirt 5. Демон добавляет ВМ интерфейс типа bridge
    <interface type='bridge'>
      <source bridge='br0'/>
      <model type='virtio'/>
    </interface>

    ВМ подключается не к физической карте, а к мосту - как кабель, воткнутый в порт коммутатора.

  • libvirt 6. Демон создаёт tap и сажает его на мост
    /dev/net/tun -> vnet0
    ip link set vnet0 master br0

    TAP - виртуальный Ethernet-порт: кадры из QEMU попадают в мост так же, как с настоящего кабеля.

  • QEMU 7. QEMU передаёт кадры гостя в tap
    -netdev tap,id=hostnet0,ifname=vnet0,vhost=on
    -device virtio-net-pci,netdev=hostnet0,mac=52:54:00:…

    Гость видит обычную сетевую карту; QEMU только переносит кадры между гостем и tap-устройством.

  • гость 8. Гость настраивает сеть как на железе
    eth0: link up, 52:54:00:…
    DHCPDISCOVER -> 192.168.10.77

    Гость не знает, что он виртуальный: он шлёт обычный DHCP-запрос, и его слышит DHCP-сервер ЛВС.

  • сеть 9. Мост учит MAC и пересылает кадры
    FDB: 52:54:00:… -> vnet0
    ответ шлюза -> vnet0

    Мост запомнил, за каким портом живёт MAC гостя, и дальше отдаёт его кадры только туда.