標籤:

如何為libvirt設置虛擬主機

最近在ARM Server上分析虛擬機的數據壓力,其中一種場景類似Docker,要把guest中的埠映射到host中,類似對Docker Image中做這樣的動作:

docker run -p 8080:80 my_web_server

但libvirt沒有這樣的配置,只在手冊(Networking - Libvirt Wiki)中這樣建議:

iptables -I FORWARD -o virbr0 -d $GUEST_IP -j ACCEPTniptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORTn

但實際上你這樣做了,映射根本過不去。

所以,我和Docker的規則對了一下,發現區別在這個地方:

首先,DNAT不僅僅要對PREROUTING鏈來做,還要對OUTPUT鏈來做:

iptables -t nat -A OUTPUT -p tcp --dport $HOST_PORT -j DNAT --to-destination $GUEST_IP:$GUEST_IPn

第二,要給反向的包做SNAT:

iptables -t nat -A POSTROUTING -d $GUEST_IP -s $GUEST_IP -p tcp --dport $GUEST_PORT -j MASQUERADEn

這樣就通了。

深入分析一下,其實第二條是不需要的,因為如果你的機器使用默認的NAT網路,本來就有這個配置,而且,很多協議並不需要雙向連接,沒有SNAT並不會引起問題。

而增加第一個配置的原因可以從這個圖上看出來(來源:upload.wikimedia.org/wi):

veth是路由一層的協議,不經過nat鏈在鏈路層布下的PREROUTING鉤子的,所以如果不在OUTPUT上做DNAT,就沒有DNAT了。

libvirt在這個問題上處理得好的話,應該把這種映射直接做在網路的XML配置中的,不過libvirt的應用場景和docker不一樣,前者通常是用vxlan連接多個跨節點的虛擬機的,不需要通過本地的Host做防火牆,所以這個功能就沒人弄了。但其實做單機測試和驗證這個功能卻很常用,希望圈內人士可以把這個功能加進去。

推薦閱讀:

TAG:iptables |