提示本文原创作品良心制作干货为主简洁清晰一看就会文章目录前言一、KVM基础知识1.1 KVM是什么1.2 KVM完整工具分层架构最上层用户操作工具管理员入口中间统一层libvirt下层QEMU 硬件模拟层最底层KVM 内核模块1.3 libvirt 管理架构二、KVM安装2.1 环境准备虚拟机勾选关闭 Windows 自带 Hyper-V 虚拟化底层2.2 KVM安装三、KVM简单操作3.1 临时创建KVM3.2 永久创建KVM3.3 用console连接前言KVM凭借其原生集成于 Linux 内核、高性能、开源免费等优势逐渐成为企业级虚拟化场景的首选方案。对于初入虚拟化领域的运维人员或开发者而言KVM 的概念分层如 QEMU、libvirt 与内核模块的关系和工具链virt-install、virsh 等往往容易令人困惑。本文旨在从一个纯净的 Ubuntu 环境出发系统梳理 KVM 的核心架构并通过“创建临时/永久虚拟机”、“配置串口控制台”等高频实操场景帮助读者快速跨越从理论到落地的门槛建立一套可靠且可复制的 KVM 管理方法论一、KVM基础知识1.1 KVM是什么KVMKernel-based Virtual MachineLinux内核原生内置的虚拟化模块是Linux官方自带的硬件虚拟化技术核心作用一台物理机拆分多台独立虚拟机每台虚拟机拥有独立CPU、内存、磁盘、网卡性能极强直接调用CPU硬件虚拟化指令Intel VT-x/AMD-V损耗极低接近物理机配套工具搭配libvirt/virsh/QEMU管理虚拟机用途服务器资源隔离、多系统测试、云主机底层虚拟化底座Linux内核自带的高性能虚拟化引擎用来在一台物理服务器上跑多台隔离的虚拟电1.2 KVM完整工具分层架构下图展示KVM整套工具栈层级关系分为四层上层管理工具 → libvirt 统一管理层 → QEMU 硬件模拟器 → KVM 内核虚拟化模块完整执行流程以virt-install新建虚拟机举例管理员执行virt-install工具调用libvirt API请求发给libvirtdlibvirtd下发指令给QEMUQEMU调用底层KVM内核模块开启硬件加速QEMU拉起独立进程模拟硬件生成一台虚拟机最上层用户操作工具管理员入口图形工具 Virtual Machine Managervirt-manager图形界面鼠标点选管理虚拟机virt-viewer打开虚拟机桌面窗口virtinst 工具集命令行批量创建/镜像操作virt-install新建虚拟机virt-image镜像模板管理virt-convert虚拟机格式转换virt-clone克隆虚拟机图里笔误写成virt-clagevirsh全能命令行工具启停、快照、网络存储配置全靠它所有这些工具全部依赖 libvirt 接口不直接操作底层KVM/QEMU中间统一层libvirtlibvirtd后台守护进程接收所有上层工具请求libvirtAPI统一标准接口屏蔽底层QEMU/KVM细节下层QEMU 硬件模拟层QEMU负责模拟CPU、硬盘、网卡、显卡等整套硬件设备qemu-img管理虚拟磁盘创建、扩容、转换镜像qemu-io磁盘IO调试工具qemu-kvm带KVM硬件加速的QEMU主程序每一台运行的虚拟机对应一个独立qemu进程。最底层KVM 内核模块Linux内核内置虚拟化驱动提供CPU硬件加速实现真正的硬件级虚拟化是整套虚拟化的底层底座1.3 libvirt 管理架构下图展示 libvirt 虚拟化统一管理框架上层各类虚拟机管理工具不用直接对接底层不同虚拟化引擎KVM/Xen/VMware/VirtualBox 等全部统一调用 libvirt 标准 API由 libvirt 适配各类底层虚拟化实现一套工具管所有虚拟机完整数据流举例管理员执行virt-install➡工具调用libvirt API传参给libvirtd➡libvirtd匹配KVM驱动➡调用内核KVM模块启动QEMU模拟硬件➡QEMU加载ISO创建KVM虚拟机第一层用户态管理工具User-space management tools都是给管理员操作虚拟机的前端工具全部依赖 libvirt 工作第二层核心中间层 — libvirt核心图中标注libvirt daemon libvirt API是整套架构的统一抽象层作用有两个统一API标准上层工具只需要调用 libvirt 一套接口不用为 KVM、Xen、VMware 分别写适配代码多虚拟化后端适配libvirt 内部内置驱动向下兼容市面上几乎所有虚拟化引擎屏蔽底层差异。后台常驻进程libvirtd负责接收工具请求、转发给底层虚拟化。第三层底层各类虚拟化Hypervisorlibvirt兼容的后端libvirt向下对接4大类主流虚拟化每一套架构独立Xen 虚拟化KVMLinux原生主流虚拟化Linux Kernel(KVM module)内核内置虚拟化模块提供硬件加速Qemu负责模拟CPU、磁盘、网卡等硬件设备每个虚拟机对应一个Qemu进程Guest运行的虚拟机实例VMware 系列虚拟化other hypervisors 其他虚拟化二、KVM安装2.1 环境准备先准备一台虚拟机来学习KVM虚拟机勾选如果直接开机该虚拟机可能会出现以下错误关闭 Windows 自带 Hyper-V 虚拟化底层1管理员身份打开命令提示符依次输入下面三条命令bcdedit /set hypervisorlaunchtype off bcdedit /set vsmlaunchtype off DISM /Online /Disable-Feature:Microsoft-Hyper-V2关闭 Windows 功能在搜索栏输入 “启用或关闭 Windows 功能” 并打开。务必取消勾选以下所有项目Hyper-V虚拟机平台Windows 虚拟机监控程序平台适用于 Linux 的 Windows 子系统 (WSL)Windows 沙盒 (如果有)3关闭内核隔离打开 “Windows 安全中心” - “设备安全性” - “内核隔离详细信息”将“内存完整性”开关设置为 “关”上面完成后重启电脑2.2 KVM安装## 1. 检查内核是否开启 KVM 虚拟化支持rootubuntu:~# grep -i kvm /boot/config-4.15.0-213-generic## 2. 检测 CPU 硬件虚拟化指令集是否开启rootubuntu:~# egrep (vmx|svm) /proc/cpuinfo## 3. 查看 kvm 相关驱动是否加载运行rootubuntu:~# lsmod | egrep kvm|ModuleModule Size Used by kvm_intel 217088 0 kvm 614400 1 kvm_intel irqbypass 16384 1 kvm## 4. 查看 KVM 设备文件是否存在rootubuntu:~# ls /dev/kvm/dev/kvm## 5. 安装全套 KVM 虚拟化环境组件rootubuntu:~# apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst virt-manager virt-viewer cpu-checker## 6. 查看系统静态路由表rootubuntu:~# route -nKernel IP routing table Destination Gateway Genmask Flags Metric Ref Use Iface 0.0.0.0 192.168.13.2 0.0.0.0 UG 100 0 0 ens33 192.168.13.0 0.0.0.0 255.255.255.0 U 0 0 0 ens33 192.168.13.2 0.0.0.0 255.255.255.255 UH 100 0 0 ens33 192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0## 7. 查看网卡rootubuntu:~# ip a## 8. 查看正在运行的 DNS 服务进程判断 libvirt 默认网络是否正常启动rootubuntu:~# ps aux | grep -v grep | grep dnslibvirt 5982 0.0 0.0 49988 2296?S 08:39 0:00 /usr/sbin/dnsmasq--conf-file/var/lib/libvirt/dnsmasq/default.conf--leasefile-ro--dhcp-script/usr/lib/libvirt/libvirt_leaseshelper root 5983 0.0 0.0 49960 368?S 08:39 0:00 /usr/sbin/dnsmasq--conf-file/var/lib/libvirt/dnsmasq/default.conf--leasefile-ro--dhcp-script/usr/lib/libvirt/libvirt_leaseshelper## 9. 查看 libvirt 虚拟机管理服务的全局配置目录rootubuntu:~# ls /etc/libvirt/hooks libvirt.conf libxl.conf lxc.conf qemu qemu-lockd.conf secrets virtlogd.conf libvirt-admin.conf libvirtd.conf libxl-lockd.conf nwfilter qemu.conf qemu-sanlock.conf virtlockd.conf virt-login-shell.conf## 10. 读取 libvirt默认 NAT 虚拟网卡配置rootubuntu:~# cat /etc/libvirt/qemu/networks/autostart/default.xml## 11. 创建并启动一台 KVM 虚拟机## ubuntu-18.04.6-live-server-amd64.iso镜像需要提前上传到指定目录rootubuntu:~# virt-install \# 虚拟化类型指定为KVM硬件加速虚拟化--virt-type kvm \# 虚拟机名称virsh list 能看到这个名字--name Ubuntu-18.04-amd64 \# 分配内存 2048MB2G--memory 2048 \# 分配2颗CPU核心--vcpus 2 \# 系统安装镜像路径挂载为光驱--cdrom/var/lib/libvirt/images/ubuntu-18.04.6-live-server-amd64.iso \# 创建磁盘文件路径、磁盘大小20GB格式raw--disk path/var/lib/libvirt/images/Ubuntu-18.04-amd64.raw,size20 \# 网卡使用libvirt默认default NAT网络虚拟机共享宿主机上网--network networkdefault \# 开启VNC远程图形界面允许所有IP连接0.0.0.0外部工具可VNC访问安装界面--graphics vnc,listen0.0.0.0 \# 命令行不自动弹出控制台后台运行虚拟机--noautoconsole \# 启动顺序优先光驱安装系统安装完成后从硬盘启动--boot cdrom,hd## 12. libvirt 默认虚拟机镜像存储目录rootubuntu:~# ls /var/lib/libvirt/images/ubuntu-18.04.6-live-server-amd64.iso Ubuntu-18.04-amd64.raw## 13. 查看所有虚拟机运行状态rootubuntu:~# virsh list --allId Name State----------------------------------------------------13 Ubuntu-18.04-amd64 running## 14. 查看虚拟机VNC端口用于远程连接默认5900rootubuntu:~# virsh vncdisplay Ubuntu-18.04-amd64:0我这里用vnc来连接虚拟机宿主机ip:5900连接好后双击虚拟机安装操作系统系统安装完成后进入登录界面登录虚拟机系统可正常访问外网且能获取独立内网 IP## 15. 宿主机检查进程rootubuntu:~# ps aux | grep Ubuntu虚拟机本质上就是在宿主机系统上的一个kvm进程管理虚拟机跟管理进程基本一样## 16. 存放 QEMU/KVM 虚拟机的全部配置文件rootubuntu:~# tree /etc/libvirt/qemu三、KVM简单操作3.1 临时创建KVMrootubuntu:~# cd /etc/libvirt/qemu/rootubuntu:/etc/libvirt/qemu# lsnetworks Ubuntu-18.04-amd64.xml rootubuntu:/etc/libvirt/qemu# cp Ubuntu-18.04-amd64.xml Ubuntu-18.04-amd64-1.xmlrootubuntu:/etc/libvirt/qemu# vim Ubuntu-18.04-amd64-1.xmlrootubuntu:~# virsh list --allId Name State----------------------------------------------------13 Ubuntu-18.04-amd64 running rootubuntu:~# virsh shutdown Ubuntu-18.04-amd64rootubuntu:~# virsh list --allId Name State-----------------------------------------------------Ubuntu-18.04-amd64 shut off rootubuntu:~# virsh create /etc/libvirt/qemu/Ubuntu-18.04-amd64-1.xmlDomain Ubuntu-18.04-amd64-1 created from /etc/libvirt/qemu/Ubuntu-18.04-amd64-1.xml rootubuntu:~# virsh list --allId Name State----------------------------------------------------14 Ubuntu-18.04-amd64-1 running-Ubuntu-18.04-amd64 shut off rootubuntu:~# virsh list --transientId Name State----------------------------------------------------14 Ubuntu-18.04-amd64-1 running3.2 永久创建KVMrootubuntu:/etc/libvirt/qemu# virsh destroy Ubuntu-18.04-amd64-1rootubuntu:/etc/libvirt/qemu# virsh list --allId Name State-----------------------------------------------------Ubuntu-18.04-amd64 shut off rootubuntu:/etc/libvirt/qemu# cp Ubuntu-18.04-amd64.xml Ubuntu-18.04-amd64-2.xmlrootubuntu:/etc/libvirt/qemu# vim Ubuntu-18.04-amd64-2.xmlrootubuntu:~# virsh define /etc/libvirt/qemu/Ubuntu-18.04-amd64-2.xmlrootubuntu:~# virsh start Ubuntu-18.04-amd64-2rootubuntu:~# virsh list --allId Name State----------------------------------------------------15 Ubuntu-18.04-amd64-2 running-Ubuntu-18.04-amd64 shut off由于我上面的方法只改了 name 和 uuid这三者的最终区别如下对比维度virsh create(临时)virsh define(永久)virt-install(标准创建)生命周期一次性。关机或物理机重启后虚拟机彻底消失永久注册。关机或重启后仍在virsh list --all中永久注册磁盘文件不会创建直接引用 XML 里的旧路径不会创建直接引用 XML 里的旧路径自动创建一个全新的空白磁盘文件UUID MAC需要手动改否则冲突需要手动改否则冲突全自动生成绝对不与现有冲突PCI地址复制原 XML 中的显卡/网卡插槽号极易冲突复制原 XML 中的插槽号极易冲突启动时由 libvirt重新分配空闲插槽适用场景应急调试一个临时配置导入一台已存在的旧虚拟机迁移安装全新的操作系统最推荐所以每次只能有一个kvm运行如果多个同时运行会同时向同一个磁盘文件写入数据。这会导致文件系统元数据错乱两个虚拟机都会瞬间卡死磁盘数据彻底损坏3.3 用console连接通过 VNC 连接虚拟机操作较为繁琐接下来我们改用串口 console 方式登录虚拟机rootubuntu:~# virsh destroy Ubuntu-18.04-amd64-2rootubuntu:~# virsh start Ubuntu-18.04-amd64rootubuntu:~# virsh autostart Ubuntu-18.04-amd64 # 开机自启rootubuntu:~# virsh edit Ubuntu-18.04-amd64保持一样下述操作在虚拟机内执行我这里用vnc来连接的虚拟机# 确保 GRUB 包含串口参数sudo sed-i s/^GRUB_CMDLINE_LINUX.*/GRUB_CMDLINE_LINUXconsolettyS0consoletty0/ /etc/default/grub sudo update-grub# 创建自定义串口登录服务sudo tee /etc/systemd/system/console-getty.service EOF[Unit]DescriptionConsole Getty on ttyS0 Afternetwork.target[Service]ExecStart/sbin/agetty-L ttyS0 115200 vt100 Restartalways RestartSec5 StandardInputtty StandardOutputtty TTYPath/dev/ttyS0[Install]WantedBymulti-user.target EOF 启用并启动服务 sudo systemctl daemon-reload sudo systemctl enable console-getty.service sudo systemctl start console-getty.service 检查服务状态确认 active sudo systemctl status console-getty.service 重启虚拟机测试 sudo reboot回到宿主机我们可以直接用console连接虚拟机rootubuntu:~# virsh console Ubuntu-18.04-amd64Connected to domain Ubuntu-18.04-amd64 Escape character is ^]输入回车ubuntu login:ubuntu# 创建系统时的账号Password:# 输入密码ubuntuubuntu:~$ id uid1000(ubuntu) gid1000(ubuntu) groups1000(ubuntu),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),108(lxd) ubuntuubuntu:~$ ip a注文中若有疏漏欢迎大家指正赐教。本文为100%原创转载请务必标注原创作者尊重劳动成果。求赞、求关注、求评论你的支持是我更新的最大动力评论区等你