參考:https://wiki.libvirt.org/page/Networking
Networking
本文介紹了基于libvirt的應(yīng)用的通用網(wǎng)絡(luò)配置??捎糜谒刑摂M化,不管是Xen,KVM或者其他。
兩種方式 "virtual network" , "shared physical device"。前者在所有的發(fā)布版本上都是一致的,封裝好的,可以直接使用。后者需要自定義配置。
?1 NAT forwarding (即 "virtual networks")
??1.1 Host configuration
??1.2 Guest configuration
??1.3 Applying modifications to the network
???1.3.1 virsh net-update
???1.3.2 Arbitrary changes to the network
??1.4 Forwarding Incoming Connections
?2 Bridged networking (即 "shared physical device")
??2.1 Host configuration
???2.1.1 Fedora/RHEL Bridging
????2.1.1.1 Using NetworkManager directly
????2.1.1.2 Disabling NetworkManager (for older distros)
????2.1.1.3 Creating network initscripts
???2.1.2 Debian/Ubuntu Bridging
??2.2 Guest configuration
?3 PCI Passthrough of host network devices
??3.1 Assignment with <hostdev>
??3.2 Assignment with <interface type='hostdev'> (SRIOV devices only)
??3.3 Assignment from a pool of SRIOV VFs in a libvirt <network> definition
?4 Other networking docs/links
NAT forwarding (即 "virtual networks")
Host configuration
每個標(biāo)準(zhǔn)libvirt安裝都提供自帶的NAT基礎(chǔ)連接到虛機。這也被稱為'default virtual network'。你可以通過如下操作查看:
# virsh net-list --all
Name State Autostart
-----------------------------------------
default active yes
如果沒有,那么如下的example XML config可以加載激活使用。
# virsh net-define /usr/share/libvirt/networks/default.xml
Network default defined from /usr/share/libvirt/networks/default.xml
# virsh net-autostart default
Network default marked as autostarted
# virsh net-start default
Network default started
當(dāng)libvirt的default network運行,你可以看到一個獨立的網(wǎng)橋設(shè)備。這個設(shè)備實際上沒有任何物理接口,因為它使用NAT+轉(zhuǎn)發(fā) 來連接外面的網(wǎng)絡(luò)。不需要加任何接口。
# brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.000000000000 yes
Libvirt會添加iptables rules到 INPUT, FORWARD, OUTPUT and POSTROUTING 規(guī)則鏈以允許guest的出入流量使用virbr0設(shè)備。它需要開啟ip_forward。有些應(yīng)用可能會禁用ip_forward,所以最好將如下配置添加到 /etc/sysctl.conf.
net.ipv4.ip_forward = 1
如果你在服務(wù)器上運行了dnsmasq,請參考 libvirtd and dnsmasq.
Guest configuration
如果host configuration完成了,guest就可以通過network name連到虛擬網(wǎng)絡(luò)了。比如,如果要將一個guest連到'default'虛擬網(wǎng)絡(luò),你需要編輯該guest的domain configuration file:
virsh edit <guest>
這里 <guest> 是guest的名字或者uuid。將如下代碼段添加到config文件:
<interface type='network'>
<source network='default'/>
<mac address='00:16:3e:1a:b3:4a'/>
</interface>
MAC地址是可選的,如果沒有會自動創(chuàng)建。
Applying modifications to the network
有時候,需要在運行的時候編輯網(wǎng)絡(luò)。最常見的場景,添加新的 static MAC+IP映射虛擬網(wǎng)絡(luò)的DHCP server。如果你通過"virsh net-edit"編輯網(wǎng)絡(luò),任何變更在網(wǎng)絡(luò)被銷毀重啟前不會生效,這會導(dǎo)致所有的guest丟失網(wǎng)絡(luò)連接直到它們的網(wǎng)卡接口重新連接。
virsh net-update
幸運的是,有很多網(wǎng)絡(luò)變更操作可以通過"virsh net-update"立即生效,比如上面提到的在DHCP綁定MAC+IP。
比如, 添加一個名字為"default"的靜態(tài)DHCP地址映射連到網(wǎng)絡(luò),MAC地址53:54:00:00:01映射到IP地址192.168.122.45,hostname為"bob",可以用如下命令:
virsh net-update default add ip-dhcp-host \
"<host mac='52:54:00:00:00:01' \
name='bob' ip='192.168.122.45' />" \
--live --config
virsh net-update子命令除了 "add", 還有"delete" ,"modify" (for some items),"add-first", "add-last"。
如下是可以使用virsh net-update配置的網(wǎng)絡(luò)配置項:
ip-dhcp-host
ip-dhcp-range (add/delete only, no modify)
forward-interface (add/delete only)
portgroup
dns-host
dns-txt
dns-srv
注意,命令行的最后內(nèi)容(并非"--live --config")應(yīng)該是你想要add/modify/delete的XML片段。
比如,"virsh net-update default add forward-interface"后面跟的XML應(yīng)該類似于"<interface dev='eth20'/>"
(注意引號的使用 - 因為XML包含空格和字符轉(zhuǎn)義,你必須用引號將真?zhèn)€XML片段包含起來,但這也意味著XML內(nèi)只能使用單引號,或者反斜杠)
Arbitrary changes to the network
雖然很多配置變更可以使用 "virsh net-update",但是還有一些不可以。 在這種情況下,所有的guests只能斷開網(wǎng)絡(luò)知道網(wǎng)絡(luò)重啟。為了解決這個問題,一個可行的解決方案就是,在網(wǎng)絡(luò)重啟后,通過腳本自動掛載所有主機上的所有的接口。
腳本范例 (雖然很久之前用過,但是也有很多人報告失效了) is available here.
Forwarding Incoming Connections
默認,以 <forward mode='nat'/>方式通過虛擬網(wǎng)絡(luò)連接的guest對外可以訪問任何網(wǎng)絡(luò)。但是進來的連接只允許來自當(dāng)前host,同一libvirt network下的其他guests,其他的都被iptables拒絕了。
如果你想把NAT虛擬網(wǎng)后的一個服務(wù)發(fā)布出去,你可以給qemu設(shè)置一個 libvirt 的 "hook" 腳本,來安裝必要的iptables規(guī)則轉(zhuǎn)發(fā)forward incoming connections to the host on any given port HP to port GP on the guest GNAME。
- 定義
a) guest 的 name 為 "G" (定義在 libvirt domain XML中)
b) guest 的IP地址 為 "I"
c) 接受連接的guest port 為 "GP"
d) 轉(zhuǎn)發(fā)連接到guest的 host port 為 "HP"
(為使得guest's IP address 保持不變, 你可以給 guest OS 配置固定IP, 或者在 <dhcp> element內(nèi)添加一個 <host> element。詳情請參考 the libvirt network XML documentation address section)
停止guest運行
創(chuàng)建文件 /etc/libvirt/hooks/qemu (或在一個已經(jīng)存在的hook script后追加如下內(nèi)容), 內(nèi)容類似 (根據(jù)你的情況替換GNAME, IP, GP, and HP 變量):
如下是basic script,或者參考"advanced" 版本 here or here's a python script
#!/bin/bash
# IMPORTANT: Change the "VM NAME" string to match your actual VM Name.
# In order to create rules to other VMs, just duplicate the below block and configure
# it accordingly.
if [ "${1}" = "VM NAME" ]; then
# Update the following variables to fit your setup
GUEST_IP=
GUEST_PORT=
HOST_PORT=
if [ "${2}" = "stopped" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -D FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -D PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
if [ "${2}" = "start" ] || [ "${2}" = "reconnect" ]; then
/sbin/iptables -I FORWARD -o virbr0 -d $GUEST_IP --dport $GUEST_PORT -j ACCEPT
/sbin/iptables -t nat -I PREROUTING -p tcp --dport $HOST_PORT -j DNAT --to $GUEST_IP:$GUEST_PORT
fi
fi
chmod +x /etc/libvirt/hooks/qemu
重啟 libvirtd service.
啟動guest.
(注意: 這個辦法是hack行為,在libvirt 0.9.13 版本前有瑕疵,如果libvirtd 在guest運行的時候重啟了, 所有的支撐virtual network的標(biāo)準(zhǔn)Iptables rules會被重新加載, 導(dǎo)致變更了跟reject rule 有關(guān)的FORWARD rule 順序, 那么在guest 停止和重啟之前,這部分不工作了。 在libvirt-0.9.13 和 更新的版本,使用新"reconnect" hook , 在新版本的libvirt中,這個缺陷不存在了。 (不管怎么說, 這個 hook script 依然被認為是非常規(guī)操作---hack)。
Bridged networking (即 "shared physical device")
Host configuration
NAT連接使用方便,或者用于自動配置網(wǎng)絡(luò)連接的情況。更高級的一些用戶希望使用橋接方式,guest直接連到Lan網(wǎng)絡(luò)。下面根據(jù)不同的發(fā)行版本或者OS版本,做了說明。
注意: 無線不可以使用橋接模式。
注意: 如果你配置橋接后,你發(fā)現(xiàn)你的網(wǎng)絡(luò)連接掛了,不工作了,有可能是路由器/交換機屏蔽了“unauthorized switches”(比如,通過偵測BPDU包)。你需要配置主機網(wǎng)口工作為"switch"。
Fedora/RHEL Bridging
這部分展示如何通過標(biāo)準(zhǔn)網(wǎng)絡(luò)初始化腳本和systemctl設(shè)置橋接。
- 使用NetworkManager 配置
如果發(fā)行版有 NetworkManager, 原生支持橋接。文檔如下:
- 使用 nm-connection-editor UI: https://www.happyassassin.net/2014/07/23/bridged-networking-for-libvirt-with-networkmanager-2014-fedora-21/
- 使用命令行: https://lukas.zapletalovi.com/2015/09/fedora-22-libvirt-with-bridge.html
- 不使用NetworkManager (for older distros)
如果你的版本是2015年前的,NetworkManager 不支持橋接的設(shè)置,只能用傳統(tǒng)的網(wǎng)絡(luò)設(shè)置方式,并且不使用NetworkManager管理。( "NM_CONTROLLED=no" )
徹底關(guān)閉NetworkManager也是可以的。
# chkconfig NetworkManager off
# chkconfig network on
# service NetworkManager stop
# service network start
- Creating network initscripts
在 /etc/sysconfig/network-scripts 目錄,創(chuàng)建兩個配置文件。
第一個文件ifcfg-eth0定義了物理網(wǎng)絡(luò)接口信息,并且指定歸屬網(wǎng)橋。
# cat > ifcfg-eth0 <<EOF
DEVICE=eth0
HWADDR=00:16:76:D6:C9:45
ONBOOT=yes
BRIDGE=br0
NM_CONTROLLED=no
EOF
將HWADDR更改為你的網(wǎng)卡MAC地址。你也可以配置設(shè)備的MTU。比如: MTU=9000。
第二個文件 ifcfg-br0 定義橋接設(shè)備:
# cat > ifcfg-br0 <<EOF
DEVICE=br0
TYPE=Bridge
BOOTPROTO=dhcp
ONBOOT=yes
DELAY=0
NM_CONTROLLED=no
EOF
WARNING: TYPE=Bridge 是區(qū)分大小寫的。
配置完畢后,重啟網(wǎng)絡(luò) (or reboot)
# service network restart
最后,關(guān)閉橋接的網(wǎng)絡(luò)過濾器netfilter。
# cat >> /etc/sysctl.conf <<EOF
net.bridge.bridge-nf-call-ip6tables = 0
net.bridge.bridge-nf-call-iptables = 0
net.bridge.bridge-nf-call-arptables = 0
EOF
# sysctl -p /etc/sysctl.conf
為了性能和安全,建議這么配置。 See Fedora bug #512206.
或者,你可以配置iptables在橋接設(shè)備上轉(zhuǎn)發(fā)所有:
# echo "-I FORWARD -m physdev --physdev-is-bridged -j ACCEPT" > /etc/sysconfig/iptables-forward-bridged
# lokkit --custom-rules=ipv4:filter:/etc/sysconfig/iptables-forward-bridged
# service libvirtd reload
現(xiàn)在,你有一個 "shared physical device"設(shè)備了, 可以用于guests直接接入LAN。
# brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.000000000000 yes
br0 8000.000e0cb30550 yes eth0
注意橋接是完全獨立于 virbr0的,不要將物理設(shè)備綁定到virbr0。Virbr0僅用于NAT網(wǎng)絡(luò)連接。
Debian/Ubuntu Bridging
Debian wiki bridging 的文檔: https://wiki.debian.org/BridgeNetworkConnections
Guest configuration
要讓虛擬機使用橋接,配置文件必須定義橋接。 Bridge to LAN
其實,可以通過bridge name 來配置連接。假設(shè),shared physical device 的 bridge 被定義為 “br0”,guest XML可以配置如下:
<interface type='bridge'>
<source bridge='br0'/>
<mac address='00:16:3e:1a:b3:4a'/>
<model type='virtio'/> # try this if you experience problems with VLANs
</interface>
mac address 是可選的,如果忽略將會自動生成。
使用 virsh edit <VM name> 命令來編輯虛擬機配置文件
PCI Passthrough of host network devices
還可以將主機的PCI網(wǎng)絡(luò)設(shè)備直接賦予guest。但是首先要保證主機支持 Intel VT-d or AMD IOMMU 擴展。
有兩種方式:
Assignment with <hostdev>
將 generic PCI device 掛載到guest的常用方式:
Assignment with <interface type='hostdev'> (SRIOV devices only)
SRIVO Single-root I/O virtualization,單根I/O虛擬化。SR-IOV 使一個單一的功能單元(比如,一個以太網(wǎng)端口)能看起來像多個獨立的物理設(shè)備,即支持SR-IOV 功能的物理設(shè)備能被配置為多個功能單元。
SRIOV 網(wǎng)卡可以提供多路"Virtual Functions" (VF),可以分別掛載給使用PCI設(shè)備的guests,并且每個都等效一個物理網(wǎng)卡。這允許許多guests通過直連PCI設(shè)備獲得高性能,但是只使用一個物理插槽。
VFs可以給以傳統(tǒng)方式<hostdev>分配掛載給guest,但是這個模式會有問題(不像那些常見網(wǎng)絡(luò)設(shè)備), SRIOV VF 網(wǎng)絡(luò)設(shè)備沒有永久唯一的MAC地址,而是每次OS重啟會分配一個新的不同的隨機MAC地址。結(jié)果就是,即使每次guest分配了同一個VF,只要是guest重啟了就會獲得一個新MAC地址,這就導(dǎo)致guest會將其識別為一個新的硬件設(shè)備,需要重新配置網(wǎng)絡(luò)配置文件。
可以在把VF賦予guest前就配置好MAC地址。但是在<hostdev> settings沒有這個項目可以配置。 (因為 <hostdev>用于配置 generic PCI device, 它不能配置MAC地址。).
為了解決這個問題, libvirt-0.9.10 增加了一個新配置項<interface type='hostdev'> (documented here).。這個新接口類型運行在 <interface> 和 <hostdev>的混雜模式 - libvirt 首先做網(wǎng)絡(luò)設(shè)備配置初始化 (比如設(shè)置MAC地址, and/or 以802.1Qbh協(xié)商), 然后再把PCI設(shè)備賦予guest。
為了使用 <interface type='hostdev'>, 你必須有SRIOV-capable 網(wǎng)卡, 主機支持Intel VT-d or AMD IOMMU 擴展,并且你必須知道你計劃分配給VF的PCI地址 (see this document 怎么配置).
如上信息了解后,你可以編輯guest domain configuration來配置一個設(shè)備,參考如下:
...
<devices>
...
<interface type='hostdev' managed='yes'>
<source>
<address type='pci' domain='0x0' bus='0x00' slot='0x07' function='0x0'/>
</source>
<mac address='52:54:00:6d:90:02'>
<virtualport type='802.1Qbh'>
<parameters profileid='finance'/>
</virtualport>
</interface>
...
</devices>
(注意,如果沒有提供mac地址,會自動創(chuàng)建就和其他類型的interface設(shè)備一樣 。 另外, 如果你連到一個802.11Qgh硬件交換設(shè)備只能使用<virtualport> element (802.11Qbg (即 "VEPA") switches 在這個模式不支持)).
當(dāng) guest 啟動, 應(yīng)該能看到一個已經(jīng)配置好MAC地址的由物理設(shè)備提供的網(wǎng)絡(luò)設(shè)備。 這個MAC地址在guest和host重啟前保持不變。
SRIOV VFs 池的分配在libvirt <network> 的定義
把PCI地址賦予guest配置有 兩個嚴格限制:
任何時候,當(dāng)guest啟動時指定的VF必須可用,即管理員必須永久的分配每個VF到單個guest。 (或者每次當(dāng)guest啟動的時候,賦予guest一個當(dāng)前未使用的VF's PCI address。)
如果guest被移動到其他host,那臺host必須在相同的PCI總線位置有相同的硬件。 (或者,在啟動前修改guest配置)
從 libvirt 0.10.0 開始,這些都可以通過以 device pool創(chuàng)建libvirt network的方式避免。Device pool 包含SR-IOV的所有的 VFs信息, 然后配置guest調(diào)用這個網(wǎng)絡(luò);每當(dāng)guest啟動, 一個單獨的 VF會從池內(nèi)取出分配給guest;當(dāng)guest關(guān)閉, VF將被返還到池內(nèi)以供其他guest使用
如下是一個網(wǎng)絡(luò)配置范例,一個定義在host上名為"eth3"的,SR-IOV設(shè)備VFs池。
<network>
<name>passthrough</name>
<forward mode='hostdev' managed='yes'>
<pf dev='eth3'/>
</forward>
</network>
要使用這個網(wǎng)絡(luò),將如上配置到 /tmp/passthrough.xml (使用你自己的SR-IOV device's PF替換 "eth3" ), 然后執(zhí)行如下命令:
virsh net-define /tmp/passthrough.xml
virsh net-autostart passthrough
virsh net-start passthrough.
雖然只有一個設(shè)備被顯示出來, libvirt 會自動獲得一個首次使用如下interface定義的guest的PF的所有VFs 清單 :
<interface type='network'>
<source network='passthrough'>
</interface>
你可以在啟動第一個使用該網(wǎng)絡(luò)的guest后,執(zhí)行 "virsh net-dumpxml passthrough"命令來確認; 類似如下輸出:
<network connections='1'>
<name>passthrough</name>
<uuid>a6b49429-d353-d7ad-3185-4451cc786437</uuid>
<forward mode='hostdev' managed='yes'>
<pf dev='eth3'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x1'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x3'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x5'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x10' function='0x7'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x1'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x3'/>
<address type='pci' domain='0x0000' bus='0x02' slot='0x11' function='0x5'/>
</forward>
</network>
Other networking docs/links
- David Lutterkort's guide. 注意, 'peth0' (physical) 和 'eth0' (bridge) 在 Fedora 9 不再生效了。由 'eth0' (physical) 和 'br0' (bridge) 替代。
- Anthony Liguori's guide . Debian的 'shared physical devices'
- manual KVM networking - 不使用libvirt加載guests的情況
- Ubuntu libvirt guide -網(wǎng)橋配置節(jié)選