虚拟化是云计算的基石,抛开虚拟化谈云计算无异于缘木求鱼,不得要领。

虚拟化简介

虚拟化是一种技术,它是对物理硬件资源的虚拟。通过虚拟化使得应用运行在虚拟化之后的虚拟机上,达到充分利用物理资源的目的。
 
根据虚拟化的类型可将虚拟化分为 I 型虚拟化和 II 型虚拟化。I 型虚拟化是直接作用于裸机上的,如 Xen 等虚拟化技术。II 型虚拟化是在操作系统之上的虚拟化,如 qemu-kvm,HyperV 等虚拟化技术。
 
根据虚拟化技术可将虚拟化分为:全虚拟化,半虚拟化和硬件辅助的虚拟化。
 

全虚拟化

 
如上图所示,全虚拟化是通过 QEMU 的模拟代码来模拟 Guest 请求的虚拟化。全虚拟化需要经过捕获/拦截/模拟等一系列流程。
 
物理上的 CPU 作用在不同的运行级别上,分别是 Ring3,Ring2,一直到 Ring0。对于 kernel 的代码,CPU 是运行在 Ring0 级别,可以执行特权指令,例如访问硬件资源等指令。而,作用在其它级别上时,CPU 是处于受限模式的。对于 QEMU 和 Guest 来说,CPU 在执行它们的指令时没有用 Ring0 级别去执行,当 Guest 执行 I/O 请求的时候,CPU 会报异常,这个异常会被内核模块的 KVM 捕获到,KVM 将该异常消息放入 I/O sharing page 中,然后通过 /dev/kvm 接口,告知 QEMU 去读取 sharing page 中的异常消息,QEMU 读取到该异常消息,通过自己的模拟代码来驱动内核中相应的设备模块实现 I/O 操作。当操作成功后,把结果放到 I/O sharing page 中,并通知 KVM 内核去读取该操作成功后,把结果,KVM 读取到该结果,将结果发给 Guest 的驱动程序实现整个 I/O 请求。
 
全虚拟化的指令都需要经过捕获/拦截/模拟的过程,很复杂,效率很低。
 

半虚拟化

 
如图所示,半虚拟化是对 Guest 的模块进行修改的虚拟化。现在的半虚拟化通常是基于 virtio 框架的虚拟化。在 Guest 中包含 virtio 的 Front-end,在 Host 上安装 virtio 的 Back-end。当有 I/O 请求时,Guest 上的前端 virtio driver 会直接和 Host 上的 virtio devcie 进行通信,实现对硬件资源的访问。
 
相比于 qemu 的全虚拟化,半虚拟化绕过了 QEMU ,从而少了指令捕获/拦截/模拟的过程,效率要更高。
 
完整的 Guest I/O 流程如下图所示: 
 

硬件辅助的全虚拟化

硬件辅助的全虚拟化最少需要硬件 CPU 支持。Intel VT 技术支持硬件辅助的全虚拟化方案,在使用时需要进入 BIOS 中打开 VT。
 
 
在硬件辅助的全虚拟化中,CPU 有两种执行模式,root 模式和 non-root 模式,对于 QEMU + kernel 代码的运行,CPU 是运行在 root 模式,而对于 Guest 代码的执行,CPU 运行在 non-root 模式。在 non-root 模式中,CPU 处于受限状态,只能执行限制的指令,无法执行特权指令。当 Guest 需要执行特权指令时,CPU 会从 non-root 模式切到 root 模式来执行该指令,此时 Guest 会被置于挂起状态。当执行完特权指令之后,退出到 non-root 模式,继续 Guest 的运行。
 
从 root 到 non-root 模式的切换叫 VM-Entry,从 non-root 到 root 模式的切换叫 VM-Exit。
 
相比于全虚拟化,硬件辅助的虚拟化不需要逐条翻译 Guest 指令,大部分指令都可以通过 CPU 执行,从而缩短了“流程”,提升了虚拟化的效率。
 

虚拟化原理

虚拟化从本质上来说是对 CPU / 内存 以及 I/O 资源的虚拟,使得 Guest 有自己的硬件资源,从 Guest 角度看,它就是一台独立的 server。
 
CPU 虚拟化
CPU 的虚拟化是通过 KVM 内核模块完成的,KVM 虚拟出 vCPU,Guest 上看到的 socket / core 实际上是绑定到 vCPU 上的。
 
vCPU 有三种模式,kernel / user 和 guest 模式,当 Guest 执行 I/O 相关的操作时,vCPU 是运行在 user 模式下的,当执行非 I/O 的用户空间操作,vCPU 是处在 guest 模式下的,当执行 kernel 代码时,vCPU 是处在 kernel 模式下的。
 
从 Host 上来看,Guest 就是一个 qemu-kvm 进程,而 Guest 上的 CPU 就是 qemu-kvm 上的一个线程,物理 CPU 会像调用普通进程一样调度它们。正因为 vCPU 是普通线程,所以它并不能真正代替 CPU 去执行 CPU 的指令,真正执行 Guest 上指令的还是 Host 上的物理 CPU。
 
从上图可以看到,vCPU 上的操作通过 CPU Scheduler 层层调度到指定的物理 CPU core 上执行,真正完成 Guest 操作的是物理 CPU(这也是为什么硬件辅助虚拟化最少需要物理 CPU 支持的原因)。
当然,可以通过绑核的机制实现 vCPU 和物理 CPU core 的绑定。
 

内存虚拟化

 
KVM 实现客户机内存的方式是,利用 mmap 系统调用,在 QEMU 主线程的虚拟地址空间中申明一段连续大小的空间用于客户机物理内存映射。
 
 
在 VM 中,进程的虚拟内存(VA)会映射到 VM 的物理内存(PA),而 PA 向下被映射到 Host 的机器内存(MA)。 但是 VM 操作系统不能直接实现 PA 到 MA 的映射,需要 VMM(KVM) 实现 PA 到 MA 的映射。
 
VMM 实现 PA 到 MA 的映射有两种方式:
1. 软件方式:通过影子页表技术实现内存地址的翻译;
2. 硬件方式:基于 CPU 的硬件辅助虚拟化,如 Intel 的 EPT 和 AMD 的 NPT 技术。
 

I/O 资源的虚拟化

I/O 资源的虚拟化,分为:
1. 设备模拟:在虚拟机监控器中模拟传统 I/O 设备的特性,比如在 QEMU 中模拟一个 Intel 的网卡和 IDE 硬盘驱动器,在客户机中就暴露为对应的硬件设备。客户机中的 I/O 请求都由虚拟机监控器捕获并模拟执行后返回给客户机(前面全虚拟化方式介绍的就是这种)。
2. 前后端驱动接口:在 VMM 和 VM 之间定义一种全新的适合于虚拟化环境的交互接口,常见的如 virtio 框架下,暴露给客户机的 virtio-net,virtio-blk 等网络和磁盘设备(前端设备),在 QEMU 中实现为相应的后端驱动。
3. 设备直接分配:将 Host 上的物理设备直接分配给 VM,如网卡或硬盘驱动器直接分配给 VM 等。
4. 设备共享分配:设备直接分配的 I/O 虚拟化分配的设备是极为有限的,设备共享分配将物理设备虚拟为多个虚拟机功能接口,该接口独立地分配给客户机使用,从而支持多个 VM 的设备分配。如 SRIOV 就是一种常见的设备共享分配的虚拟化 I/O 方式。
 

搭建 KVM 虚拟机

这里实现的是 qemu-kvm 硬件辅助的虚拟化方式。首先搭建虚拟化环境,打开 BIOS 中的 VT,编译 kvm 模块进内核,下载安装 qemu 软件,准备好 VMM 环境:
[root@localhost home]# lsmod | grep -i kvm
kvm_intel 170181 5
kvm 554609 1 kvm_intel
irqbypass 13503 15 kvm,vfio_pci
[root@localhost home]# rpm -qa | grep qemu
qemu-img-rhev-2.6.0-28.el7_3.6.x86_64
qemu-kvm-common-rhev-2.6.0-28.el7_3.6.x86_64
qemu-kvm-rhev-2.6.0-28.el7_3.6.x86_64
libvirt-daemon-driver-qemu-2.0.0-10.el7_3.4.x86_64
ipxe-roms-qemu-20160127-5.git6366fa7a.el7.noarch
 
环境准备好之后创建磁盘镜像,将操作系统加载到磁盘镜像中,通过 qemu-kvm 命令创建 VM:
[lianhua@localhost qemu-kvm]$ /usr/libexec/qemu-kvm -m 1G -smp 4 Virtualized.qcow2 -monitor stdio
QEMU 2.6.0 monitor - type 'help' for more information
(qemu) VNC server running on '::1;5900' (qemu) info status
VM status: running
(qemu) info cp
cpus cpustats
(qemu) info cpus
* CPU #0: pc=0xffffffff9141c0ee (halted) thread_id=825030
CPU #1: pc=0xffffffff9141c0ee (halted) thread_id=825031
CPU #2: pc=0xffffffff9141c0ee (halted) thread_id=825032
CPU #3: pc=0xffffffff9141c0ee (halted) thread_id=825033 [lianhua@localhost ~]$ ps -lef | grep -i qemu
2 S lianhua 825024 819281 32 80 0 - 537525 poll_s 16:56 pts/0 00:02:16 /usr/libexec/qemu-kvm -m 1G -smp 4 Virtualized.qcow2 -monitor stdio
 
这里磁盘镜像已经事先制作好了,通过 qemu-kvm 启动 VM,其中 -m 表示 VM 的运行内存;-smp 表示 VM 的 CPU 架构, -smp 4 表示有 4 个 core;-monitor 表示直接将 VMM monitor 重定向到当前命令行所在的标准输入输出设备上。
 
进入 monitor 中使用 info status 和 info cpus 查询 VM 的状态和 CPU 的使用情况。可以看到 CPU 其实是 Host 上的线程,CPU 0 对应的线程 id 是 825030,CPU 1 对应的线程 id 是 825031,依次类推...,而 VM 则是 Host 上的一个 qemu 进程,其进程 id 为 825024。
 
值得注意的是,即时使用一个空的磁盘镜像,qemu-kvm 还是能让它运行,但是可以想见,由于空磁盘镜像并没有安装操作系统,实际上是没有任何意义的(能想到的用处是测试 OpenStack 上 cinder / swift 组件是否正常,通常会使用一个测试镜像测试该镜像是否可以上传/安装/被 VM 使用):
[lianhua@localhost qemu-kvm]$ ll -h lianhua.raw
-rw-r--r--. 1 lianhua lianhua 20G Jul 5 16:52 lianhua.raw
[lianhua@localhost qemu-kvm]$ du lianhua.raw
0 lianhua.raw
[lianhua@localhost qemu-kvm]$ /usr/libexec/qemu-kvm -m 1G -smp 5 lianhua.raw -monitor stdio
WARNING: Image format was not specified for 'lianhua.raw' and probing guessed raw.
Automatically detecting the format is dangerous for raw images, write operations on block 0 will be restricted.
Specify the 'raw' format explicitly to remove the restrictions.
QEMU 2.6.0 monitor - type 'help' for more information
(qemu) VNC server running on '::1;5900' (qemu) info status
VM status: running
(qemu) info cpus
* CPU #0: pc=0x000000003fefa56a thread_id=888039
CPU #1: pc=0x00000000000fd374 (halted) thread_id=888041
CPU #2: pc=0x00000000000fd374 (halted) thread_id=888042
CPU #3: pc=0x00000000000fd374 (halted) thread_id=888043
CPU #4: pc=0x00000000000fd374 (halted) thread_id=888044
(qemu) info cpus
* CPU #0: pc=0x00000000000fc373 (halted) thread_id=888039
CPU #1: pc=0x00000000000fd374 (halted) thread_id=888041
CPU #2: pc=0x00000000000fd374 (halted) thread_id=888042
CPU #3: pc=0x00000000000fd374 (halted) thread_id=888043
CPU #4: pc=0x00000000000fd374 (halted) thread_id=888044

仔细看在创建 image 的时候, qemu 会聪明的不让镜像占用磁盘空间,而是等需要占用的时候再为它分配磁盘空间。使用 prealloction=full 选项可以在创建的时候为镜像分配磁盘空间。

 
 
 
 

KVM 学习笔记:再谈虚拟化的更多相关文章

  1. [ kvm ] 学习笔记 2:虚拟化基础

    1. 虚拟化概念 什么是虚拟化 虚拟化是使用所谓虚拟机管理程序从一台物理机上创建若干个虚拟机的过程.虚拟机的行为和运转方式与物理机一样,但它们会使用物理机的计算资源,如 CPU .内存和存储.虚拟机管 ...

  2. Java学习笔记——浅谈数据结构与Java集合框架(第一篇、List)

    横看成岭侧成峰,远近高低各不同.不识庐山真面目,只缘身在此山中. --苏轼 这一块儿学的是云里雾里,咱们先从简单的入手.逐渐的拨开迷雾见太阳.本次先做List集合的三个实现类的学习笔记 List特点: ...

  3. [ kvm ] 学习笔记 4:KVM 高级功能详解

    1. 半虚拟化驱动 1.1 virtio 概述 KVM 是必须使用硬件虚拟化辅助技术(如 Intel VT-x .AMD-V)的 Hypervisor,在CPU 运行效率方面有硬件支持,其效率是比较高 ...

  4. Python学习6——再谈抽象(面对对象编程)

    1.对象魔法 在面对对象编程中,术语对象大致意味着一系列数据(属性)以及一套访问和操作这些数据的方法. 使用对象而非全局变量以及函数的原因有多个,而最重要的好处不过以下几点: 多态:可对不同类型的对象 ...

  5. java设计模式学习笔记--浅谈设计模式

    设计模式的目的 编写软件的过程中,程序员面临着来自耦合性,内聚性以及可维护性,可扩展性,重用性,灵活性等多方面的挑战.设计模式为了让程序具有更好的 1.代码重用性(即:相同功能的代码,不用多次编写) ...

  6. [ kvm ] 学习笔记 1:Linux 操作系统及虚拟化

    1. 前言 一台计算机是由一堆硬件设备组合而成,在硬件之上是操作系统,操作系统与计算机硬件密不可分,操作系统用来管理所有的硬件资源提供服务,各个硬件设备是通过 总线 进行连接起来的: 在操作系统之上, ...

  7. [ kvm ] 学习笔记 8:Ovirt 基础及使用

    目录- 1. oVirt 功能介绍- 2. oVirt 安装部署    - 2.1 基础准备    - 2.2 安装 ovirt-engine    - 2.3 配置 kvm 主机    - 2.4 ...

  8. OpenStack学习笔记(一)----安装虚拟化工具

    下面的命令运行在操作系统Ubuntu 14.04上. 在开源软件里面,主要是采用KVM和Xen.尽管OpenStack对KVM和Xen都支持,但是OpenStack对KVM的支持明显要比Xen做得好, ...

  9. KVM 学习笔记

    查看虚拟化环境 (1)查看虚拟机环境 (2)查看kvm模块支持 (3)查看虚拟工具版本 (4)查看网桥

  10. [ kvm ] 学习笔记 7:KVM 虚拟机创建的几种方式

    通过对 qemu-kvm.libvirt 的学习,总结三种创建虚拟机的方式: (1)通过 qemu-kvm 创建 (2)通过 virt-install 创建 (3)通过 virt-manager 创建 ...

随机推荐

  1. 【已解决】nrm -g安装成功后不是全局应用(command not found: nrm)

    本机情况: 服务器系统:CentOS 8.1 nodejs版本:20 问题描述: 在命令行执行命令,npm install -g nrm,全局安装nrm. 安装之后,执行nrm ls 报command ...

  2. 聊聊流式数据湖Paimon(一)

    翻译自 Apache Paimon官方文档 概览 概述 Apache Paimon (incubating) 是一项流式数据湖存储技术,可以为用户提供高吞吐.低延迟的数据摄入.流式订阅以及实时查询能力 ...

  3. .NET开发中合理使用对象映射库,简化和提高工作效率

    前言 在日常开发中,我们常常需要将一个对象映射到另一个对象,这个过程中可能需要编写大量的重复性代码,如果每次都手动编写,不仅会影响开发效率,而且当项目越来越复杂,庞大的时候还容易出现错误.为了解决这个 ...

  4. 在arm架构的银河麒麟系统部署Redis

    以下是在arm架构的银河麒麟系统上部署Redis的详细步骤: 1. 创建文件夹 首先,在合适的位置创建必要的文件夹.在本例中,我们将创建/opt/redis和/usr/src/redis两个文件夹. ...

  5. MySQL|MySQL执行计划

    使用explain关键字可以模拟优化器执行SQL查询语句,从而知道MySQL是如何处理你的SQL语句的,分析你的查询语句或是表结构的性能瓶颈. explain执行计划包含的信息 每列的内容 列 含义 ...

  6. QRCoder1.4.3生成二维码,不依赖System.Drawing,解决"未能找到类型或命名空间名QRCode","及ImageFormatPng仅在windows上受支持"

    生成二维码1(简单) 包引用: <PackageReference Include="QRCoder" Version="1.4.3" /> usi ...

  7. 微软用它取代了`Nginx`吞吐量提升了百分之八十!

    Azure应用服务用YARP取代了Nginx,获得了80%以上的吞吐量.他们每天处理160B多个请求(1.9 m RPS).这是微软的一项了不起的技术创新. 首先我们来介绍一下什么是Yarp Yarp ...

  8. Git commit emoji 对照表

    emoji emoji代码 commit说明 (调色板) :art: 改进代码结构/代码格式 ️ (闪电) :zap: 提升性能 (赛马) :racehorse: 提升性能 (火焰) :fire: 移 ...

  9. 《语义增强可编程知识图谱SPG》白皮书

    语义増强可编程图谱框架:新一代知识图谱语义框架/引擎.SPG+LLM双驱架构及应用相关进展和应用.<语义增强可编程知识图谱SPG>白皮书 v1.0.pdf: https://url39.c ...

  10. 华为云MVP付健权:从机械工程师到AI开发者的华丽转身

    摘要:谁说AI开发难,看一个机械工程师是如何转型成为AI工程师的. 付健权,华为云MVP,企业上云导师.软通动力,售前解决方案经理,为制造业讲解华为云产品,为客户提供上云和云上解决方案.为企业提供大数 ...