假設宿主機有 1 塊與外網連接的物理網卡 eth0,上面跑了 1 個虛機 VM1,現在有個問題是: 
如何讓 VM1 能夠訪問外網?
① 給 VM1 分配一個虛擬網卡 vnet0,通過 Linux Bridge br0 將 eth0 和 vnet0 連接起來,如下圖所示
OpenStack入門修煉之網絡虛擬化基礎(20)

Linux Bridge 是 Linux 上用來做 TCP/IP 二層協議交換的設備,其功能大家可以簡單的理解為是一個二層交換機或者 Hub。多個網絡設備可以連接到同一個 Linux Bridge,當某個設備收到數據包時,Linux Bridge 會將數據轉發給其他設備。

在上面這個例子中,當有數據到達 eth0 時,br0 會將數據轉發給 vnet0,這樣 VM1 就能接收到來自外網的數據; 
反過來,VM1 發送數據給 vnet0,br0 也會將數據轉發到 eth0,從而實現了 VM1 與外網的通信。

現在我們增加一個虛機 VM2,如下圖所示
OpenStack入門修煉之網絡虛擬化基礎(20)

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 地址轉換。