Libvirt --- networking

參考:https://wiki.libvirt.org/page/Networking


Networking

本文介紹了基于libvirt的應(yīng)用的通用網(wǎng)絡(luò)配置??捎糜谒刑摂M化,不管是Xen,KVM或者其他。

兩種方式 "virtual network" , "shared physical device"。前者在所有的發(fā)布版本上都是一致的,封裝好的,可以直接使用。后者需要自定義配置。

\color{steelblue}{Contents}
?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。

  1. 定義
    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)

  1. 停止guest運行

  2. 創(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
  1. chmod +x /etc/libvirt/hooks/qemu

  2. 重啟 libvirtd service.

  3. 啟動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è)置橋接。

  1. 使用NetworkManager 配置
    如果發(fā)行版有 NetworkManager, 原生支持橋接。文檔如下:
  1. 不使用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
  1. 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> 命令來編輯虛擬機配置文件

FAQ :http://wiki.libvirt.org/page/FAQ#Where_are_VM_config_files_stored.3F_How_do_I_edit_a_VM.27s_XML_config.3F


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的常用方式:

libvirt PCI Device Assignment

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配置有 兩個嚴格限制:

  1. 任何時候,當(dāng)guest啟動時指定的VF必須可用,即管理員必須永久的分配每個VF到單個guest。 (或者每次當(dāng)guest啟動的時候,賦予guest一個當(dāng)前未使用的VF's PCI address。)

  2. 如果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

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 虛擬化技術(shù)概覽KVM簡介KVM的管理操作 一、虛擬化技術(shù)概覽 (一)虛擬化技術(shù)類型: 主機虛擬化:xen, kvm...
    哈嘍別樣閱讀 2,018評論 0 5
  • 1. Libvirt 是什么 為什么需要Libvirt? Hypervisor 比如 qemu-kvm 的命令行虛...
    51reboot閱讀 4,746評論 0 6
  • 一、虛擬化分類 1、虛擬化是指通過虛擬化技術(shù)將一臺計算機虛擬為多臺邏輯計算機。在一臺計算機上同時運行多個邏輯計算機...
    WickJohn閱讀 2,280評論 0 3
  • 節(jié)選Devices 通常需要指定:1) 模擬器2) 磁盤3) 網(wǎng)卡4) 圖形界面接口 1) 模擬器 范例: QEM...
    偷油考拉閱讀 3,052評論 0 0
  • 寫下的日記都是回憶!泛黃的紙張,舊燈下的字跡,塵封后的往事。世人都喜歡美麗的奇跡,情感偏好卻總是負面的。 2005...
    人生相冊閱讀 457評論 1 1

友情鏈接更多精彩內(nèi)容