web-dev-qa-db-fra.com

Avec Ubuntu 16.04 et KVM, je ne peux pas mettre vms en réseau sans utiliser NAT

J'essaie de faire fonctionner une machine virtuelle dans KVM comme si elle disposait de sa propre interface réseau physique sur le réseau local. Je crois que cela s'appelle un pontage et j'ai essayé de suivre plusieurs guides en ligne, sans succès. Chaque fois que je me retrouve avec une VM possédant une carte réseau virtuelle ne pouvant pas communiquer avec mon réseau local.

Mon hôte et mes invités utilisent tous le serveur Ubuntu 16.04.

J'ai commencé par ajouter un br0 à mon fichier /etc/network/interfaces, qui ressemble maintenant à ceci:

~$ cat /etc/network/interfaces
source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

iface enp2s0 inet manual

auto br0
iface br0 inet dhcp
  bridge_ports enp2s0
  bridge_stp off
  bridge_fd 0
  bridge_maxwait 0

Après le redémarrage, mon ifconfig ressemble à ceci:

~$ ifconfig
br0       Link encap:Ethernet  HWaddr d0:50:99:c0:25:fb
          inet addr:192.168.113.2  Bcast:192.168.113.255  Mask:255.255.255.0
          ...

docker0   Link encap:Ethernet  HWaddr 02:42:dc:4f:96:9e
          ...

enp2s0    Link encap:Ethernet  HWaddr d0:50:99:c0:25:fb
          inet6 addr: fe80::d250:99ff:fec0:25fb/64 Scope:Link
          ...

lo        Link encap:Local Loopback
          ...

veth009cb0a Link encap:Ethernet  HWaddr 66:d6:6c:e7:80:cb
          inet6 addr: fe80::64d6:6cff:fee7:80cb/64 Scope:Link
          ...

virbr0    Link encap:Ethernet  HWaddr 52:54:00:1a:56:65
          inet addr:192.168.122.1  Bcast:192.168.122.255  Mask:255.255.255.0
          ...

L'hôte a une entrée statique sur mon serveur DHCP, il reçoit donc toujours 192.168.113.2, de sorte que l'adresse IP sur br0 est correcte. Si je comprends bien, tout ce que je devrais faire maintenant, c’est de démarrer une nouvelle machine virtuelle en utilisant l’interface br0. Alors je lance ceci:

Sudo virt-install --virt-type=kvm --name myvm \
--hvm --ram 4096 --vcpus=2 --graphics vnc \
--network bridge=br0 \
--os-type=linux --os-variant=ubuntu16.04 \
--cdrom=/var/lib/libvirt/boot/ubuntu-16.04.2-server-AMD64.iso \
--disk path=/var/lib/libvirt/images/myvm.qcow2,size=16,bus=virtio,format=qcow2

Je peux utiliser VNC dans la machine virtuelle et progresser dans l’installation à ce stade, jusqu’à ce que j’arrive à la phase "Configuration du réseau avec DHCP", où elle arrive à expiration et ne reçoit jamais une adresse IP.

Si j'utilise l'interface par défaut NAT, cela fonctionne bien, obtient une adresse IP sur la plage 192.168.112.xxx, et peut accéder au réseau local et à un plus grand réseau Internet, sans problème. Si je modifie ensuite la configuration de virsh sur cette machine virtuelle en réseau pour passer à br0, je ne peux parler à aucun réseau, local ou autre. DHCP ne parvient pas à obtenir une adresse IP et la définition d'une adresse IP statique ne génère pas de trafic extérieur.

Au cas où cela vous aiderait, pendant que le programme d'installation était en cours d'exécution, j'ai ouvert un autre terminal et j'ai reçu plus d'informations de l'hôte:

~$ brctl show
bridge name     bridge id               STP enabled     interfaces
br0             8000.d05099c025fb       no              enp2s0
                                                        vnet0
docker0         8000.0242dc4f969e       no              veth009cb0a
virbr0          8000.5254001a5665       yes             virbr0-nic

~$ brctl showmacs br0
port no mac addr                is local?       ageing timer
  1     00:04:20:eb:7e:96       no                 3.90
  1     00:11:32:63:9c:cf       no                 1.86
  1     30:46:9a:0f:81:cd       no                 3.39
  1     44:8a:5b:9e:d1:90       no                 0.00
  1     88:de:a9:13:86:48       no                 0.29
  1     b8:ae:ed:73:3e:ca       no                 3.89
  1     d0:50:99:c0:25:fb       yes                0.00
  1     d0:50:99:c0:25:fb       yes                0.00
  1     d0:50:99:e0:21:46       no                 2.90
  1     f0:f6:1c:e3:7f:be       no               173.56
  2     fe:54:00:6f:b8:64       yes                0.00
  2     fe:54:00:6f:b8:64       yes                0.00

~$ ip route
default via 192.168.113.1 dev br0
172.17.0.0/16 dev docker0  proto kernel  scope link  src 172.17.0.1
192.168.113.0/24 dev br0  proto kernel  scope link  src 192.168.113.2
192.168.122.0/24 dev virbr0  proto kernel  scope link  src 192.168.122.1 linkdown

Je suis prêt à lancer le fichier dumpxml complet ici si quelqu'un le veut, mais voici juste la section réseau:

<interface type='bridge'>
  <mac address='52:54:00:6f:b8:64'/>
  <source bridge='br0'/>
  <model type='virtio'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

PDATE 2017-03-25: En modifiant les éléments suivants:

    <interface type='network'>
      <mac address='52:54:00:6f:b8:64'/>
      <source network='default'/>
      <model type='virtio'/>
      <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
    </interface>

Ensuite, NAT fonctionne et je reçois l'adresse IP 192.168.122.xxx. Je peux parler à des services externes, etc. Alors ... y a-t-il un problème avec mes hôtes br0? Si c'est le cas, pourquoi l'hôte reçoit-il une adresse IP dessus? Existe-t-il des périphériques Ethernet qui ne prennent tout simplement pas en charge les ponts? Voici le résultat de lspci sur l'hôte:

~$ lspci | grep Ethernet
02:00.0 Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)
03:00.0 Ethernet controller: Intel Corporation I210 Gigabit Network Connection (rev 03)

Je n'ai pas du tout configuré le second contrôleur Ethernet, peut-être que je vais le configurer et essayer de le remplacer à la place.

PDATE 2017-03-25 b: La deuxième interface ne semble pas avoir modifié les résultats. Voici les interfaces/etc/network/résultantes:

source /etc/network/interfaces.d/*

auto lo
iface lo inet loopback

auto enp2s0
iface enp2s0 inet dhcp

auto enp3s0
iface enp3s0 inet manual

auto br0
iface br0 inet dhcp
  bridge_ports enp3s0
  bridge_stp off
  bridge_fd 0
  bridge_maxwait 0

Ce qui, quand je ip a, a pour résultat:

1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope Host lo
      valid_lft forever preferred_lft forever
    inet6 ::1/128 scope Host
      valid_lft forever preferred_lft forever
2: enp2s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
    link/ether d0:50:99:c0:25:fb brd ff:ff:ff:ff:ff:ff
    inet 192.168.113.2/24 brd 192.168.113.255 scope global enp2s0
      valid_lft forever preferred_lft forever
    inet6 fe80::d250:99ff:fec0:25fb/64 scope link
      valid_lft forever preferred_lft forever
3: enp3s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq master br0 state UP group default qlen 1000
    link/ether d0:50:99:c0:25:fa brd ff:ff:ff:ff:ff:ff
    inet6 fe80::d250:99ff:fec0:25fa/64 scope link
      valid_lft forever preferred_lft forever
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether d0:50:99:c0:25:fa brd ff:ff:ff:ff:ff:ff
    inet 192.168.113.100/24 brd 192.168.113.255 scope global br0
      valid_lft forever preferred_lft forever
    inet6 fe80::d250:99ff:fec0:25fa/64 scope link
      valid_lft forever preferred_lft forever
5: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether 52:54:00:1a:56:65 brd ff:ff:ff:ff:ff:ff
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
      valid_lft forever preferred_lft forever
6: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN group default qlen 1000
    link/ether 52:54:00:1a:56:65 brd ff:ff:ff:ff:ff:ff
7: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether 02:42:18:2c:73:bb brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 scope global docker0
      valid_lft forever preferred_lft forever
    inet6 fe80::42:18ff:fe2c:73bb/64 scope link
      valid_lft forever preferred_lft forever
9: vethaa3cd40@if8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default
    link/ether ae:05:f7:1b:f9:9e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::ac05:f7ff:fe1b:f99e/64 scope link
      valid_lft forever preferred_lft forever
10: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN group default qlen 1000
    link/ether fe:54:00:3a:54:b3 brd ff:ff:ff:ff:ff:ff
    inet6 fe80::fc54:ff:fe3a:54b3/64 scope link
      valid_lft forever preferred_lft forever

La VM continue d'avoir exactement les mêmes problèmes lorsqu'on lui dit d'utiliser br0.

3
brakeley

Résolu.

Le problème venait des paramètres par défaut du module br_netfilter, qui envoient des paquets pontés à iptables. Les documents libvirt le mentionnent sur leur page de mise en résea , mais la plupart des tutoriels que j'avais suivis ne le couvraient pas.

Pour une raison quelconque, iptables mangeait ces paquets (peut-être quelque chose de docker a-t-il été ajouté?), Mais envoyer ces paquets à iptables est apparemment inefficace, donc le correctif consiste à contourner iptables en modifiant ces paramètres.

Notez que la méthode que je décris ici est en fait un exemple dans la page de manuel sysctl.d .

Créez un /etc/udev/rules.d/99-bridge.rules et insérez cette ligne:

ACTION=="add", SUBSYSTEM=="module", KERNEL=="br_netfilter", RUN+="/lib/systemd/systemd-sysctl --prefix=/net/bridge"

Ensuite, créez un /etc/sysctl.d/bridge.conf et insérez ces trois lignes:

net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0

Ensuite, je devais simplement revenir à ma configuration de pont d'origine, qui implique un /etc/network/interfaces qui ressemble à ceci:

source /etc/network/interfaces.d/*
auto lo
iface lo inet loopback
auto enp2s0
iface enp2s0 inet manual
auto br0
iface br0 inet dhcp
  bridge_ports enp2s0
  bridge_stp off
  bridge_fd 0
  bridge_maxwait 0

Et une définition d'interface réseau virsh qui ressemble à ceci:

<interface type='bridge'>
  <mac address='52:54:00:37:e1:55'/>
  <source bridge='br0'/>
  <model type='virtio'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

Avec tout cela en place, mon VM démarre, il reçoit une adresse IP et je peux parler librement avec mon hôte, le réseau local et Internet.

2
brakeley

Je l'ai fait fonctionner, en utilisant direct au lieu de bridge:

En utilisant ce /etc/network/interfaces

source /etc/network/interfaces.d/*
auto lo
iface lo inet loopback
auto enp2s0
iface enp2s0 inet dhcp
auto enp3s0
iface enp3s0 inet manual

Et cette configuration de virsh:

<interface type='direct'>
  <mac address='52:54:00:37:e1:55'/>
  <source dev='enp3s0' mode='vepa'/>
  <target dev='macvtap0'/>
  <model type='rtl8139'/>
  <alias name='net0'/>
  <address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>

Mon réseau local voit l'adresse MAC 52: 54: 00: 37: e1: 55, et le serveur DHCP lui attribue une adresse IP. Je peux faire ssh sur cette machine via cette adresse IP. Je peux exécuter simultanément une seconde VM, son MAC reçoit également une adresse IP, de sorte que je semble avoir la solution que je souhaitais.

Peut-être que j'essaierai ensuite de faire tout cela sur le port Ethernet d'origine. Je suis également curieux de savoir ce qu'est réellement un pont, et ce qui résout ce problème directement, si quelqu'un qui lit ceci a une réponse. Merci!

UPDATE: Le problème de cette solution est que toutes les machines virtuelles partageant une seule interface physique ne parviennent pas à se parler. Il en va de même pour l'hôte, lorsque l'hôte et les ordinateurs virtuels partagent la même interface physique.

Je suppose que c’est le problème même que le pontage est censé résoudre, mais je pourrais vraiment utiliser les conseils de quelqu'un qui a une certaine expérience de ce genre de choses.

1
brakeley