如何為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並不會引起問題。
而增加第一個配置的原因可以從這個圖上看出來(來源:https://upload.wikimedia.org/wikipedia/commons/3/37/Netfilter-packet-flow.svg):
veth是路由一層的協議,不經過nat鏈在鏈路層布下的PREROUTING鉤子的,所以如果不在OUTPUT上做DNAT,就沒有DNAT了。
libvirt在這個問題上處理得好的話,應該把這種映射直接做在網路的XML配置中的,不過libvirt的應用場景和docker不一樣,前者通常是用vxlan連接多個跨節點的虛擬機的,不需要通過本地的Host做防火牆,所以這個功能就沒人弄了。但其實做單機測試和驗證這個功能卻很常用,希望圈內人士可以把這個功能加進去。
推薦閱讀:
TAG:iptables |