橋接:創建一個虛擬橋設備,將虛擬機連接至橋設備上,再給橋設備配置一個IP地址,作為宿主機與外部通信的地址,即可完成與外網的通信(一起使用物理網卡的硬件功能),不過此時虛擬機使用的公網地址;
隔離:僅將需要互相通信的虛擬機的后半段網卡添加到同一個虛擬的橋設備上,即可完成虛擬機之間的通信,且與外網乃至是物理機隔離;
路由:將虛擬機關聯至虛擬橋設備上,再給橋設備配置一個與虛擬機同段的ip地址(內網地址)作為虛擬機的網關(物理網卡是連接外網的,所以應該與內網IP地址不是一個段),最后再打開物理主機的核心轉達功能,即可讓虛擬機可以ping外部主機,但是外部主機無法發送相應包,因為外部主機沒有到達虛擬機的路由;
NAT:在路由模型的基礎上,為其配置SNAT規則,即可完成真正的虛擬機與外網通信,且自己使用的是內網地址;但是這樣還有一個問題,就是外網不能主動訪問內網的虛擬機,除非再為其配置DNAT規則;
Linux內核支持的隔離功能:
namespace(名稱空間):netns是在內核中實現的,使用iproute所提供的netsn這個OBJECT來對其進行管理;且Centos6所提供的iproute工具不具有此OBJECT,需要依賴於OpenStack Icehouse源(https://repos.fedorapeople.org/openstack/EOL/openstack-icehouse/epel-6/)來提供;
文件系統隔離:讓分離的多個空間都認為僅有自己在使用文件系統;
網絡隔離:主要用於實現網絡資源的隔離,包括隔離網絡設備、IPV4及IPV6地址、IP路由表、防火牆、/proc/net、/sys/class/net以及套接字等;
IPC隔離:各個被分離的空間中的進程互不影響,不可通信;
用戶和用戶組隔離
PID隔離:對各名稱空間中的PID進行重新標號,兩個不懂的名稱空間可以使用相同的PID號;
UTS隔離:提供主機名和域名的隔離;
NETNS:
ip netns list:顯示名稱空間列表;
ip netns add NAME:添加一個名稱空間;
ip [-all] netns delete [NAME]:刪除名稱空間;
ip [-all] netns exec [NAME] cmd ...:在指定名稱空間中運行命令;
例子:~]# ip netns exec r1 ifconfig -a
ip link set { DEVICE | dev DEVICE | group DEVGROUP } [ netns { PID | NAME } ]:將某個網卡設備分配個某個名稱空間;
ip link add DEVICE1 type TYPE(此處為veth) peer name DEVICE2:創建一對虛擬網卡;
TYPE := { vlan | veth | vcan | dummy | ifb | macvlan | macvtap |
bridge | bond | ipoib | ipip | sit | vxlan |gre | gretap |vti | nlmon |bond_slave | geneve | bridge_slave | macsec }
cgroups:
用於完成資源配置,限制被各namespace隔離起來的資源;還可以為資源設置權重(比如某個名稱空間占用總資源的百分之80,另一個名稱空間僅占用總資源的百分之10,因為前者更重要或者他花的錢更多)、計算資源使用量、完成各種所需的管理任務等;
通過虛擬設備(OpenVSwitch)解決跨越物理主機的虛擬機通信問題:
在linux中我們可以通過創建成對的虛擬機網卡接口,然后將這些虛擬網卡接口與隔離出來的namespace相連接,從而在linux內部創建復雜的虛擬網絡;比如創建一對虛擬網卡(~]# ip link add veth1.1 type veth peer name veth1.2),再創建出一塊名稱空間(~]# ip netns add r1),將成對兒的虛擬機網卡的一端分配給名稱空間(~]# ip link set vetn1.2 netns r2),將另一端分配給宿主機上為虛擬機創建的虛擬橋設備,就可以實現類似將虛擬機連接至路由器(隔離出來的namespace就可以看成是一個路由器)的功能;
示例:
創建兩個KVM虛擬機,使其連接到一個名為br-in的虛擬橋設備(s)上,創建一個名稱為r1的namespace作為路由器,通過一對虛擬網卡(rinr,rins)將br-in與r1相連,使虛擬機可以通過r1與外網通信,再創建一對虛擬網卡(rexr,rexs),用於連接r1與同外網交互的虛擬網橋,從而實現與外網通信;
配置過程:
1.創建虛擬機並將虛擬機連接至橋br-in:
~]# brctl addbr br-in
~]# ip link set br-in up
~]# brctl addbr br-ex
~]# ip link set br-ex up
~]# ip addr del 192.168.0.8/24 dev ens34; ip addr add 192.168.0.8/24 dev br-ex; brctl addif br-ex ens34 將IP地址配置到橋設備上,使物理網卡作為硬件設備發送數據包;
~]# mkdir -pv /images/kvm/
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm1.qcow2
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm2.qcow2
~]# cat /etc/qemu-ifup
#!/bin/bash
BRIDGE=br-in
if [ -n "$1" ] ; then
ip link set $1 up
brctl addif $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No Interface specified."
exit 1
fi
~]# chmod +x /etc/qemu-ifup
~]# qemu-kvm -m 128 -smp 2 -name kvm1 -drive file=/images/kvm/kvm1.qcow2,if=virtio,media=disk -net nic,macaddr=52:54:00:12:34:55 -net tap,ifname=vif1.0,script=/etc/qemu-ifup -nographic
登錄虛擬機,為KVM1配置ip地址:ifconfig eth1 10.0.1.1/24 up
~]# qemu-kvm -m 128 -smp 2 -name kvm2 -drive file=/images/kvm/kvm2.qcow2,if=virtio,media=disk -net nic,macaddr=52:54:00:12:34:66 -net tap,ifname=vif2.0,script=/etc/qemu-ifup -nographic
登錄虛擬機,為KVM2配置ip地址:ifconfig eth1 10.0.1.2/24 up
2.創建作為路由器的namespace(創建namespace之前要打開物理機的核心轉發功能:~]# echo 1 > /proc/sys/net/ipv4/ip_forward):
~]# ip netns add r1 創建一個namespace
~]# ip link add rinr type veth peer name rins 添加一個對兒用於連接內網的網卡
~]# ip link show
~]# ip link set rinr up
~]# ip link set rins up
~]# brctl addif br-in rins 將路由器與內網交換機相連
~]# ip link set rinr netns r1 將內網成對兒網卡的一端添加至路由器(r1)
~]# ip netns exec r1 ip link set rinr name eth0
~]# ip netns exec r1 ip link set eth0 up
~]# ip netns exec r1 ip addr add 10.0.1.254/24 dev eth0 設置路由器對內網的接口的IP地址,且作為虛擬機的網關(回到虛擬機里面設置網關:~]# route add default gw 10.0.1.25)
~]# ip link add rexr type veth peer name rexs 添加一對兒用於連接外網的網卡
~]# brctl addif br-ex rexs 將路由器與同外網交互的虛擬網橋相連
~]# ip link set rexr netns r1 將外網成對兒網卡的一端添加至路由器(r1)
~]# ip netns exec r1 ip link set rexr name eth1
~]# ip netns exec r1 ip link set eth1 up
~]# ip netns exec r1 ip addr add 192.168.0.100/24 dev eth1 設置路由器對外網的接口的IP地址
Note:此時可以做一些ping測試,並且使用tcpdump抓包查看過程;此時虛擬機與外網是無法通信的,數據包只能出去,但是回不來;
~]# ip netns exec r1 iptables -t nat -A POSTROUTING -s 10.0.1.0/24 ! -d 10.0.1.0/24 -j SNAT --to-source 192.168.0.8 添加一條SNAT規則,此時虛擬機才可與外網互相通信;
~]# ip netns exec r1 dnsmasq --dhcp-range=10.0.1.100,10.0.1.120 為虛擬機配置DHCP,使其動態獲得地址
# udhcpc -R 虛擬機重新獲得IP地址
Note:上面的內容與OpenVswitch沒有直接關系,僅僅是展示linux本身也可以實現路由交換功能;
OpenVswitch:軟件模擬的交換機;
支持802.1q
支持NIC bonding
支持NetFlow,sFlow
支持Qos
支持GRE,Vxlan
……
OVS的組成部分:
ovs-vswitchd:OVS的守護進程,實現數據報文的交換功能,其與linux內核兼容模塊一起實現了基於流的交換技術;
ovsdb-server:輕量級的OVS數據庫服務,用於存儲OVS的配置信息;
ovs-dpctl:用於配置轉發規則;
ovs-vsctl:用於獲取或者更改ovs-vswitchd的配置信息,將修改信息保存至ovsdb-server中;
常用選項:
show:查看已配置的信息;
add-br BRIDGE:添加橋設備;
del-br BRIDGE:刪除橋設備;
add-port BRIDGE PORT:往橋設備上添加端口;
del-port [BRIDGE] PORT:從橋設備上刪除端口;
list-ports BRIDGE:顯示指定橋設備上的端口;
list-br:顯示當前主機上的所有已添加的橋設備;
list TBL [REC]:顯示指定表中的數據;
TBL可以為interface、port、br等
set TBL REC COL[:KEY]=VALUE:設置某個表中的某條數據的值;
例子:ovs-vsctl set port vif0.0(name字段) tag=10(欲修改字段)
remove TBL REC COL [KEY=]VALUE:將某個表中的某條數據的值移除;
例子:ovs-vsctl set port vif0.0 tag 10
示例1:
在Vmware中開啟一個虛擬機作為物理機,並且為其添加兩塊網卡;一塊作為管理接口(VMnat8),一塊作為物理機互相通信的接口(VMnat2自定義);接着在物理機中創建多個虛擬機,通過OpenVswitch的vlan功能使同一物理主機的相同vlan中的虛擬機通信;
配置過程:
~]# yum install openvswitch
~]# systemctl restart network.service
~]# ovs-vsctl add-br br-in 創建一個橋設備
~]# ovs-vsctl show
Bridge br-in:橋設備
Port br-in:端口,可以看作交換機上的物理端口
Interface br-in:接口,可以看作交換機上的端口號
type: internal:接口類型
~]# cat /etc/qemu-ifup
#!/bin/bash
BRIDGE=br-in
if [ -n "$1" ]; then
ip link set $1 up
sleep 1
ovs-vsctl add-port $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No port specified."
exit 2
fi
~]# cat /etc/qemu-ifdown
#!/bin/bash
BRIDGE=br-in
if [ -n "$1" ]; then
ip link set $1 down
sleep 1
ovs-vsctl del-port $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No port specified."
exit 2
fi
~]# chmod +x /etc/qemu-ifdown /etc/qemu-ifup
~]# mkdir -pv /images/kvm/
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm1.qcow2
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm2.qcow2
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm3.qcow2
~]# qemu-kvm -m 128 -smp 2 -name vm1 -drive file=/images/kvm/kvm1.qcow2,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:11:22:33 -net tap,ifname=vif0.0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -nographic
~]# qemu-kvm -m 128 -smp 2 -name vm2 -drive file=/images/kvm/kvm2.qcow2,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:11:22:55 -net tap,ifname=vif1.0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -nographic
vm1:# ifconfig eth0 10.0.10.1/24 up 為vm1配置IP地址
vm2:# ifconfig eth0 10.0.10.2/24 up 為vm2配置IP地址
Note:可以互ping一下,看網絡是否暢通;
~]# ovs-vsctl list port 查看接口的vlan tag值;
~]# ovs-vsctl set port vif0.0 tag=10 設置vif0.0接口的tag值為10,即將其添加至vlan10中;
~]# ovs-vsctl list port 再查看一下接口的vlan tag值,發現已經更改;
Note:在讓vm1與vm2互ping一下,發現已經ping不通了;
~]# ovs-vsctl add-br br-test 再添加一個橋設備
~]# cat /etc/qemu-ifup2
#!/bin/bash
BRIDGE="br-test"
if [ -n "$1" ]; then
ip link set $1 up
sleep 1
ovs-vsctl add-port $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No port specified."
exit 2
fi
~]# cat /etc/qemu-ifdown2
#!/bin/bash
BRIDGE="br-test"
if [ -n "$1" ]; then
ip link set $1 down
sleep 1
ovs-vsctl del-port $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No port specified."
exit 2
fi
~]# qemu-kvm -m 128 -smp 2 -name vm3 -drive file=/images/kvm/kvm3.qcow2,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:11:22:55 -net tap,ifname=vif2.0,script=/etc/qemu-ifup2,downscript=/etc/qemu-ifdown2 -nographic
# ifconfig eth0 10.0.10.3/24 up
~]# ip link add s0 type veth peer name s1 添加一對兒連接br-in與br-test的網卡
~]# ip link set s0 up
~]# ip link set s1 up
~]# ovs-vsctl add-port br-in s0
~]# ovs-vsctl add-port br-test s1
將br-in與br-test連接起來,且接口默認就為trunk類型;但是兩個虛擬交換機上的虛擬機在都沒有添加vlan tag時是無法通信的,只有配置其為某一vlan才可以通信;
~]# ovs-vsctl set port vif2.0 tag=10 將vm3的vlan tag改為10
Note:用vm1 ping vm3發現可以通信,用vm2 ping vm3無法通信,至此目的完成;
示例2:
通過GRE技術連接使不在同一網段中的物理機中的虛擬機通信;
在Vmware中開啟兩個虛擬機作為物理機,並且為其添加兩塊網卡;一塊作為管理接口(VMnat8),一塊作為物理機互相通信的接口(VMnat2自定義);接着在物理機中創建多個虛擬機,通過OpenVswitch的vlan與GRE功能使不同物理主機的相同vlan中的虛擬機通信;
配置過程:
Host1:
~]# ip netns add r0 創建一個namespace名為r0
~]# ip link add sif0 type veth peer name rif0 添加一對兒網卡用於連接r0與br-in;
~]# ip link set sif0 up
~]# ip link set rif0 up
~]# ip link set rif0 netns r0 將其一端的網卡分配給r0
~]# ovs-vsctl add-port br-in sif0 將另一端連接至br-in
~]# ip netns exec r0 ip link set rif0 up
~]# ip netns exec r0 ip addr add 10.0.20.254/24 dev rif0
~]# ip netns exec r0 dnsmasq --dhcp-range=10.0.20.200,10.0.20.250,86400 --dhcp-option=option:router,10.0.20.154 在r0中配置dhcp服務,用於給Host1中的vm1與mv2以及Host2中的vm1分配IP地址;
~]# qemu-kvm -m 128 -smp 2 -name vm1 -drive file=/images/kvm/kvm1.qcow2,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:11:22:33 -net tap,ifname=vif0.0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -nographic
~]# qemu-kvm -m 128 -smp 2 -name vm2 -drive file=/images/kvm/kvm2.qcow2,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:11:22:55 -net tap,ifname=vif1.0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -nographic
vm1:# udhcpc -R 使虛擬機自動獲取IP地址;
vm2:# udhcpc -R
~]# ifconfig ens34 192.168.20.1/24 up 為VMnet2中的物理網卡配置IP地址;
~]# ovs-vsctl add-port br-in gre0 在br-in橋上添加一個名為gre0的端口;
~]# ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.20.2 將gre0端口的類型改為gre,並且指定遠端IP地址;
~]# ovs-vsctl list interface gre0
Host2:
~]# ovs-vsctl add-br br-in
~]# mkdir -pv /images/kvm/
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm1.qcow2
~]# cp cirros-no_cloud-0.3.0-x86_64-disk.img /images/kvm/kvm2.qcow2
~]# cat /etc/qemu-ifup
#!/bin/bash
BRIDGE=br-in
if [ -n "$1" ]; then
ip link set $1 up
sleep 1
ovs-vsctl add-port $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No port specified."
exit 2
fi
~]# cat /etc/qemu-ifdown
#!/bin/bash
BRIDGE=br-in
if [ -n "$1" ]; then
ip link set $1 down
sleep 1
ovs-vsctl del-port $BRIDGE $1
[ $? -eq 0 ] && exit 0 || exit 1
else
echo "Error:No port specified."
exit 2
fi
~]# chmod +x /etc/qemu-ifdown /etc/qemu-ifup
~]# qemu-kvm -m 128 -smp 2 -name vm1 -drive file=/images/kvm/kvm1.qcow2,media=disk,if=virtio -net nic,model=virtio,macaddr=52:54:00:11:22:66 -net tap,ifname=vif0.0,script=/etc/qemu-ifup,downscript=/etc/qemu-ifdown -nographic
~]# ifconfig ens34 192.168.20.2/24 up
~]# ovs-vsctl add-port br-in gre0 在br-in橋上添加一個名為gre0的端口;
~]# ovs-vsctl set interface gre0 type=gre options:remote_ip=192.168.20.1 將gre0端口的類型改為gre,並且指定遠端IP地址;
Note:現在Host2中的vm1虛擬機也可以通過Host1中的r0中的dnsmasq獲取IP地址了(別忘記關閉防火牆);且Host1與Host2中的虛擬機都是互通的;
在Host1的ens34上的抓包結果:
現在我們已經啟動了三個虛擬機,其中Host1中有vm1和vm2,Host2中有vm1,且三者可以互通;我們可以通過vlan功能,讓Host1的vm2與Host2中的vm1通信,但是Host1的vm1卻不能與自己的 vm2通信;但是因為示例1已經演示過了,這里就不贅述了!!!
示例3:
通過VxLAN技術實現不同物理主機上的虛擬機互通;
相比於VLAN,VxLAN可以支持更多的vlan;且VxLAN可以完成類似GRE(隧道)的功能;
拓撲同示例2
配置過程:
在示例2的基礎上繼續配置(沒有添加vlan控制);
Host1:
~]# ovs-vsctl del-port gre0
~]# ovs-vsctl add-port br-in vx0 -- set interface vx0 type=vxlan options:remote_ip=192.168.20.2
Host2:
~]# ovs-vsctl del-port gre0
~]# ovs-vsctl add-port br-in vx0 -- set interface vx0 type=vxlan options:remote_ip=192.168.20.1