Libvirt --- networking

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


Networking

本文介绍了基于libvirt的应用的通用网络配置。可用于所有虚拟化,不管是Xen,KVM或者其他。

两种方式 "virtual network" , "shared physical device"。前者在所有的发布版本上都是一致的,封装好的,可以直接使用。后者需要自定义配置。

\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

每个标准libvirt安装都提供自带的NAT基础连接到虚机。这也被称为'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

当libvirt的default network运行,你可以看到一个独立的网桥设备。这个设备实际上没有任何物理接口,因为它使用NAT+转发 来连接外面的网络。不需要加任何接口。

# brctl show
bridge name bridge id       STP enabled interfaces
virbr0      8000.000000000000   yes

Libvirt会添加iptables rules到 INPUT, FORWARD, OUTPUT and POSTROUTING 规则链以允许guest的出入流量使用virbr0设备。它需要开启ip_forward。有些应用可能会禁用ip_forward,所以最好将如下配置添加到 /etc/sysctl.conf.

net.ipv4.ip_forward = 1

如果你在服务器上运行了dnsmasq,请参考 libvirtd and dnsmasq.

Guest configuration

如果host configuration完成了,guest就可以通过network name连到虚拟网络了。比如,如果要将一个guest连到'default'虚拟网络,你需要编辑该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地址是可选的,如果没有会自动创建。

Applying modifications to the network

有时候,需要在运行的时候编辑网络。最常见的场景,添加新的 static MAC+IP映射虚拟网络的DHCP server。如果你通过"virsh net-edit"编辑网络,任何变更在网络被销毁重启前不会生效,这会导致所有的guest丢失网络连接直到它们的网卡接口重新连接。

virsh net-update
幸运的是,有很多网络变更操作可以通过"virsh net-update"立即生效,比如上面提到的在DHCP绑定MAC+IP。
比如, 添加一个名字为"default"的静态DHCP地址映射连到网络,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配置的网络配置项:

   ip-dhcp-host
   ip-dhcp-range (add/delete only, no modify)
   forward-interface (add/delete only)
   portgroup
   dns-host
   dns-txt
   dns-srv

注意,命令行的最后内容(并非"--live --config")应该是你想要add/modify/delete的XML片段。
比如,"virsh net-update default add forward-interface"后面跟的XML应该类似于"<interface dev='eth20'/>"
(注意引号的使用 - 因为XML包含空格和字符转义,你必须用引号将真个XML片段包含起来,但这也意味着XML内只能使用单引号,或者反斜杠)

Arbitrary changes to the network

虽然很多配置变更可以使用 "virsh net-update",但是还有一些不可以。 在这种情况下,所有的guests只能断开网络知道网络重启。为了解决这个问题,一个可行的解决方案就是,在网络重启后,通过脚本自动挂载所有主机上的所有的接口。

脚本范例 (虽然很久之前用过,但是也有很多人报告失效了) is available here.

Forwarding Incoming Connections

默认,以 <forward mode='nat'/>方式通过虚拟网络连接的guest对外可以访问任何网络。但是进来的连接只允许来自当前host,同一libvirt network下的其他guests,其他的都被iptables拒绝了。

如果你想把NAT虚拟网后的一个服务发布出去,你可以给qemu设置一个 libvirt 的 "hook" 脚本,来安装必要的iptables规则转发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) 转发连接到guest的 host port 为 "HP"

(为使得guest's IP address 保持不变, 你可以给 guest OS 配置固定IP, 或者在 <dhcp> element内添加一个 <host> element。详情请参考 the libvirt network XML documentation address section)

  1. 停止guest运行

  2. 创建文件 /etc/libvirt/hooks/qemu (或在一个已经存在的hook script后追加如下内容), 内容类似 (根据你的情况替换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的标准Iptables rules会被重新加载, 导致变更了跟reject rule 有关的FORWARD rule 顺序, 那么在guest 停止和重启之前,这部分不工作了。 在libvirt-0.9.13 和 更新的版本,使用新"reconnect" hook , 在新版本的libvirt中,这个缺陷不存在了。 (不管怎么说, 这个 hook script 依然被认为是非常规操作---hack)。


Bridged networking (即 "shared physical device")

Host configuration

NAT连接使用方便,或者用于自动配置网络连接的情况。更高级的一些用户希望使用桥接方式,guest直接连到Lan网络。下面根据不同的发行版本或者OS版本,做了说明。

注意: 无线不可以使用桥接模式。
注意: 如果你配置桥接后,你发现你的网络连接挂了,不工作了,有可能是路由器/交换机屏蔽了“unauthorized switches”(比如,通过侦测BPDU包)。你需要配置主机网口工作为"switch"。

Fedora/RHEL Bridging
这部分展示如何通过标准网络初始化脚本和systemctl设置桥接。

  1. 使用NetworkManager 配置
    如果发行版有 NetworkManager, 原生支持桥接。文档如下:
  1. 不使用NetworkManager (for older distros)
    如果你的版本是2015年前的,NetworkManager 不支持桥接的设置,只能用传统的网络设置方式,并且不使用NetworkManager管理。( "NM_CONTROLLED=no" )
    彻底关闭NetworkManager也是可以的。
# chkconfig NetworkManager off
# chkconfig network on
# service NetworkManager stop
# service network start
  1. Creating network initscripts
    在 /etc/sysconfig/network-scripts 目录,创建两个配置文件。
    第一个文件 ifcfg-eth0定义了物理网络接口信息,并且指定归属网桥。
# cat > ifcfg-eth0 <<EOF
DEVICE=eth0
HWADDR=00:16:76:D6:C9:45
ONBOOT=yes
BRIDGE=br0
NM_CONTROLLED=no
EOF

将HWADDR更改为你的网卡MAC地址。你也可以配置设备的MTU。比如: MTU=9000。

第二个文件 ifcfg-br0 定义桥接设备:

# cat > ifcfg-br0 <<EOF
DEVICE=br0
TYPE=Bridge
BOOTPROTO=dhcp
ONBOOT=yes
DELAY=0
NM_CONTROLLED=no
EOF

WARNING: TYPE=Bridge 是区分大小写的。

配置完毕后,重启网络 (or reboot)

 # service network restart

最后,关闭桥接的网络过滤器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在桥接设备上转发所有:

# 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

现在,你有一个 "shared physical device"设备了, 可以用于guests直接接入LAN。

 # brctl show
 bridge name     bridge id               STP enabled     interfaces
 virbr0          8000.000000000000       yes
 br0             8000.000e0cb30550       yes             eth0

注意桥接是完全独立于 virbr0的,不要将物理设备绑定到virbr0。Virbr0仅用于NAT网络连接。

Debian/Ubuntu Bridging

Debian wiki bridging 的文档: https://wiki.debian.org/BridgeNetworkConnections

Guest configuration

要让虚拟机使用桥接,配置文件必须定义桥接。 Bridge to LAN
其实,可以通过bridge name 来配置连接。假设,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网络设备直接赋予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 使一个单一的功能单元(比如,一个以太网端口)能看起来像多个独立的物理设备,即支持SR-IOV 功能的物理设备能被配置为多个功能单元。

SRIOV 网卡可以提供多路"Virtual Functions" (VF),可以分别挂载给使用PCI设备的guests,并且每个都等效一个物理网卡。这允许许多guests通过直连PCI设备获得高性能,但是只使用一个物理插槽。

VFs可以给以传统方式<hostdev>分配挂载给guest,但是这个模式会有问题(不像那些常见网络设备), SRIOV VF 网络设备没有永久唯一的MAC地址,而是每次OS重启会分配一个新的不同的随机MAC地址。结果就是,即使每次guest分配了同一个VF,只要是guest重启了就会获得一个新MAC地址,这就导致guest会将其识别为一个新的硬件设备,需要重新配置网络配置文件。

可以在把VF赋予guest前就配置好MAC地址。但是在<hostdev> settings没有这个项目可以配置。 (因为 <hostdev>用于配置 generic PCI device, 它不能配置MAC地址。).
为了解决这个问题, libvirt-0.9.10 增加了一个新配置项<interface type='hostdev'> (documented here).。这个新接口类型运行在 <interface> 和 <hostdev>的混杂模式 - libvirt 首先做网络设备配置初始化 (比如设置MAC地址, and/or 以802.1Qbh协商), 然后再把PCI设备赋予guest。

为了使用 <interface type='hostdev'>, 你必须有SRIOV-capable 网卡, 主机支持Intel VT-d or AMD IOMMU 扩展,并且你必须知道你计划分配给VF的PCI地址 (see this document 怎么配置).

如上信息了解后,你可以编辑guest domain configuration来配置一个设备,参考如下:

 ...
 <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地址,会自动创建就和其他类型的interface设备一样 。 另外, 如果你连到一个802.11Qgh硬件交换设备只能使用<virtualport> element (802.11Qbg (即 "VEPA") switches 在这个模式不支持)).

当 guest 启动, 应该能看到一个已经配置好MAC地址的由物理设备提供的网络设备。 这个MAC地址在guest和host重启前保持不变。

SRIOV VFs 池的分配在libvirt <network> 的定义
把PCI地址赋予guest配置有 两个严格限制:

  1. 任何时候,当guest启动时指定的VF必须可用,即管理员必须永久的分配每个VF到单个guest。 (或者每次当guest启动的时候,赋予guest一个当前未使用的VF's PCI address。)

  2. 如果guest被移动到其他host,那台host必须在相同的PCI总线位置有相同的硬件。 (或者,在启动前修改guest配置)

从 libvirt 0.10.0 开始,这些都可以通过以 device pool创建libvirt network的方式避免。Device pool 包含SR-IOV的所有的 VFs信息, 然后配置guest调用这个网络;每当guest启动, 一个单独的 VF会从池内取出分配给guest;当guest关闭, VF将被返还到池内以供其他guest使用

如下是一个网络配置范例,一个定义在host上名为"eth3"的,SR-IOV设备VFs池。

 <network>
   <name>passthrough</name>
   <forward mode='hostdev' managed='yes'>
     <pf dev='eth3'/>
   </forward>
 </network>

要使用这个网络,将如上配置到 /tmp/passthrough.xml (使用你自己的SR-IOV device's PF替换 "eth3" ), 然后执行如下命令:

  virsh net-define /tmp/passthrough.xml
  virsh net-autostart passthrough
  virsh net-start passthrough.

虽然只有一个设备被显示出来, libvirt 会自动获得一个首次使用如下interface定义的guest的PF的所有VFs 清单 :

  <interface type='network'>
    <source network='passthrough'>
  </interface>

你可以在启动第一个使用该网络的guest后,执行 "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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,377评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,390评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,967评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,344评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,441评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,492评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,497评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,274评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,732评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,008评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,184评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,837评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,520评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,156评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,407评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,056评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,074评论 2 352

推荐阅读更多精彩内容

  • 虚拟化技术概览KVM简介KVM的管理操作 一、虚拟化技术概览 (一)虚拟化技术类型: 主机虚拟化:xen, kvm...
    哈喽别样阅读 1,801评论 0 5
  • 1. Libvirt 是什么 为什么需要Libvirt? Hypervisor 比如 qemu-kvm 的命令行虚...
    51reboot阅读 4,405评论 0 6
  • 一、虚拟化分类 1、虚拟化是指通过虚拟化技术将一台计算机虚拟为多台逻辑计算机。在一台计算机上同时运行多个逻辑计算机...
    WickJohn阅读 2,139评论 0 3
  • 节选Devices 通常需要指定:1) 模拟器2) 磁盘3) 网卡4) 图形界面接口 1) 模拟器 范例: QEM...
    偷油考拉阅读 2,658评论 0 0
  • 写下的日记都是回忆!泛黄的纸张,旧灯下的字迹,尘封后的往事。世人都喜欢美丽的奇迹,情感偏好却总是负面的。 2005...
    人生相册阅读 384评论 1 1