libvirt 的使用

原文地址:http://itxx.sinaapp.com/blog/content/86


0x001 libvirt網絡基本概念

libvirt默認使用了一個名爲default的nat網絡,這個網絡默認使用virbr0作爲橋接接口,使用dnsmasq來爲使用nat網絡的虛擬機提供dns及dhcp服務,dnsmasq生效後的配置文件默認保存在以下路徑:

/var/lib/libvirt/dnsmasq/default.hostsfile mac&&ip綁定的配置文件

/var/lib/libvirt/dnsmasq/default.leases dhcp分配到虛擬機的ip地址列表

/var/lib/libvirt/network/default.xml default網絡的配置文件

dnsmasq服務的啓動腳本在/etc/init.d/dnsmasq ,但是我們如果手動使用此腳本來啓動服務將會導致dnsmasq讀取其自己的配置文件來啓動此服務,因此這麼做是不推薦的,因爲這個服務完全由libvirtd在接管,

當libvirtd服務啓動的時候,它會將它管理的被標記爲autostart的network一併啓動起來,而啓動network的時候就會自動調用dnsmasq並賦予其適宜的配置文件來運行服務。

使用libvirt管理的網絡都會用到dnsmasq來產生相應的配置,比如定義了一個名爲route110的network,那麼這個route110將使用一個新的橋接接口virbr1來接入網絡,並使用dnsmasq產生名爲route110.hostsfile和route110.leases的配置文件。

其實這裏提到的virbr0和virbr1都是libvirt產生的虛擬網卡,其作用就相當於一個虛擬交換機,爲虛擬機提供網絡轉發服務。

0x002 逐漸深入

首先分析一下libvirt所能提供的網絡類型:isolated 和forwarding,其中,isolated意爲絕對隔離的網絡,也就是說處於此網絡內的虛擬機對於外界是隔離的,這種模式可以用到一些特殊的場合,比如

虛擬機只提供給內部使用,虛擬機只要求能相互通信而不需要與互聯網通信。

另外一類,forwarding,就是把虛擬機的數據forward到物理網絡實現與外部網絡進行通訊,其中forwarding又分爲兩種:nat和routed。

nat,就是把虛擬機的網絡數據在經過物理機網絡的時候進行ip僞裝,這樣所有虛擬機出去的網絡數據都相當於是物理機出去的數據,也就是說,我們可以分配給使用nat網絡的虛擬機一個內網ip,而這

個內網ip的虛擬機訪問出去的時候外部網絡看到的是物理機的公網ip,這樣做的用處就是實現多個虛擬機共享物理主機的公網ip,節省公網ip地址;如前所述,默認情況下libvirt已經提供了一個名爲default的

nat網絡,在不需要進行任何配置的情況下使用default網絡的虛擬機即可訪問互聯網,但是互聯網卻無法訪問虛擬機提供的服務,這是因爲default網絡只對虛擬機的數據包進行了僞裝,而沒有進行dnat和snat。

需要注意的是libvirt所實現的這種nat網絡是通過物理機的iptables規則來實現的,也即是在虛擬機數據經過nat表的postrouting鏈出去的時候對其進行了僞裝。

forwarding模式的另外一種,routed,就是將虛擬機的數據直接通過物理機route出去,和nat一樣,也是需要一個virbr虛擬網卡接口來與外面進行通信,這種模式的不同之處在於虛擬機的數據沒有經過僞裝便直接

交給了外部網絡,也就是說,使用route模式網絡的虛擬機可以使用公網ip地址,而物理機卻恰恰在這個時候完全可以使用一個內網ip而不對外提供訪問,這樣,虛擬機的網卡僅僅把物理機當作一個route數據的工具,

此模式應用的場合很多,比如需要讓虛擬機運行在一個dmz網絡中。但是使用route模式有諸多限制,例如物理機的網絡接口不夠用的情況下。

這裏需要注意的是,nat模式和route模式的區別僅僅在於前者使用了iptables對虛擬機的數據包進行了僞裝,而後者沒有。

0x003 Hack It

在實際的虛擬機使用過程中,我們可能會碰到下面的情況:

1 使用nat網絡的虛擬機也需要對外提供服務,

2 物理機只有一個網卡和一個ip,而我們現在既需要通過這個網卡來管理虛擬機,又需要使用這個網卡來提供route網絡。

當然你所能碰到的問題可能千奇百怪,也可能根本沒有碰到過此類bt問題。下面的內容只作爲分析和解決問題的思路,不能生搬。

在瞭解了libvirt的網絡管理模式之後,就可以自己動手解決這些限制,下面重點解釋第二種問題的解決方法:

首先假定route網絡使用的是virbr1虛擬網卡,而虛擬機使用virbr1來爲虛擬機提供服務,而我本機又有了一個br0作爲em1的橋接網卡來對外提供網絡服務,br0的ip是192.168.1.51

首先禁用br0:

ifdown br0

並配置br0的onboot爲no

配置文件爲onboot=no

然後我們定義了一個名爲route的網絡,virbr1的ip設置爲192.168.1.51 ,這樣做的目的是讓virbr1取代之前的br0.

<network>
<name>route</name>
<uuid>6224b437-386b-f510-11d5-58d58b1ce87a</uuid>
<forward mode='route'/>
<bridge name='virbr1' stp='on' delay='0' />
<mac address='52:54:00:C8:9F:07'/>
<ip address='192.168.1.51' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.1.128' end='192.168.1.254' />
</dhcp>
</ip>
</network>

virsh net-define route.xml

virsh net-start route

virsh net-autostart route

/etc/libvirt/qemu/networks/ virsh net-define的network會保存到這

/var/lib/libvirt/network/ net-start啓動了的network同時也會會保存到這

/etc/libvirt/qemu/networks/autostart/ net-autostart的network同時也會保存到這

接下來,我們需要修改em1的配置並將其橋接到virbr1上

ifcfg-em1

DEVICE="em1"
ONBOOT="yes"
BRIDGE=virbr1

接着啓動em1

ifup em1

至此em1就被橋接到了virbr1上,可以使用下面的命令檢查

brctl show

現在我們需要在本機添加一條默認路由,不然虛擬機是訪問不了外面的:

route add default gw 192.168.1.1 dev virbr1

這裏的192.168.1.1是真實的路由

ok,問題已經解決了。下面說說問題1的解決方法:

既然知道了nat出去的虛擬機只能訪問外網而外網卻不能訪問進來,nat又是通過iptables來做的,也就是當libvirt每次啓動的時候都會往iptables最前面插入自己的規則以保證nat的虛擬機能正常訪問外網,

那麼我們是不是可以通過修改iptables的規則來實現呢,比如我們需要一個內網ip的虛擬機對外提供80服務,那麼我們就把物理機的80端口映射到這臺虛擬機的80端口上,因爲我們的物理機是可以直接和虛擬機通信的,

只是外網不能而已,下面添加規則:

iptables -t nat -A PREROUTING -p tcp -i virbr1 --dport 80 -j DNAT --to-destination 192.168.122.2:80

這樣我們對外部訪問80端口進來的數據進行了dnat,而出去的我們不用snat,只需要再添加如下規則:

iptables -I FORWARD -i virbr1 -o virbr0 -p tcp -m state --state NEW -j ACCEPT

至此問題看似得到解決,但是我們忽略了一個關鍵的問題,那就是每當libvirt啓動的時候就會往表的最前面插入它自己的規則,而iptables的規則是有先後順序的,也就是說,我們自己添加的規則在libvirtd服務重啓之後即被

libvirt定義的規則所淹沒,怎麼辦呢,我現在只想到了這麼一個方法,直接修改libvirtd的啓動腳本,在它的規則生效之後插入我們自定義的規則:

vi /etc/init.d/libvirtd

start() {
echo -n $"Starting $SERVICE daemon: "
initctl_check

mkdir -p /var/cache/libvirt
rm -rf /var/cache/libvirt/*
KRB5_KTNAME=$KRB5_KTNAME daemon --pidfile $PIDFILE --check $SERVICE $PROCESS --daemon $LIBVIRTD_CONFIG_ARGS $LIBVIRTD_ARGS
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch /var/lock/subsys/$SERVICE
sleep 1
iptables -D FORWARD -i virbr1 -o virbr0 -p tcp -m state --state NEW -j ACCEPT
iptables -I FORWARD -i virbr1 -o virbr0 -p tcp -m state --state NEW -j ACCEPT

。。。 。。。

至此問題基本解決。

再一個問題,我們前面有發現route和nat的網絡區別僅僅是一個做了nat的iptables規則一個沒有,那麼我們可不可以自己在iptables裏面添加相應的規則將route網絡變身爲nat網絡呢?

答案肯定是可以的,只需要添加上下面的規則即可,原理還請觀看本文的同學自己分析,這裏假設我們route網絡給虛擬機分配的ip是192.168.100.0/24網段:

iptables -t nat -A POSTROUTING -s 192.168.100.0/24 -d ! 192.168.100.0/24 -j MASQUERADE

iptables -A FORWARD --destination 192.168.100.0/24 -m state --state RELATED,ESTABLISHED -j ACCEPT

這裏再添加一個可以手工啓動dnsmasq的小腳本

#!/bin/bash
brctl addbr routebr
ifconfig routebr 192.168.122.1 netmask 255.255.255.0
iptables -t nat -A POSTROUTING -s 192.168.122.0/24 -d ! 192.168.122.0/24 -j MASQUERADE
iptables -A FORWARD --destination 192.168.122.0/24 -m state --state RELATED,ESTABLISHED -j ACCEPT
/usr/sbin/dnsmasq \
--strict-order \
--bind-interfaces \
--pid-file=/usr/local/vps/network/default.pid \
--conf-file= \
--except-interface lo \
--listen-address 192.168.122.1 \
--dhcp-range 192.168.122.2,192.168.122.254 \
--dhcp-leasefile=/usr/local/vps/network/dnsmasq/default.leases \
--dhcp-lease-max=253 \
--dhcp-no-override \
--dhcp-hostsfile=/usr/local/vps/network/dnsmasq/default.hostsfile


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章