kubevirt(一)虚拟化技术

在云计算领域我们经常能听到虚拟化(Virtualization)技术,到底什么是虚拟化技术呢?关于虚拟化的定义,我们能看到这样的术语:

虚拟化是一个广义的术语,在计算机方面通常是指计算元件在虚拟的基础上而不是真实的基础上运行。虚拟化技术可以扩大硬件的容量,简化软件的重新配置过程。CPU的虚拟化技术可以单CPU模拟多CPU 并行,允许一个平台同时运行多个操作系统,并且应用程序都可以在相互独立的空间内运行而互不影响,从而显著提高计算机的工作效率。

虚拟化技术一般来说包括:

  • CPU虚拟化
  • 内存虚拟化
  • 服务器虚拟化
  • 存储虚拟化
  • 网络虚拟化
  • 应用虚拟化

虚拟化技术的目的是通过隐藏特定计算平台的物理特性,为用户提供抽象的、统一的、模拟的计算环境,通常是虚拟机。虚拟机可以通过是否在裸机上部署分为面向主机的虚拟机和面向裸机的虚拟机。面向主机的虚拟机是指在一台已经安装操作系统的主机上安装虚拟机管理(VMM)程序,如VMware、Xen;而面向裸机的虚拟机是指在裸机上直接安装虚拟机管理程序,所有的虚拟机调用都是直接由虚拟机管理程序来负责,没有了操作系统这一步,在效率上一般要高于面向主机的虚拟机。

从硬件虚拟化角度来看,虚拟化又可以分为三大类:

  • Full Virtualization(全虚拟化): 几乎是完整的模拟一套真实的硬件设备,大部分操作系统无需进行任何修改即可直接运行在全虚拟化环境中,例如KVM技术。
  • Partial Virtualization(部分虚拟化): 仅仅提供了对关键性计算组件或者指令集的模型,操作系统可能需要做某些修改才能够运行在部分虚拟化环境中。
  • Paravirtualization(半虚拟化): 不对硬件设备进行模拟,虚拟机拥有独立的运行环境,通过虚拟机管理程序共享底层的硬件资源。大部分操作系统需要进行修改才能运行在半虚拟化环境中。半虚拟化的性能要稍微高于全虚拟化,像Xen。

并且,我们把最原始的宿主机(一般是物理机)称作host,在host上用虚拟化技术创建出来的虚拟机称作guest。基于这些背景,本文对kubevirt底层用到的三个虚拟化技术相关点qemukvmlibvirt做简单说明和实践。

Note

下文相关命令都是在一台有足够资源的物理机上操作的,读者如果自己动手参考操作,注意检查自己的机器信息,以及修改相关配置匹配自己实际的资源信息

qemu

qemu是一个开源纯软件实现的虚拟化模拟器,它可以实现在一个操作系统上通过模拟硬件资源运行一个完整的操作系统。qemu可模拟的硬件资源包括disk、network、VGA、PCI、USB、serial/parallel ports、cpu等。项目地址:https://github.com/qemu/qemu,先看看官方的说明:

QEMU is a generic and open source machine & userspace emulator and virtualizer.

QEMU is capable of emulating a complete machine in software without any need for hardware virtualization support. By using dynamic translation, it achieves very good performance. QEMU can also integrate with the Xen and KVM hypervisors to provide emulated hardware while allowing the hypervisor to manage the CPU. With hypervisor support, QEMU can achieve near native performance for CPUs. When QEMU emulates CPUs directly it is capable of running operating systems made for one machine (e.g. an ARMv7 board) on a different machine (e.g. an x86_64 PC board).

QEMU is also capable of providing userspace API virtualization for Linux and BSD kernel interfaces. This allows binaries compiled against one architecture ABI (e.g. the Linux PPC64 ABI) to be run on a host using a different architecture ABI (e.g. the Linux x86_64 ABI). This does not involve any hardware emulation, simply CPU and syscall emulation.

QEMU aims to fit into a variety of use cases. It can be invoked directly by users wishing to have full control over its behaviour and settings. It also aims to facilitate integration into higher level management layers, by providing a stable command line interface and monitor API. It is commonly invoked indirectly via the libvirt library when using open source applications such as oVirt, OpenStack and virt-manager.

qemu官方目前支持的CPU架构(CPU Architecture)和加速器(Accelerators)如下:

CPU Architecture Accelerators
Arm kvm (64 bit only), tcg, xen
MIPS kvm, tcg
PPC kvm, tcg
RISC-V tcg
s390x kvm, tcg
SPARC tcg
x86 hax, hvf (64 bit only), kvm, nvmm, tcg, whpx (64 bit only), xen
qemu安装

qemu可以用yum install qemu的方式安装,或者采用编译安装的方式安装,源码包和安装步骤可以参考qemu官网https://www.qemu.org/download/,相关步骤不再赘述,全编译时间比较长,可查找资料选择性编译。

安装完会有如下命令(输入qemu按tab键补全),本文仅需要用到qemu-imgqemu-system-x86_64两个命令:

# qemu-
qemu-aarch64              qemu-mips                 qemu-riscv64              qemu-system-microblaze    qemu-system-sh4eb
qemu-aarch64_be           qemu-mips64               qemu-s390x                qemu-system-microblazeel  qemu-system-sparc
qemu-alpha                qemu-mips64el             qemu-sh4                  qemu-system-mips          qemu-system-sparc64
qemu-arm                  qemu-mipsel               qemu-sh4eb                qemu-system-mips64        qemu-system-tricore
qemu-armeb                qemu-mipsn32              qemu-sparc                qemu-system-mips64el      qemu-system-unicore32
qemu-cris                 qemu-mipsn32el            qemu-sparc32plus          qemu-system-mipsel        qemu-system-x86_64
qemu-edid                 qemu-nbd                  qemu-sparc64              qemu-system-moxie         qemu-system-xtensa
qemu-ga                   qemu-nios2                qemu-system-aarch64       qemu-system-nios2         qemu-system-xtensaeb
qemu-hppa                 qemu-or1k                 qemu-system-alpha         qemu-system-or1k          qemu-tilegx
qemu-i386                 qemu-ppc                  qemu-system-arm           qemu-system-ppc           qemu-x86_64
qemu-img                  qemu-ppc64                qemu-system-cris          qemu-system-ppc64         qemu-xtensa
qemu-io                   qemu-ppc64abi32           qemu-system-hppa          qemu-system-riscv32       qemu-xtensaeb
qemu-m68k                 qemu-ppc64le              qemu-system-i386          qemu-system-riscv64       
qemu-microblaze           qemu-pr-helper            qemu-system-lm32          qemu-system-s390x         
qemu-microblazeel         qemu-riscv32              qemu-system-m68k          qemu-system-sh4

查看版本号:

# qemu-img --version
qemu-img version 4.2.1
Copyright (c) 2003-2019 Fabrice Bellard and the QEMU Project developers
qemu实践

先查看host信息:

# uname -a
Linux mb-control1 5.4.131-1.el7.elrepo.x86_64 #1 SMP Sun Jul 11 08:52:19 EDT 2021 x86_64 x86_64 x86_64 GNU/Linux
  • 创建虚拟机磁盘
# qemu-img create -f qcow2 archlinux.qcow2 4G
Formatting 'archlinux.qcow2', fmt=qcow2 size=4294967296 encryption=off cluster_size=65536 lazy_refcounts=off

# ls -al
total 204
drwxr-xr-x.  2 root root   4096 Sep  4 17:11 .
drwxr-xr-x. 22 root root   4096 Sep  4 17:02 ..
-rw-r--r--.  1 root root 197120 Sep  4 17:11 archlinux.qcow2

// 查看磁盘信息
# qemu-img info archlinux.qcow2 
image: archlinux.qcow2
file format: qcow2
virtual size: 4 GiB (4294967296 bytes)
disk size: 196 KiB
cluster_size: 65536
Format specific information:
    compat: 1.1
    lazy refcounts: false
    refcount bits: 16
    corrupt: false

创建一个4G大小的磁盘镜像,-f参数是指定镜像的格式,名称为archlinux.qcow2。

  • 准备guest操作系统的iso文件

下载一个操作系统的iso文件,本文以archlinux为例,先去官网(https://archlinux.org/download/)里边找到中国区加速站,下载archlinux.iso文件,并上传到做验证的host机器上:

# ls -al
total 813596
drwxr-xr-x.  2 root root      4096 Sep  4 17:20 .
drwxr-xr-x. 22 root root      4096 Sep  4 17:02 ..
-rw-r--r--.  1 root root    197120 Sep  4 17:11 archlinux.qcow2
-rw-r--r--.  1 root root 832909312 Sep  4 17:17 archlinux-x86_64.iso
  • 创建并访问qemu虚拟机

qemu虚拟机的访问方式可以参考https://blog.csdn.net/RichardYSteven/article/details/54807927,这里选取vnc的访问方式:

qemu-system-x86_64 archlinux.qcow2 \
  -cdrom archlinux-x86_64.iso \
  -m 4096 \
  -vnc :1

解释下上述命令参数含义:

  1. archlinux.qcow2:指定虚拟机的磁盘
  2. -cdrom archlinux-x86_64.iso:指定虚拟机镜像
  3. -m 4096:指定虚拟机的内存大小为4G
  4. -vnc :1:指定虚拟机vnc端口号,如果不指定vnc参数,默认vnc监听地址为127.0.0.1:5900,这里的“:1”表示监听端口为1+5900,即监听地址为":5901"
  • 查看虚拟机

我们先在host上查看虚拟机的信息:

# ps -ef|grep qemu
root     37484 26347 99 22:43 pts/4    00:08:14 qemu-system-x86_64 archlinux.qcow2 -cdrom archlinux-x86_64.iso -m 4096 -vnc :1

# netstat -ntlp|grep 37484
tcp        0      0 0.0.0.0:5901            0.0.0.0:*               LISTEN      37484/qemu-system-x 
tcp6       0      0 :::5901                 :::*                    LISTEN      37484/qemu-system-x

再通过vnc viewer工具连接到虚拟机(连接地址是{hostIP:5901}):

kubevirt(一)虚拟化技术_第1张图片
kubevirt(一)虚拟化技术_第2张图片

通过上面guest信息,可以看到虚拟机内网络和操作系统和host的差异,于是qemu guest和host可以看做如下关系:

kubevirt(一)虚拟化技术_第3张图片

kvm

kvm的全称是Kernel-Based Virtual Machine,对应的是2007年加进linux 2.26.20的内核的kvm.ko模块。kvm必须在具备Intel VT(对应kvm-intel.ko)或AMD-V(对应kvm-amd.ko)功能的x86平台上运行,是一种全虚拟化的解决方案。

kvm的功能包括:

  • 支持cpu和memory超分(overcommit)
  • 支持半虚拟化I/O(virtio)
  • 支持热插拔(cpu,块设备、网络设备等)
  • 支持对称多处理(Symmetric Multi-Processing,缩写为SMP)
  • 支持实时迁移(Live Migration)
  • 支持PCI设备直接分配和单根I/O虚拟化(SR-IOV)
  • 支持内核同页合并(KSM)
  • 支持NUMA(Non-Uniform Memory Access,非一致存储访问结构)

kvm可以看作是qemu可执行文件的一个分支,两个团队都积极努力将差异降至最低,并且在减少差异方面取得了进展,最终目标是qemu可以在任何地方运行。当前qemu团队更专注于硬件仿真和可移植性,而kvm团队则专注于内核模块以及与其余用户空间代码的接口。

qemu虚拟机是可以独立运行的,但是由于qemu完全是软件模拟硬件,在速度上比真正的硬件要差不少。为了解决速度问题,qemu允许使用kvm作为加速器,以便可以使用物理CPU虚拟化扩展。当qemu独立运行时,qemu模拟cpu、内存和硬件资源;当kvm和qemu协同工作时,kvm负责cpu和内存的访问,而qemu则模拟其它硬件资源。

再补充两个概念:

  • Type-1 hypervisor

Type-1 is a native or bare metal hypervisor that’s running directly on the host’s hardware

  • Type-2 hypervisor:

Type-2 is a hosted hypervisor, which means that it runs on a conventional operating system just as other computer programs would

基于上述概念,也可以这么理解qemu和kvm:qemu是在用户空间中运行并执行虚拟硬件仿真的Type-2 hypervisor,而kvm是在内核空间中运行的Type-1 hypevisor。

更详细内容可参考qemu官网架构图:

kubevirt(一)虚拟化技术_第4张图片

kvm加载

要使用kvm,需要先检查一下cpu是否支持虚拟化,可用如下命令查看:

# cat /proc/cpuinfo | grep -E "(svm|vmx)"

其中svm表示Secure Virtual Machine,是AMD的虚拟化技术AMD-V;vmx则是intel的虚拟化技术Intel-VT。

再看看kvm内核模块是否已加载:

# lsmod | grep kvm
kvm_intel             282624  0 
kvm                   663552  1 kvm_intel
irqbypass              16384  1 kvm

最后检查下kvm对外暴露的接口/dev/kvm:

# ls /dev/kvm -al
crw-------. 1 root root 10, 232 Sep  7 22:12 /dev/kvm

如果内核加载了kvm模块,qemu会通过ioctl /dev/kvm与其交互。

libvirt

libvirt源码在gitlab上:https://gitlab.com/libvirt/libvirt,github上也有代码mirror:https://github.com/libvirt/libvirt。

广义的libvirt应该包含多个语言版本的libvirt sdklibvirtd等内容,本文仅限于libvirtd。libvirtd是一个守护进程,本质上是对不同的hypervisor(如qemu、Xen、LXC等)操作做了封装,并且对外提供了统一的api接口,可以把libvirt看做是一个统一抽象层。

本文访问libvirt的客户端使用的是virsh——一个命令行工具,下文安装libvirt的时候会一起安装好。

通过上述内容,我们能知道virsh、libvirtd、qemu、kvm有如下的关系:

kubevirt(一)虚拟化技术_第5张图片

libvirt安装

libvirt可以源码编译安装,源码可去libvirt官网下载合适的版本:https://libvirt.org/sources/。也可以使用yum install的方式安装,这也是本文的安装方法:

# yum install libvirt virt-install -y

# systemctl enable libvirtd
# ps -ef|grep libvirt
root     24825 20264  0 22:12 pts/0    00:00:00 grep --color=auto libvirt
# systemctl start libvirtd
# ps -ef|grep libvirt
root     26552     1  0 22:12 ?        00:00:01 /usr/sbin/libvirtd
nobody   27562     1  0 22:12 ?        00:00:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
root     27563 27562  0 22:12 ?        00:00:00 /usr/sbin/dnsmasq --conf-file=/var/lib/libvirt/dnsmasq/default.conf --leasefile-ro --dhcp-script=/usr/libexec/libvirt_leaseshelper
root     72300 20264  0 22:16 pts/0    00:00:00 grep --color=auto libvirt

# virsh --version
4.5.0

libvirtd相关配置文件默路径在/etc/libvirt:

# ls /etc/libvirt/ -al
total 104
drwx------.   5 root root  4096 Sep  7 22:12 .
drwxr-xr-x. 129 root root 12288 Sep  8 00:13 ..
-rw-r--r--.   1 root root   450 Apr 28  2021 libvirt-admin.conf
-rw-r--r--.   1 root root   547 Apr 28  2021 libvirt.conf
-rw-r--r--.   1 root root 16529 Apr 28  2021 libvirtd.conf
-rw-r--r--.   1 root root  1175 Apr 28  2021 lxc.conf
drwx------.   2 root root  4096 Sep  7 22:12 nwfilter
drwx------.   3 root root  4096 Sep  7 22:07 qemu
-rw-r--r--.   1 root root 30306 Apr 28  2021 qemu.conf
-rw-r--r--.   1 root root  2169 Apr 28  2021 qemu-lockd.conf
drwx------.   2 root root  4096 Sep  7 22:12 secrets
-rw-r--r--.   1 root root  3202 Apr 28  2021 virtlockd.conf
-rw-r--r--.   1 root root  3247 Apr 28  2021 virtlogd.conf
libvirtd+qemu+kvm实践

我们基于前文的内容创建一个2C4G的虚拟机,这里用到的命令行工具是virt-install,virt-install会连接libvirtd:

# virt-install --name nuczzz \
  --connect qemu:///system \
  --ram=4096 \
  --vcpus=2 \
  --disk path=archlinux.qcow2 \
  --cdrom=archlinux-x86_64.iso \
  --vnc --vnclisten=0.0.0.0 --vncport=5902 \
  --network bridge=virbr0,model=virtio \
  --noautoconsole

相关参数释义:

-–name:指定虚拟机的名称
–-connect:指定虚拟机连接方式
–-ram:指定内存大小
–-vcpus:指定cpu的逻辑核数
–-disk:指定磁盘路径(即上文创建的虚拟磁盘)
–-cdrom:指定镜像
--vnc:指定vnc相关配置,vnc客户端可用该配置连接虚拟机
–-network:指定虚拟机配置信息
--noautoconsole:启动时不需要console界面

查看虚拟机相关信息:

// 查看虚拟机列表
# virsh list
 Id    Name                           State
----------------------------------------------------
 4     nuczzz                         running

// 查看虚拟机对应的qemu进程信息
# ps -ef|grep qemu
root     21402 17013  0 19:13 pts/1    00:00:00 grep --color=auto qemu
root     68536     1 49 19:10 ?        00:01:28 /usr/local/bin/qemu-system-x86_64 -name guest=nuczzz,debug-threads=on -S -object secret,id=masterKey0,format=raw,file=/var/lib/libvirt/qemu/domain-4-nuczzz/master-key.aes -machine pc-i440fx-4.2,accel=kvm,usb=off,dump-guest-core=off -cpu Skylake-Server-IBRS,ss=on,vmx=on,hypervisor=on,tsc_adjust=on,clflushopt=on,umip=on,pku=on,avx512vnni=on,md-clear=on,stibp=on,ssbd=on,xsaves=on,ibpb=on,hle=off,rtm=off -m 4096 -realtime mlock=off -smp 2,sockets=2,cores=1,threads=1 -uuid 1293c4e6-ca78-4657-b140-86c56bfd0d75 -no-user-config -nodefaults -chardev socket,id=charmonitor,fd=25,server,nowait -mon chardev=charmonitor,id=monitor,mode=control -rtc base=utc,driftfix=slew -global kvm-pit.lost_tick_policy=delay -no-hpet -no-reboot -global PIIX4_PM.disable_s3=1 -global PIIX4_PM.disable_s4=1 -boot strict=on -device ich9-usb-ehci1,id=usb,bus=pci.0,addr=0x4.0x7 -device ich9-usb-uhci1,masterbus=usb.0,firstport=0,bus=pci.0,multifunction=on,addr=0x4 -device ich9-usb-uhci2,masterbus=usb.0,firstport=2,bus=pci.0,addr=0x4.0x1 -device ich9-usb-uhci3,masterbus=usb.0,firstport=4,bus=pci.0,addr=0x4.0x2 -drive file=/root/nuczzz/vm/archlinux.qcow2,format=qcow2,if=none,id=drive-ide0-0-0 -device ide-hd,bus=ide.0,unit=0,drive=drive-ide0-0-0,id=ide0-0-0,bootindex=2 -drive file=/root/nuczzz/vm/archlinux-x86_64.iso,format=raw,if=none,id=drive-ide0-0-1,readonly=on -device ide-cd,bus=ide.0,unit=1,drive=drive-ide0-0-1,id=ide0-0-1,bootindex=1 -netdev tap,fd=28,id=hostnet0,vhost=on,vhostfd=29 -device virtio-net-pci,netdev=hostnet0,id=net0,mac=52:54:00:fa:35:f6,bus=pci.0,addr=0x3 -chardev pty,id=charserial0 -device isa-serial,chardev=charserial0,id=serial0 -vnc 0.0.0.0:2 -device cirrus-vga,id=video0,bus=pci.0,addr=0x2 -device virtio-balloon-pci,id=balloon0,bus=pci.0,addr=0x5 -msg timestamp=on

// 查看虚拟机qemu进程监听的端口号(即vnc端口号)
# netstat -ntlp|grep 68536
tcp        0      0 0.0.0.0:5902            0.0.0.0:*               LISTEN      68536/qemu-system-x

// 宿主机上查看虚拟机网络信息
# brctl show 
bridge name    bridge id          STP enabled    interfaces
virbr0         8000.52540065466f  yes            virbr0-nic
                                                 vnet0
# ip link show vnet0
13245: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master virbr0 state UNKNOWN mode DEFAULT group default qlen 1000
    link/ether fe:54:00:87:cd:f1 brd ff:ff:ff:ff:ff:ff

查看虚拟机cpu物理核信息:

kubevirt(一)虚拟化技术_第6张图片

查看虚拟机cpu逻辑核信息:

kubevirt(一)虚拟化技术_第7张图片

查看虚拟机内存信息:

kubevirt(一)虚拟化技术_第8张图片

查看虚拟机网络信息:

kubevirt(一)虚拟化技术_第9张图片

到这里一台通过libvirt+qemu+kvm虚拟机就创建好了(通过上面ps qemu进程信息中的accel=kvm可以看出使用了kvm加速),我们可以用virsh命令来管理虚拟机,virsh常用的命令如下:

virsh list: 查看虚拟机列表
virsh start vm_name: 启动名称为vm_name的虚拟机
virsh suspend vm_name: 挂起虚拟机
virsh resume vm_name: 恢复被挂起的虚拟机
virsh autostart vm_name: 开机启动虚拟机,以及在虚拟服务libvirt启动时启动虚拟机
virsh auto start --disable vm_name: 关闭开机启动虚拟机
virsh shutdown vm_name: 关闭虚拟机(需要ACPID服务的支持,ACPI是Advanced Configuration and PowerInterface缩写,高级配置和电源管理接口)
virsh reboot vm_name: 重启持久虚拟机
virsh reset vm_name: 强制重启虚拟机
virsh destroy vm_name: 强制关闭虚拟机,这种方式是从virsh list列表中将虚拟机删
除,仍然可以start起来
virsh net-start default: 启动默认的网络
virsh net-autostart default: 自启动默认网络

如果想彻底删除虚拟机,可以使用如下命令:

1、关闭虚拟机:virsh destroy vm_name
2、删除定义:virsh undefine vm_name

结束语

本文简单地介绍了一些虚拟化技术的术语,以及kvm、qemu、libvirt和virsh/virt-install简单实践,还有很多虚拟化的内容未提到,例如cpu/内存/IO虚拟化的原理和qemu虚拟机网络、存储的实现等。仅仅希望本文浅显的知识能作为kubevirt原理学习和虚拟化技术学习的基础,也敬请期待后续相关的文章。

微信公众号卡巴斯同步发布,欢迎大家关注。

你可能感兴趣的:(kubernetes,云计算)