1.Linux Bridge的基本概念
假设宿主机有 1 块与外网连接的物理网卡 eth0,上面跑了 1 个虚机 VM1,现在有个问题是:
如何让 VM1 能够访问外网?
① 给 VM1 分配一个虚拟网卡 vnet0,通过 Linux Bridge br0 将 eth0 和 vnet0 连接起来,如下图所示
Linux Bridge 是 Linux 上用来做 TCP/IP 二层协议交换的设备,其功能大家可以简单的理解为是一个二层交换机或者 Hub。多个网络设备可以连接到同一个 Linux Bridge,当某个设备收到数据包时,Linux Bridge 会将数据转发给其他设备。
在上面这个例子中,当有数据到达 eth0 时,br0 会将数据转发给 vnet0,这样 VM1 就能接收到来自外网的数据;
反过来,VM1 发送数据给 vnet0,br0 也会将数据转发到 eth0,从而实现了 VM1 与外网的通信。
现在我们增加一个虚机 VM2,如下图所示
VM2 的虚拟网卡 vnet1 也连接到了 br0 上。
现在 VM1 和 VM2 之间可以通信,同时 VM1 和 VM2 也都可以与外网通信。
2.理解virbr0
virbr0 是 KVM 默认创建的一个 Bridge,其作用是为连接其上的虚机网卡提供 NAT 访问外网的功能。
virbr0 默认分配了一个IP 192.168.122.1,并为连接其上的其他虚拟网卡提供 DHCP 服务。
[root@linux-node1 ~]# ifconfig
brqc39c1348-5a: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.56.11 netmask 255.255.255.0 broadcast 192.168.56.255
ether 00:0c:29:4c:ef:31 txqueuelen 0 (Ethernet)
RX packets 1069698 bytes 374890434 (357.5 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 854554 bytes 289390857 (275.9 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
inet6 fe80::20c:29ff:fe4c:ef31 prefixlen 64 scopeid 0x20<link>
ether 00:0c:29:4c:ef:31 txqueuelen 1000 (Ethernet)
RX packets 1272820 bytes 454742027 (433.6 MiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 948074 bytes 428034564 (408.2 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING> mtu 65536
inet 127.0.0.1 netmask 255.0.0.0
inet6 ::1 prefixlen 128 scopeid 0x10<host>
loop txqueuelen 0 (Local Loopback)
RX packets 12361940 bytes 4186785589 (3.8 GiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 12361940 bytes 4186785589 (3.8 GiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tapae04cfac-d0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500
ether 6a:ef:28:f7:c5:90 txqueuelen 1000 (Ethernet)
RX packets 5 bytes 438 (438.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 13043 bytes 2231018 (2.1 MiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
virbr0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500
inet 192.168.122.1 netmask 255.255.255.0 broadcast 192.168.122.255
ether 52:54:00:8b:7a:13 txqueuelen 0 (Ethernet)
RX packets 0 bytes 0 (0.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 0 bytes 0 (0.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
查看虚拟机
[root@linux-node1 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
- centos 关闭
查看虚拟机网卡信息
[root@linux-node1 ~]# virsh domiflist centos
接口 类型 源 型号 MAC
-------------------------------------------------------
- network default virtio 52:54:00:e4:75:83
查看桥接网卡信息,可以看到virbr0-nic桥接到virbr0网卡上
[root@linux-node1 ~]# brctl show
bridge name bridge id STP enabled interfaces
brqc39c1348-5a 8000.000c294cef31 no eth0
tapae04cfac-d0
virbr0 8000.5254008b7a13 yes virbr0-nic
启动虚拟机
[root@linux-node1 ~]# virsh start centos
域 centos 已开始
[root@linux-node1 ~]# virsh list --all
Id 名称 状态
----------------------------------------------------
1 centos running
使用TightVNC连接192.168.56.11,查看网卡信息
[root@linux-node1 ~]# ssh 192.168.122.169
root@192.168.122.169's password:
Last login: Tue Dec 12 15:04:59 2017
ping外网可通
[root@localhost ~]# ping www.baidu.com
PING www.a.shifen.com (14.215.177.39) 56(84) bytes of data.
64 bytes from 14.215.177.39: icmp_seq=1 ttl=127 time=13.4 ms
64 bytes from 14.215.177.39: icmp_seq=2 ttl=127 time=9.14 ms
64 bytes from 14.215.177.39: icmp_seq=3 ttl=127 time=8.47 ms
64 bytes from 14.215.177.39: icmp_seq=4 ttl=127 time=15.5 ms
64 bytes from 14.215.177.39: icmp_seq=5 ttl=127 time=8.85 ms
64 bytes from 14.215.177.39: icmp_seq=6 ttl=127 time=8.85 ms
^C
--- www.a.shifen.com ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5012ms
rtt min/avg/max/mdev = 8.473/10.716/15.538/2.741 ms
没有问题,可以访问外网,说明 NAT 起作用了。
需要说明的是,使用 NAT 的虚拟机 centos可以访问外网,但外网无法直接访问 centos。
因为 centos 发出的网络包源地址并不是 192.168.122.169,而是被 NAT 替换为宿主机的 IP 地址了。
这个与使用 br0 不一样,在 br0 的情况下,centos 通过自己的 IP 直接与外网通信,不会经过 NAT 地址转换。