云原生运维学习笔记:揭开虚拟化的硬核面纱,从底层架构到KVM实战

云原生运维学习笔记:揭开虚拟化的硬核面纱,从底层架构到KVM实战

第一阶段的Linux基础和云计算概览算是告一段落了。说实话,昨天刚看完那几份PPT的时候,我感觉脑子里塞满了各种名词:IaaS、VLAN、SAN、RAID......当时觉得云计算的底层真的是又碎又多。但今天进入虚拟化技术的课程,尤其是拿着《1021实际学习内容》这份文档仔细啃完之后,我突然有了一种"打通任督二脉"的感觉。

之前学服务器硬件、学操作系统,都是把一台物理机当成一个整体来看。而虚拟化技术,硬生生地把物理机的CPU、内存、I/O这些硬件资源拆成了"乐高积木",然后重新拼装成一个个虚拟机。这个过程背后的原理,尤其是CPU和内存的虚拟化,真的极其硬核。这篇博客我就抛开那些走马观花的泛泛而谈,紧扣我们今天实际学习的核心内容,把虚拟化的底层逻辑掰开揉碎了记录一下,顺便附上在Linux下用KVM/Libvirt动手实操的命令。


一、 虚拟化到底是个啥?(概念重塑)

在今天的《1021实际学习内容》里,开篇就给虚拟化定了调子:解除了物理硬件和操作系统之间的紧耦合关系。

以前一台服务器装一个Windows或Linux,应用就跑在这上面。现在我们在中间塞了一个叫Hypervisor(虚拟机监控器,VMM)的东西。它把底层的物理资源抽象成一个共享资源池,然后在上层虚拟出多台"Guest Machine"(虚拟机)。

这里面有几个必须刻在DNA里的概念:

  • Host OS / Host Machine:也就是宿主机,真实跑着的物理服务器和上面的操作系统。
  • Guest OS:跑在虚拟机里面的操作系统。
  • Hypervisor:核心大佬,虚拟化软件层。

为什么企业都要用虚拟化?文档里总结了四大特点,我觉得拿来做备忘录特别合适:

  1. 分区:一台物理机同时跑多台虚拟机,每台虚拟机都觉得自己独占了一台服务器。
  2. 隔离:虚拟机之间互不干扰。A虚拟机中毒了,B虚拟机该干嘛干嘛,资源也能通过控制确保不被某台虚拟机"吃独食"。
  3. 封装:整台虚拟机(硬件配置、BIOS、内存状态、磁盘状态)就相当于几个文件。拷贝文件就等于拷贝了整台服务器。
  4. 相对于硬件独立:虚拟机跑在虚拟化层上,底层物理机是IBM、Dell还是HP根本无所谓,直接无缝迁移。

虚拟化也分派系:全虚拟化 (不用改Guest OS,但性能有开销)、半虚拟化 (需要改Guest OS配合,性能好但兼容差)、硬件辅助虚拟化(靠CPU硬件支持,现在的绝对主流)。


二、 硬核拆解:CPU虚拟化到底难在哪?

这是今天最烧脑,也是最让我拍大腿的一节。

1. x86架构的"先天缺陷"

我们先得明白CPU的分级保护域。在x86架构下,CPU被分成了4个环:Ring 0、Ring 1、Ring 2、Ring 3。Ring 0权限最高,可以直接操作硬件(内核态);Ring 3权限最低(用户态)。

而在指令集上,分为普通指令 (Ring 3执行)和特权指令 (Ring 0执行)。在ARM(RISC精简指令集)架构下,所有敏感指令都是特权指令,这好办。但在x86(CISC复杂指令集)架构下,偏偏有19条敏感的非特权指令!

这意味着什么?当操作系统(本来该在Ring 0)被虚拟化放到Ring 1去跑时,它一旦执行这19条指令,系统不会触发异常陷入Hypervisor,而是直接在物理硬件上执行了,这就导致了虚拟化环境的崩溃。这就是x86架构最初不适合虚拟化的根本原因。

2. 解决方案的演进路线

为了解决这19条"刺头"指令,技术演进经历了三个阶段:

① 二进制翻译(BT - Binary Translation)

既然执行会出问题,那就在执行前检查一遍。VMM在Guest OS指令段执行前,进行整段翻译。把里面那些敏感的、非特权的指令,全部替换成能够触发陷入模拟的指令。特权指令被陷入到VMM后,VMM进行模拟,然后再返回给Guest OS。

  • 优点:Guest OS完全无感知,兼容性好。
  • 缺点:负载大、频繁翻译时性能极差(早期VMware就是这个路子)。

② 半虚拟化(Para-Virtualization)

直接改代码!在Guest OS里面集成半虚拟化代码,让它能识别Hypervisor。Hypervisor提供Hypercall接口来满足Guest OS的内存管理、中断等内核操作。

  • 优点:性能极其接近物理机。
  • 缺点:没法跑没修改过的Windows系统,兼容性差(早期Xen走的路)。

③ 硬件辅助虚拟化(VMX模式)

Intel和AMD终于在硬件层面出手了。引入了VMX模式(Virtual Machine eXtension) ,把CPU直接分成了两个大区:VMX Root模式 (给VMM用)和VMX Non-Root模式 (给Guest OS用)。

当Guest OS在Non-Root模式执行那19条敏感指令时,硬件直接捕获,产生一个VM-Exit (虚拟机退出),切换到Root模式让VMM处理。处理完再通过VM-Entry 切回Guest OS。

现在Intel的VT-x和AMD的AMD-V都是这个机制,真正的性能与兼容性兼得。


三、 内存虚拟化:从GVA到HPA的"三段位移"

CPU搞定了,内存呢?以前物理机上,内存都是从地址0开始的连续空间。但虚拟化环境下,多台虚拟机怎么可能都独占从0开始的内存?

所以这里引入了三个地址概念(重点划线):

  • GVA (Guest Virtual Address):客户机虚拟地址(Guest OS里应用看到的地址)。
  • GPA (Guest Physical Address):客户机物理地址(Guest OS以为的物理地址)。
  • HPA (Host Physical Address):宿主机物理地址(真正物理内存条上的地址)。

内存虚拟化的核心,就是地址转换。

转换机制的演进

最传统的做法是影子页表(Shadow Page Table)。由于宿主机MMU不能直接装客户机的页表,VMM得在底层维护一张表,把GVA直接映射到HPA。Guest OS一改页表,VMM就得跟着把影子页表也改一遍,极其消耗性能。

后来,Intel搞出了EPT(Extended Page Tables,扩展页表) ,AMD也有对应的NPT。

CR3寄存器把GVA转为GPA(由Guest OS维护),然后硬件自动查询EPT,把GPA转为HPA(由VMM维护)。这两次转换在硬件底层一步到位,翻译效率极高,彻底解放了VMM的CPU压力。


四、 KVM与QEMU:内核与用户的"双剑合璧"

了解了原理,我们看看实际的Linux虚拟化方案。

KVM (Kernel-based Virtual Machine) 本质上只是Linux内核的一个模块(kvm.ko)。它主要负责CPU和内存的虚拟化 。

但是光有KVM不行,它不具备I/O设备模拟的能力。所以,QEMU(一个纯软件实现的开源模拟软件)登场了。

KVM + QEMU 怎么配合?

  • KVM 运行在内核空间,管CPU和内存。
  • QEMU 运行在用户空间,负责硬件I/O的虚拟化模拟。
  • 两者通过 /dev/kvm 文件进行交互。

在KVM中,虚拟机其实就是一个普通的Linux进程(叫qemu-kvm进程),由Linux内核的CPU调度器来调度它运行!

实战:使用Libvirt命令行管理虚拟机

虽然我们平时在桌面端用 virt-manager 点点鼠标就能建虚拟机,但在没有图形界面的服务器上,还是得靠命令行。这里用到的是 Libvirt。

Libvirt 是一套通用且稳定的API库(底层是C语言写的),它可以同时管理KVM、Xen、VMware等。这里面有三个核心概念:

  • Node(节点):物理机。
  • Hypervisor(虚拟机监控器):比如KVM。
  • Domain(域):也就是一台虚拟机实例。

下面是我在CentOS 7环境下实操的几个 virsh 命令(属于libvirt原生命令行管理工具,功能最全):

1. 查看当前节点上的所有虚拟机

bash 复制代码
[root@server ~]# virsh list --all
 Id    名称                         状态
----------------------------------------------------
 1     centos7-vm                     running
 -     test-vm                        关闭

2. 启动、关闭、重启虚拟机

bash 复制代码
# 启动一台叫test-vm的虚拟机
[root@server ~]# virsh start test-vm
域 test-vm 已启动

# 正常关闭(相当于在系统里执行shutdown命令)
[root@server ~]# virsh shutdown test-vm
域 test-vm 被关闭

# 强制关闭(拔电源)
[root@server ~]# virsh destroy test-vm
域 test-vm 被删除(仅关闭电源,不删配置文件)

# 重启
[root@server ~]# virsh reboot test-vm
域 test-vm 正在重新启动

3. 查看虚拟机的XML配置详情(核心)

Libvirt 把虚拟机的所有配置(CPU、内存、磁盘、网卡)都保存为一个XML文件。

bash 复制代码
[root@server ~]# virsh dumpxml centos7-vm | head -n 20
<domain type='kvm' id='1'>
  <name>centos7-vm</name>
  <uuid>8b1f1e63-17a1-4314-8915-36b3e2331281</uuid>
  <memory unit='KiB'>2097152</memory>
  <currentMemory unit='KiB'>2097152</currentMemory>
  <vcpu placement='static'>2</vcpu>
  <os>
    <type arch='x86_64' machine='pc-i440fx-rhel7.6.0'>hvm</type>
    <boot dev='hd'/>
  </os>
... (省略部分输出)

你看,<memory> 和 <vcpu> 就是内存和CPU配置。如果想修改CPU核数,可以直接编辑XML:

bash 复制代码
[root@server ~]# virsh edit centos7-vm
# 会调用默认编辑器(如vi),把 <vcpu placement='static'>2</vcpu> 改成 4,保存退出即可。

4. 挂起与恢复

bash 复制代码
# 挂起(相当于保存当前运行状态)
[root@server ~]# virsh suspend centos7-vm
域 centos7-vm 被挂起

# 恢复
[root@server ~]# virsh resume centos7-vm
域 centos7-vm 被重新恢复

五、 华为FusionCompute:企业级虚拟化平台的缩影

学完了底层的KVM,PPT里又带我们看了一下华为的FusionCompute虚拟化套件。它是企业级数据中心常用的商业软件,说白了也就是把KVM、QEMU这些底层技术做了个精美的"包装",加了强大的管理平台。

FusionCompute 主要分两个核心模块:

  • CNA (Compute Node Agent):部署在物理服务器上,负责提供虚拟化计算资源,管理节点上的虚拟机。
  • VRM (Virtual Resource Management):可以部署为虚拟机,提供WebUI,负责整个集群的资源调度、生命周期管理、网络、存储分发。

它的高级特性让人叹为观止:

  • 热迁移(Live Migration):不停机把虚拟机从A物理机挪到B物理机。原理是内存压缩传输,磁盘数据位置不变(仅改映射),非常牛。
  • 动态资源调度(DRS):集群负载不均衡时,自动把虚拟机迁移到较闲的机器上。
  • 内存复用(内存气泡、共享、交换):把物理内存"超卖"。比如3个虚拟机共享同一块只读内存,用写时复制(COW)技术隔离,本来需要3G内存,可能只用1G就跑起来了,极客省钱。
  • 分布式虚拟交换机(DVS):跨主机的虚拟交换机,不管虚拟机热迁移到哪台物理机,网络配置都不需要改。

六、 课后总结与踩坑反思

今天的理论课信息量极大,尤其是《1021实际学习内容》里关于CPU虚拟化 和内存虚拟化的拆解,让我真正明白了为什么早年"一核有难,多核围观"的虚拟机很卡,而现在的硬件辅助虚拟化(EPT、VT-x)能跑得飞快。

几个记忆犹新的点:

  1. x86那19条"敏感非特权指令"是万恶之源。
  2. GVA -> GPA -> HPA 的翻译链路,EPT直接硬件搞定,不再依赖复杂的影子页表。
  3. KVM只是内核模块,没有QEMU它就是个"光杆司令",两者缺一不可。
  4. 虚拟机只是一个普通的Linux进程,这句话越品越有味道。

踩过的坑(动手实操时):

在用 virsh edit 修改虚拟机配置时,如果不小心把XML标签写错了(比如少了闭合标签),重新启动虚拟机时就会报错 Error: internal error: Failed to parse XML。那时候别慌,系统提示的报错行号很清楚,顺着改回来就行。另外,如果是开启了SELinux的系统,虚拟机镜像文件的上下文权限不对(没有 virt_image_t 标签),虚拟机经常会报无权访问磁盘而启动失败。这个留到下一节课如果做实验再重点排查。

从虚机化的逻辑来看,如今云原生环境下的容器化(Docker)其实在理念上是一脉相承的。它们都在讲"隔离"(Namespace/Cgroups),都在讲"封装"(镜像),都在解决硬件与软件的紧耦合问题。

今天算是把虚拟化这层窗户纸捅破了。下一阶段,就要去接触更上层的云平台和容器技术了。继续加油,一步一步把云计算这棵大树的根摸透!

相关推荐
深圳老胡37 分钟前
STM32C5A3ZG开发板:基于STM32CubeMX与VSCode的按键检测与LED闪烁实战
笔记·stm32·单片机·代码规范
星恒随风38 分钟前
Linux线程同步与互斥(二):从日志系统与线程池设计,到线程安全单例、可重入函数和死锁原理
linux·运维·状态模式
天疆说41 分钟前
DeepSeek 开源学习中心公开课调研笔记
笔记·学习·开源
mengge.cloud42 分钟前
1022小白入门教程(番外筑基)— nerdctl 容器基本功 + K8s 资源编写
linux·网络·云原生·容器·kubernetes·云计算·k8s
FY@-@1 小时前
云计算基础(上):从传统 IT 到 IaaS/PaaS/SaaS
云原生·云计算·paas
whyutianict_vv1 小时前
HCIE-Datacom 考纲技术拆解:从 OSPF/BGP 到 VXLAN/Netconf 的知识地图
运维·网络
March.s1 小时前
Kubernetes 控制器深度指南:从 ReplicaSet 到 DaemonSet
云原生·容器·kubernetes
你看我名字1 小时前
Kubernetes HPA 自动扩缩容详解:指标、策略、资源与常见故障
云原生·容器·kubernetes