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.
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.
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.