[ kvm ] 四種簡單的網路模型

JL-LOVE發表於2020-10-21


    1. 隔離模式:虛擬機器之間組建網路,該模式無法與宿主機通訊,無法與其他網路通訊,相當於虛擬機器只是連線到一臺交換機上。
    2. 路由模式:相當於虛擬機器連線到一臺路由器上,由路由器(物理網路卡),統一轉發,但是不會改變源地址。
    3. NAT模式:在路由模式中,會出現虛擬機器可以訪問其他主機,但是其他主機的報文無法到達虛擬機器,而NAT模式則將源地址轉換為路由器(物理網路卡)地址,這樣其他主機也知道報文來自那個主機,在docker環境中經常被使用。
    4. 橋接模式:在宿主機中建立一張虛擬網路卡作為宿主機的網路卡,而物理網路卡則作為交換機。

 

    1. 隔離模型:

        Guest1 和 Guest2 都為虛擬機器。
        Linux在虛擬機器中的網路卡都包含前半段和後半段,前半段在虛擬機器上,後半段在宿主機上。上圖eth0在Guest1虛擬機器上的網路卡,對應的後半段為vnet0,在Guest1上所有發往eth0的資料就直接發往vnet0了,也可以將vnet0看作一張網路卡

        Guest1和Guest2如何通訊:
            在宿主機中建立一個虛擬交換機,讓vnet0和vnet1分別為虛擬交換機的一個介面,交換機也可以叫做bridge,只要兩個虛擬網路卡的前半段ip地址在同一個網段內,就可以相互通訊,這就是隔離模式。

 

    1.1 使用qemu-kvm建立隔離模式

[root@kvm ~]# yum install bridge-utils qemu-kvm -y         # 安裝所需軟體包

# 建立網橋

[root@kvm ~]# brctl addbr br0
[root@kvm ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
br0        8000.000000000000    no
[root@kvm ~]# ip link set br0 up     # 必須保持橋接網路卡的活躍狀態,否則虛擬機器之間無法互通

虛擬機器啟動時,網路卡的後半段不會自動新增到虛擬網橋,需要一個指令碼來實現,首先編寫指令碼

新增網路卡指令碼:

[root@kvm ~]# vim /etc/qemu-ifup

#!/bin/bash
#
BRIDGE=br0
if [ -n $1 ]; then
    ip link set $1 up
    sleep 1
    brctl addif $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
    echo "Error: no interface specified."
exit 1
fi

[root@kvm ~]# sh -n /etc/qemu-ifup         # 檢測有無語法錯誤
[root@kvm ~]# chmod +x /etc/qemu-ifup     # 給與執行許可權

當虛擬機器停止時,網路卡會自動從網橋中down掉,所以不用編寫停止網路卡指令碼

[root@kvm ~]# qemu-kvm -smp 1 -m 512 -cpu host -drive file=/images/centos7.img,if=virtio,media=disk,cache=writeback -net nic,model=virtio,macaddr=52:54:00:11:22:33 -net tap,ifname=vnet0.0,script=/etc/qemu-ifup -daemonize
VNC server running on `127.0.0.1:5900'


    -smp: 虛擬機器cpu執行緒數
    -cpu: cpu的型別;host為虛擬機器使用物理機cpu型別
    -drive: 驅動裝置
        file: 驅動裝置目錄
        if: 驅動裝置型別,virtio為半虛擬化型別,效能較好
        media:驅動裝置是disk還是cdrom
        cache:裝置快取,writeback為回寫
    -net
        nic:虛擬機器網路卡前半段,這是在虛擬機器中使用的網路卡
        macaddr:設定虛擬機器網路卡mac地址,在使用qemu-kvm建立虛擬機器時,需要手動指定mac地址,否則會出現相同的mac地址虛擬機器
        model:網路卡型別,virtio為半虛擬化型別,效能較好
        tap:為虛擬網路卡後半段,需要連線到網橋上
        ifname:系統中網路卡名稱,比如:vnet0.0
        script:指定啟動時,需要執行的指令碼,該指令碼是將虛擬機器的後半段網路卡新增到網橋中

 

啟動第二臺虛擬機器

[root@kvm ~]# qemu-kvm -smp 1 -m 512 -cpu host -drive file=/images/centos7-1.img,if=virtio,media=disk,cache=writeback -net nic,model=virtio,macaddr=52:54:00:11:22:34 -net tap,ifname=vnet0.1,script=/etc/qemu-ifup -daemonize
VNC server running on `127.0.0.1:5901'

通過上圖,虛擬主機之間能相互連通。

 

宿主機是無法訪問到虛擬機器,這就是kvm隔離模式

 

    2. 路由模型及NAT模型

    NAT模式
        該模式網橋要作為路由器對虛擬機器地址進行轉發,路由模式是無法修改源地址ip,因此虛擬機器可能會成功的將報文傳送給目標地址ip,而目標地址ip無法將報文回傳給源地址ip;
                                                           NAT模式則是將源地址ip改為物理網路卡ip傳送給目標地址,目標地址ip回傳給物理網路卡,在將報文傳送至虛擬主機。

 

    2.1 使用qemu-kvm建立NAT模式

[root@kvm ~]# yum install qemu-kvm iptables-services bridge-utils -y     # 安裝需要的程式包,使用iptables規則對報文進行轉發。

編寫虛擬機器開啟執行指令碼:

[root@kvm ~]# vim /etc/qemu-natup 

#!/bin/bash
#
bridge=br0
net="192.168.100.1/24"

checkbr() {
    if brctl show | grep -i $1; then
        return 0
    else
        return 1
    fi
}

initbr() {
    brctl addbr $bridge
    ip link set $bridge up
    ip addr add $net dev $bridge
}

enable_ip_forward() {
    sysctl -w net.ipv4.ip_forward=1
}

setup_nat() {
    checkbr $bridge
    if [ $? -eq 1 ]; then
        initbr
        enable_ip_forward
        iptables -t nat -A POSTROUTING -s $net ! -d $net -j MASQUERADE
    fi
}

if [ -n $1 ]; then
    setup_nat
    ip link set $1 up
    brctl addif $bridge $1
    exit 0
else
    echo "Error: no interface specified."
    exit 1
fi

 

編寫虛擬機器關閉執行指令碼:

[root@kvm ~]# vim /etc/qemu-natdown 

#!/bin/bash
#
bridge=br0
net='192.168.100.0/24'

remove_rule() {
    iptables -t nat -F
}

isalone_bridge() {
    if ! brctl show | awk "/^$bridge/{print \$4}" | grep "[^[:space:]]" &> /dev/null; then
        ip link set $bridge down
        brctl delbr $bridge
        remove_rule
    fi
}

if [ -n $1 ]; then
    ip link set $1 down
    brctl delif $bridge $1
    isalone_bridge
exit 0
else
    echo "Error: no interface specified."
    exit 1
fi

以上兩個指令碼對於NAT模型來說非常重要。

使用qemu-kvm 建立虛擬機器

[root@kvm ~]# qemu-kvm -smp 1 -m 512 -cpu host -drive file=/images/centos7.img,if=virtio,media=disk,cache=writeback -net nic,model=virtio,macaddr=52:54:00:11:22:33 -net tap,ifname=vnet0.0,script=/etc/qemu-natup,downscript=/etc/qemu-natdown -daemonize
net.ipv4.ip_forward = 1
VNC server running on `127.0.0.1:5900'


[root@kvm ~]# qemu-kvm -smp 1 -m 512 -cpu host -drive file=/images/centos7-1.img,if=virtio,media=disk,cache=writeback -net nic,model=virtio,macaddr=52:54:00:11:22:34 -net tap,ifname=vnet0.1,script=/etc/qemu-natup,downscript=/etc/qemu-natdown -daemonize
br0        8000.9acac824e624    no        vnet0.0
VNC server running on `127.0.0.1:5901'

 

檢視兩臺虛擬機器的後半段網路卡都連線在橋br0上,在通過POSTROUTING鏈進行源地址轉換。

 

[root@kvm ~]# brctl show
bridge name    bridge id        STP enabled    interfaces
br0        8000.9acac824e624    no        vnet0.0
                                    vnet0.1


[root@kvm ~]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
    link/ether 00:0c:29:7b:9f:8c brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.11/24 brd 10.0.0.255 scope global eno16777736
       valid_lft forever preferred_lft forever
6: vnet0.0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 500
    link/ether 9a:ca:c8:24:e6:24 brd ff:ff:ff:ff:ff:ff
7: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 9a:ca:c8:24:e6:24 brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.1/24 scope global br0
       valid_lft forever preferred_lft forever
8: vnet0.1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 500
    link/ether f6:6c:f7:34:91:d4 brd ff:ff:ff:ff:ff:ff


[root@kvm ~]# iptables -L -n -t nat 
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination         

Chain INPUT (policy ACCEPT)
target     prot opt source               destination         

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination         

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination         
MASQUERADE  all  --  192.168.100.0/24    !192.168.100.0/24 

分別給兩臺虛擬機器配置ip地址,命令如下:

ip addr add 192.168.100.20/24 dev eth0 
ip addr add 192.168.100.30/24 dev eth0

 

 

兩臺虛擬機器之間實現互通了,配置預設路由為br0地址,實現公網的訪問。

路由配置如下:

ip route add default via 192.168.100.1

 

 

kvm-nat模型實現成功。

 

    3. 橋接模式

        在該模式下,宿主機會虛擬出來一張虛擬網路卡作為宿主機本身的通訊網路卡,而宿主機的物理網路卡則成為橋裝置(交換機),所以虛擬機器相當於在宿主機所在區域網內的一個單獨的主機,他的行為和宿主機是同等地位的,沒有依存關係。

 

    3.1 使用qemu-kvm建立橋接模式

 

為宿主機建立虛擬網路卡,並將物理網路卡作為橋裝置

[root@kvm ~]# cd /etc/sysconfig/network-scripts/
[root@kvm network-scripts]# cp -a ifcfg-eno16777736 ifcfg-br0
[root@kvm network-scripts]# vim ifcfg-eno16777736

TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
NAME=eno16777736
UUID=9f0bf158-e598-4309-8c0c-7609174ff212
DEVICE=eno16777736
ONBOOT=yes
BRIDGE=br0

[root@kvm network-scripts]# vim ifcfg-br0 

TYPE=Bridge
BOOTPROTO=none
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=no
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=10.0.0.11
NETMASK=255.255.255.0
GATEWAY=10.0.0.1
DNS1=10.0.0.1
DNS2=114.114.114.114


[root@kvm network-scripts]# systemctl restart network 
[root@kvm network-scripts]# ip a 
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN 
    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
2: eno16777736: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP qlen 1000
    link/ether 00:0c:29:7b:9f:8c brd ff:ff:ff:ff:ff:ff
5: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
    link/ether 00:0c:29:7b:9f:8c brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.11/24 brd 10.0.0.255 scope global br0
       valid_lft forever preferred_lft forever


[root@kvm network-scripts]# brctl show
bridge name    bridge id        STP enabled    interfaces
br0        8000.000c297b9f8c    no        eno16777736

物理網路卡eno16777736 將作為交換機使用,沒有ip地址

編寫虛擬機器啟動指令碼,該指令碼和隔離模式指令碼一致:

[root@kvm network-scripts]# vim /etc/qemu-ifup 

#!/bin/bash
#
BRIDGE=br0
if [ -n $1 ]; then
    ip link set $1 up
    sleep 1
    brctl addif $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
    echo "Error: no interface specified."
exit 1
fi

啟動虛擬機器

[root@kvm network-scripts]# qemu-kvm -smp 1 -m 512 -cpu host -drive file=/images/centos7-1.img,if=virtio,media=disk,cache=writeback -net nic,model=virtio,macaddr=52:54:00:11:22:34 -net tap,ifname=vnet0.1,script=/etc/qemu-ifup -daemonize
VNC server running on `127.0.0.1:5900'

 

 


橋接模式完成。  以上為KVM最簡單是4種網路模型,最為常見的是橋接模型。虛擬化環境中,目前見過最多的就是使用橋接模型。現在流行的docker一般是基於nat模型實現的。

相關文章