Libvirt 是目前使用最为广泛的异构虚拟化管理工具,由 libvirt API 函数库、libvirtd Daemon 这 2 个关键部分组成,还具有一个默认命令行管理工具 virsh。
Libvirt 采用了面向驱动的架构设计,北向提供了统一的虚拟化资源管理 API,南向通过不同的驱动程序来对接异构的底层虚拟化技术。同时,libvirt API 为多种高级编程语言都提供了编程接口,包括 C、Python、Java、Perl、Ruby 等,具有非常强的可扩展性。
除了官方提供的多种管理工具之外(包括:virsh CLI、virt-manager、virt-viewer、vist-install ),OpenStack 也通过 libvirt API 提供的跨虚拟化平台能力,可以同时支持 QEMU-KVM、VMware、Xen 等多种虚拟化实现。
libvirtd Daemon 是一个 Multi-Drivers 软件架构,围绕虚拟机这一核心对象提供了计算、存储、网络、安全、监控等虚拟化资源的管理功能。
libvirtd 的软件架构包括了以下核心组件:
为了保障 HostOS 的安全性,libvirtd 可以在 2 种权限模式下运行:
为了支持集群管理和虚拟机迁移功能,libvirtd 具有 2 种运行模式:
virsh list # 查看在运行的虚拟机。
virsh list --all # 查看所有虚拟机。
virsh console centos72 # 连接虚拟机的 Console。
virsh start centos72 # 启动虚拟机。
virsh reboot centos72 # 重新启动虚拟机。
virsh shutdown centos72 # 优雅关闭虚拟机。
virsh destroy centos72 # 强制关闭虚拟机。
virsh suspend centos72 # 暂停(挂起)虚拟机。
virsh resume centos72 # 恢复被挂起的虚拟机。
virsh undefine centos72 # 删除虚拟机的 XML 配置文件,但不删除虚拟机的磁盘文件。
virsh autostart centos72 # 设置虚拟机随物理机一同启动。
virsh autostart --disable centos72 # 取消虚拟机的开机自启动。
virsh dumpxml centos72 # 查看虚拟机的配置文件。
virsh edit centos72 # 编辑虚拟机的配置文件。
virsh setvcpus # 动态配置虚拟机的 CPU。
virsh setmaxmem # 动态配置虚拟机的 Memory。
libvirtd 使用 XML 格式来保存一个 VM 所有的配置信息,下面是一个简单的示例:
<domain type='kvm'>
<name>myvmname>
<memory unit='KiB'>1048576memory>
<vcpu placement='static'>2vcpu>
<os>
<type arch='x86_64' machine='pc-i440fx-2.9'>hvmtype>
<boot dev='hd'/>
os>
<devices>
<disk type='file' device='disk'>
<driver name='qemu' type='qcow2'/>
<source file='/var/lib/libvirt/images/myvm.qcow2'/>
<target dev='vda' bus='virtio'/>
disk>
<interface type='network'>
<mac address='52:54:00:9b:08:fa'/>
<source network='default'/>
<model type='virtio'/>
interface>
devices>
domain>
虚拟机的磁盘有多种类型,包括:软盘(Floppy)、硬盘(Hard Disk)、光驱(cdrom)等。
标签格式:
<disk type='XXX' device='XXX'>
示例:
<disk type='volume' device='disk'>
<driver name='qemu' type='raw'/>
<source pool='blk-pool0' volume='blk-pool0-vol0'/>
<target dev='hdk' bus='ide'/>
disk>
<disk type='file' device='disk' snapshot='external'>
<driver name="tap" type="aio" cache="default"/>
<source file='/var/lib/xen/images/fv0' startupPolicy='optional' />
<target dev='hda' bus='ide'/>
disk>
<disk type='block' device='cdrom'>
<driver name='qemu' type='raw'/>
<target dev='hdd' bus='ide' tray='open'/>
<readonly/>
disk>
<disk type='network' device='cdrom'>
<driver name='qemu' type='raw'/>
<source protocol="http" name="url_path">
<host name="hostname" port="80"/>
source>
<target dev='hde' bus='ide' tray='open'/>
<readonly/>
disk>
可以给 Libvirt 创建多种不同的 Networks,包括:Bridge、NAT、Route、Passthrough、hostdev 等等。
<network>
<name>host-bridgename>
<forward mode="bridge"/>
<bridge name="br0"/>
network>
<network>
<name>defaultname>
<bridge name="virbr0" />
<forward mode="nat"/>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.2" end="192.168.122.254" />
dhcp>
ip>
<ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
network>
<network>
<name>localname>
<bridge name="virbr1" />
<forward mode="route" dev="eth1"/>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.2" end="192.168.122.254" />
dhcp>
ip>
<ip family="ipv6" address="2001:db8:ca2:2::1" prefix="64" />
network>
<forward mode='passthrough'>
<interface dev='eth10'/>
<interface dev='eth11'/>
<interface dev='eth12'/>
<interface dev='eth13'/>
<interface dev='eth14'/>
forward>
<forward mode='hostdev' managed='yes'>
<driver name='vfio'/>
<address type='pci' domain='0' bus='4' slot='0' function='1'/>
<address type='pci' domain='0' bus='4' slot='0' function='2'/>
<address type='pci' domain='0' bus='4' slot='0' function='3'/>
forward>
支持多种不同类型的虚拟机网卡接口,包括:Network、Bridge、Direct、hostdev 等等。
<devices>
<interface type='network'>
<source network='default'/>
interface>
...
<interface type='network'>
<source network='default' portgroup='engineering'/>
<target dev='vnet7'/>
<mac address="00:11:22:33:44:55"/>
<virtualport>
<parameters instanceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
virtualport>
interface>
devices>
<interface type='bridge'>
<source bridge='br0'/>
</interface>
<interface type='bridge'>
<source bridge='br1'/>
<target dev='vnet7'/>
<mac address="00:11:22:33:44:55"/>
</interface>
<interface type='bridge'>
<source bridge='ovsbr'/>
<virtualport type='openvswitch'>
<parameters profileid='menial' interfaceid='09b11c53-8b5c-4eeb-8f00-d84eaa0aaa4f'/>
</virtualport>
</interface>
<interface type='direct' trustGuestRxFilters='no'>
<source dev='eth0' mode='vepa'/>
</interface>
<devices>
<interface type='hostdev' managed='yes'>
<driver name='vfio'/>
<source>
<address type='pci' domain='0x0000' 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>
针对不同的 hostdev 可以定义对应的主机设备分配方式。
# USB 设备直接分配
<hostdev mode='subsystem' type='usb'>
<source startupPolicy='optional'>
<vendor id='0x1234'/>
<product id='0xbeef'/>
source>
<boot order='2'/>
hostdev>
# PCI 设备直接分配
<hostdev mode='subsystem' type='pci' managed='yes'>
<source>
<address domain='0x0000' bus='0x06' slot='0x02' function='0x0'/>
source>
<boot order='1'/>
<rom bar='on' file='/etc/fake/boot.bin'/>
hostdev>
增:
查:
改:
删:
查:
改:
增:
查:
改:
删:
其他:
增:
查:
改:
删:
增:
查:
改:
删:
其他:
增:
查:
改:
删:
其他:
增:
查:
改:
删:
其他:
增:
查:
改:
删:
$ yum -y install wget
$ mkdir /etc/yum.repos.d/repo.bk
$ mv /etc/yum.repos.d/*.repo /etc/yum.repos.d/repo.bk
$ wget -O /etc/yum.repos.d/CentOS-Base.repo http://mirrors.aliyun.com/repo/Centos-7.repo
$ wget -O /etc/yum.repos.d/epel-7.repo http://mirrors.aliyun.com/repo/epel-7.repo
$ yum clean all
$ yum makecache
$ yum install -y epel-release
$ yum update -y && yum upgrade -y
如果 HostOS 本身就是一个 VM,那么就需要开启 KVM Nested 嵌套虚拟化,使得 HostOS 能够具有与 Host 相同的 CPU 硬件辅助虚拟化特性,才能够在 VM 里面嵌套运行 KVM 虚拟机。
KVM Nested 是一个可通过修改内核参数来启用的功能,它能够使一台 VM 与 Host 可以具相同的 CPU 特性,支持 vmx|svm(AMD) 硬件虚拟化,该特性需要 Linux 内核版本大于 Linux 3.x。
查看是否启动了 Nested:
$ cat /sys/module/kvm_intel/parameters/nested
Y
启用 Nested:
$ echo 'options kvm_intel nested=1' >/etc/modprobe.d/kvm-nested.conf
# 卸载内核模块
$ modprobe -r kvm_intel
# 重新加载内核模块
$ modprobe kvm_intel
NOTE:如果无法重载内核模块,可以考虑直接重启。
如果希望已经存在的 KVM 虚拟机支持嵌套虚拟化,则需要重新编辑虚拟机的 XML 文件,修改其 CPU mode。
# 关机
$ virsh shutdown domain-xxx
# 编辑
$ virsh edit domain-xxx
<cpu mode='host-passthrough'>
# 开机
$ virsh start domain-xxx
登录入虚拟机检查是否有 CPU 穿透:
$ egrep '(vmx|svm)' /proc/cpuinfo
flags : fpu vme de pse tsc msr pae mce cx8 apic sep mtrr pge mca cmov pat pse36 clflush mmx fxsr sse sse2 ss syscall nx pdpe1gb rdtscp lm constant_tsc arch_perfmon rep_good nopl eagerfpu pni pclmulqdq vmx ssse3 cx16 pcid sse4_1 sse4_2 x2apic popcnt tsc_deadline_timer aes xsave avx f16c rdrand hypervisor lahf_lm tpr_shadow vnmi flexpriority ept vpid fsgsbase tsc_adjust smep erms xsaveopt
$ yum groupinstall -y "X Window System"
$ yum groupinstall -y "GNOME Desktop" "Graphical Administration Tools"
$ init 5
$ cat /proc/cpuinfo | egrep 'vmx|svm'
$ setenforce 0
$ sed -i 's/=enforcing/=disabled/g' /etc/selinux/config
$ systemctl disable firewalld.service && systemctl stop firewalld.service && systemctl status firewalld.service
$ yum install -y qemu-kvm libvirt virt-manager virt-install bridge-utils
$ lsmod | grep kvm
# 修改 QEMU 配置,使 Root 用户有文件访问权限
$ vi /etc/libvirt/qemu.conf
...
user = "root"
group = "root"
$ systemctl start libvirtd && systemctl enable libvirtd && systemctl status libvirtd
相关安装包及其作用:
$ wget https://download.qemu.org/qemu-2.11.0.tar.xz
$ yum -y install gcc gcc-c++ automake libtool zlib-devel glib2-devel bzip2-devel libuuid-devel spice-protocol spice-server-devel usbredir-devel libaio-devel
$ tar xvJf qemu-2.11.0.tar.xz
$ cd qemu-2.11.0
$ yum install -y libseccomp libseccomp-devel
$ yum install -y numactl numactl-devel
$ ./configure --enable-seccomp --enable-numa --prefix=/usr/local/qemu.2.11 && make && make install
$ ln -s /usr/local/qemu.2.11/bin/qemu-system-x86_64 /usr/bin/qemu-kvm
$ ln -s /usr/local/qemu.2.11/bin/qemu-system-x86_64 /usr/libexec/qemu-kvm
$ ln -s /usr/local/qemu.2.11/bin/qemu-img /usr/bin/qemu-img
$ qemu-img --version
$ qemu-kvm -version