KVM 是 Linux 上最常用的虚拟化方案,公有云的底层、很多私有云平台的底座都是它。它的好处是内核自带、开源免费、性能接近原生。坏处是——它没有像 VMware 那样"下一步下一步"的图形安装向导,全靠命令行和配置文件,第一次搭的人很容易在网桥、存储池、VNC 这些环节卡住。这篇文章就从零开始,带你在一台装了 Linux 的服务器上把 KVM 完整搭起来:检测 CPU 是否支持虚拟化、装软件包(RHEL 系和 Debian 系两套命令都给你)、配网桥让虚拟机有独立 IP、用 virt-install 建第一台虚拟机、用 virsh 日常管理、配存储池和控制台。最后把新手最容易踩的坑一个个列出来。
跟着做之前,请确认三件事:你的 CPU 支持硬件虚拟化并且 BIOS 里已开启、你在这台机器上有 root 或 sudo 权限、这台机器能联网装包。命令以 RHEL 8/9、Rocky、CentOS Stream 和 Ubuntu 22.04/24.04、Debian 12 为准,其他版本大同小异。
一、先检测 CPU 虚拟化支持
别急着装,先用一条命令判断机器能不能当 KVM 宿主机。
# 查看 CPU 是否支持 Intel VT-x(vmx)或 AMD-V(svm),有输出且数量大于 0 即可
egrep -c '(vmx|svm)' /proc/cpuinfo
# 更规范的写法(有些内核需要看 flags 行)
grep -Eoc '(vmx|svm)' /proc/cpuinfo
# 看内核模块是否具备条件:/dev/kvm 是否存在(装了 kvm 模块后才有)
ls -l /dev/kvm
# 一次性看硬件虚拟化是否可用
lscpu | grep -i virtualization
如果 egrep -c 输出大于 0(比如 8、16),说明 CPU 支持且 BIOS 已开启。如果输出 0,大概率是 BIOS/UEFI 里没开虚拟化,进 BIOS 打开 Intel VT-x / AMD-V(有的主板叫 Virtualization Technology、SVM Mode)再重启。如果开了还是 0,可能是这台机器本身是虚拟机且宿主没开嵌套虚拟化——这是新手在最常见的云主机上搭 KVM 时的头号障碍,后面"常见坑"一节会专门讲。
判断自己是不是跑在虚拟机里:
systemd-detect-virt # 输出 kvm/vmware/microsoft 等说明你在虚拟机里
二、安装 KVM 与 libvirt
KVM 的组件分工是:qemu-kvm 是模拟器核心,libvirt 是管理框架,virt-install 用来创建虚拟机,virt-manager 是图形管理界面。RHEL 系和 Debian 系包名有差异,下面给两套。
RHEL 8/9、Rocky、CentOS Stream:
# 安装虚拟化主机组(会带上一批常用包)
sudo dnf groupinstall -y "Virtualization Host"
# 逐个安装,等价且更明确
sudo dnf install -y qemu-kvm libvirt virt-install virt-manager \
libvirt-daemon-config-network libvirt-daemon-kvm
# 启动并设置开机自启
sudo systemctl enable --now libvirtd
# 确认服务状态(注意有些发行版服务名是 virtqemud + libvirtd,二者其一)
systemctl status libvirtd --no-pager
# 验证 libvirt 能识别 KVM 加速
virt-host-validate qemu
Debian 12 / Ubuntu 22.04 / 24.04:
sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients \
virtinst virt-manager bridge-utils
sudo systemctl enable --now libvirtd
systemctl status libvirtd --no-pager
sudo virt-host-validate qemu # 注意 Debian 系里这个命令带 sudo 或需在 libvirt 组
virt-host-validate qemu 会逐项检查硬件虚拟化、IOMMU 等,全绿(PASS)最好。它报 FAIL 的地方要逐个解决,别硬着头皮往下走。
把日常管理用户加进 libvirt 组,这样不用每次都 sudo:
sudo usermod -aG libvirt,kvm $USER
# 重新登录或执行 newgrp libvirt 才生效
三、配置网桥 br0,让虚拟机有独立 IP
装完默认只有一个 NAT 网络(virbr0),虚拟机走 NAT 能上网,但外面访问不进去,做服务器很不方便。生产里通常给虚拟机配桥接网桥,让虚拟机和物理机平起平坐,各自有局域网 IP。
RHEL 系用 nmcli 最稳(NetworkManager)。假设物理网卡是 eno1,要和网桥共用同一个网段,做法是把 IP 从物理网卡移到网桥上。这是远程操作服务器的危险动作,改错会直接断 SSH,务必先配好带外或本地控制台。
# 查看当前网卡名(别猜,按实际输出改)
nmcli device status
# 1) 创建网桥 br0,绑定物理网卡 eno1
sudo nmcli connection add type bridge ifname br0 con-name br0
sudo nmcli connection add type ethernet ifname eno1 con-name eno1-slave master br0
# 2) 把 IP 配到网桥上(示例:静态 IP 192.168.1.10/24,网关 192.168.1.1)
sudo nmcli connection modify br0 ipv4.addresses 192.168.1.10/24
sudo nmcli connection modify br0 ipv4.gateway 192.168.1.1
sudo nmcli connection modify br0 ipv4.dns 192.168.1.1
sudo nmcli connection modify br0 ipv4.method manual
sudo nmcli connection modify br0 bridge.stp no
# 3) 清掉物理网卡上原来的 IP,避免冲突(先记下原配置!)
sudo nmcli connection modify eno1-slave ipv4.method disabled ipv6.method ignore
# 4) 生效
sudo nmcli connection up eno1-slave
sudo nmcli connection up br0
ip addr show br0
如果这台机器用的是 netplan(Ubuntu Server 常见),编辑 /etc/netplan/01-netcfg.yaml:
# /etc/netplan/01-netcfg.yaml 注意 YAML 缩进必须用空格,不能用 Tab
network:
version: 2
renderer: networkd
ethernets:
eno1:
dhcp4: no
bridges:
br0:
interfaces: [eno1]
addresses: [192.168.1.10/24]
routes:
- to: default
via: 192.168.1.1
nameservers:
addresses: [192.168.1.1]
parameters:
stp: false
forward-delay: 0
# 预演配置是否合法,确认无误再应用(netplan 有语法错会断网)
sudo netplan try # 会倒计时,回车确认;超时自动回滚
sudo netplan apply
ip addr show br0
Ubuntu 桌面版若用 NetworkManager,用 nm-connection-editor 图形配置更省事,或用 nmtui。
几种网桥方案的取舍:nmcli 适合 RHEL 系和管理规范的 Ubuntu Server,配置持久、重启不丢;netplan 适合 Ubuntu Server 默认环境,语法清晰但缩进要求严格;直接在 /etc/sysconfig/network-scripts/ 里手写 ifcfg 文件是老派做法,RHEL 8 以后逐渐被 nmcli 取代,不推荐新环境用。改完网桥一定要验证三件事:宿主机自己能否上网或与其他机器互通(ping 网关)、虚拟机启动后能否拿到 IP、外部能否访问虚拟机的服务。如果配了网桥后宿主机自己也失联了,说明 IP 只加在了物理网卡或哪里冲突了,用带外控制台或本地终端把 br0 的 IP 补上即可恢复。
另外,建网桥时最好给网桥起一个有意义的连接名并记录到文档里。很多"改完网络连不上、又想不起来原来怎么配的"事故,都是因为一开始没备份、没记录。养成习惯:改任何网络配置前,先 nmcli connection show 或 cat /etc/netplan/*.yaml 把现状存一份。
四、用 virt-install 创建第一台虚拟机
先把要用的镜像放到一个目录,比如 /var/lib/libvirt/images/。然后用 virt-install 一条命令建机器。
# 准备 ISO 目录
sudo mkdir -p /var/lib/libvirt/images
# 把 CentOS Stream 或 Ubuntu Server 的 ISO 拷进来,这里假设文件已就位
# 创建一台 2 核 2G、20G 磁盘、桥接到 br0、带 VNC 控制台的虚拟机
sudo virt-install \
--name web01 \
--memory 2048 \
--vcpus 2 \
--cpu host-passthrough \
--disk path=/var/lib/libvirt/images/web01.qcow2,size=20,format=qcow2,bus=virtio \
--cdrom /var/lib/libvirt/images/CentOS-Stream-9-latest-x86_64-dvd1.iso \
--network bridge=br0,model=virtio \
--graphics vnc,listen=0.0.0.0,port=5901 \
--os-variant detect=on,name=centos-stream9 \
--boot cdrom,hd \
--noautoconsole
几个关键参数说明:
--cpu host-passthrough:把宿主机 CPU 特性透传给虚拟机,性能最好;要在线迁移的集群则用--cpu host-model。bus=virtio/model=virtio:半虚拟化磁盘和网卡,性能远好于模拟的 IDE/e1000,前提是客户机装了 virtio 驱动(现代 Linux 自带)。--graphics vnc:开 VNC 控制台,装系统时要用图形界面。--noautoconsole:不自动打开控制台,适合脚本化。--os-variant:帮助优化默认参数,不确定就先osinfo-query os | grep -i ubuntu查准确名字。
创建完成后,虚拟机进入安装界面(通过 VNC),装完系统它就独立运行了。
五、用 virsh 做日常管理
virsh 是 KVM 的日常命令入口,最常用的命令都在这里。
# 列出所有虚拟机(运行中)
sudo virsh list
# 列出全部,含关机状态
sudo virsh list --all
# 启动 / 关机 / 强制断电 / 重启
sudo virsh start web01
sudo virsh shutdown web01 # 优雅关机(需客户机装 qemu-guest-agent)
sudo virsh destroy web01 # ⚠️ 相当于拔电源,仅在 shutdown 无响应时用,有丢数据风险
sudo virsh reboot web01
# 进入控制台(字符界面),退出用 Ctrl+]
sudo virsh console web01
# 查看详细信息:CPU、内存、磁盘、网卡、状态
sudo virsh dominfo web01
sudo virsh domifaddr web01 --source agent # 需要 guest-agent
sudo virsh domblklist web01
# 查看/编辑配置(编辑会打开编辑器,改完保存生效,一般下次启动生效)
sudo virsh dumpxml web01 > /root/web01.xml # 备份配置,好习惯
sudo virsh edit web01
# 取消定义(删除虚拟机配置,⚠️ 不删磁盘文件,但机器就从 libvirt 里消失了)
sudo virsh undefine web01
# 若含 UEFI/NVRAM 需加 --nvram,若连磁盘一起删要手动删 qcow2 文件
风险提示:virsh destroy 是强制断电、virsh undefine 是移除虚拟机定义,都不是日常操作。执行前先 virsh dumpxml 备份配置,磁盘文件(qcow2)不会被 undefine 自动删除,删盘要自己确认路径再 rm。
还有几组命令值得记住:virsh autostart web01 让虚拟机随宿主机开机自动启动,virsh autostart --disable web01 取消,生产环境里跑关键业务的虚拟机基本都要开启自启;virsh dominfo 能看状态和资源,virsh domstats 能一次性拿到所有虚拟机的 CPU、内存、磁盘、网络统计,做监控时用得上;virsh setmem/virsh setvcpus 可以在线调整已分配的内存和 CPU(需要客户机支持热插拔,且一般只能增大不能超过上限)。另外,virsh dumpxml 出来的 XML 就是虚拟机的完整定义,把它纳入版本管理或定期归档,机器出问题时可以照着重建,这比到处找"当初怎么配的"靠谱得多。
六、存储池:把磁盘目录管起来
存储池(storage pool)是 libvirt 对"存放虚拟机磁盘的目录/LUN"的抽象,建好之后创建虚拟机时可以直接引用。
# 定义一个目录型存储池,路径 /var/lib/libvirt/images
sudo virsh pool-define-as guest_images dir --target /var/lib/libvirt/images
# 启动池、设置开机自启、查看状态
sudo virsh pool-start guest_images
sudo virsh pool-autostart guest_images
sudo virsh pool-list --all
sudo virsh pool-info guest_images
# 在池里直接建一块 20G 的卷
sudo virsh vol-create-as guest_images disk01.qcow2 20G --format qcow2
sudo virsh vol-list guest_images
常见池类型:dir(普通目录)、logical(LVM 卷组)、netfs(NFS 共享)、iscsi(iSCSI LUN)。中小企业自建多用 dir 或 logical,接了集中存储就用 netfs/iscsi。
七、VNC 控制台怎么连
创建虚拟机时用 --graphics vnc 开了 VNC,可以用如下方式确认端口:
# 查看虚拟机 VNC 显示端口(不是 5900+port-5900 的算法要看输出)
sudo virsh vncdisplay web01
# 输出如 :1 表示监听在 5901
# 查看实际监听端口
sudo ss -tlnp | grep qemu
然后用任意 VNC 客户端连 宿主机IP:5901 即可看到虚拟机屏幕。安全提醒:listen=0.0.0.0 表示所有网卡都能连 VNC,强烈建议只监听管理网段,或者在外层加 SSH 隧道转发,别把 VNC 裸暴露在公网。
# 用 SSH 隧道安全地转发 VNC(本地执行),本地 5901 连宿主机 5901
ssh -L 5901:127.0.0.1:5901 user@宿主机IP
# 然后 VNC 客户端连 127.0.0.1:5901
八、新手最容易踩的坑
坑一:云主机里没有 /dev/kvm。 如果你在公有云的普通云主机上搭 KVM,egrep -c 返回 0、/dev/kvm 不存在,多半是宿主没开嵌套虚拟化。解决办法是换支持嵌套虚拟化的实例规格,或者选裸金属/支持 KVM 的实例类型。这是绕不过去的,软件层解决不了。
坑二:配网桥把 SSH 弄断了。 用 nmcli 或 netplan 把物理网卡 IP 移到 br0 时,如果 br0 配错,远程连接立刻断。务必:先备份原网卡配置、在带外控制台或本地终端上改、用 netplan try 这种带自动回滚的方式、或者先开一个备用 SSH 会话别关。
坑三:qcow2 磁盘空间不够要扩容。 qcow2 支持在线扩容,但要分两步:先在宿主机扩虚拟磁盘,再进客户机扩大分区和文件系统。
# 1) 宿主机上加 10G(⚠️ 仅扩容,不能缩,缩容会丢数据)
sudo qemu-img resize /var/lib/libvirt/images/web01.qcow2 +10G
# 确认
sudo qemu-img info /var/lib/libvirt/images/web01.qcow2
# 2) 进客户机后(以最新内核识别新空间为前提):
# 若是 LVM:pvresize /dev/vda3 && lvextend -l +100%FREE /dev/vg0/root && resize2fs /dev/vg0/root
# 若是普通分区 + ext4:
sudo growpart /dev/vda 3 # 扩大分区(分区号按实际改)
sudo resize2fs /dev/vda3 # ext4 在线扩容;xfs 用 xfs_growfs /挂载点
# ⚠️ 操作前对虚拟机做快照或备份,分区号写错会毁数据
坑四:客户机里关机命令没用。 virsh shutdown 依赖客户机里的 qemu-guest-agent 或 ACPI 支持。装好系统后进客户机装 agent:RHEL 系 dnf install -y qemu-guest-agent,Debian 系 apt install -y qemu-guest-agent,然后 systemctl enable --now qemu-guest-agent。
坑五:磁盘/网卡性能差。 默认可能用了模拟设备。确认磁盘 bus=virtio、网卡 model=virtio;再开多队列 virsh edit 里加 并让客户机网卡也配多队列,高吞吐场景提升明显。
常见问题
Q:KVM 和 QEMU 是什么关系?
QEMU 是纯软件模拟器,能模拟各种 CPU,但慢;KVM 是 Linux 内核模块,利用 CPU 硬件虚拟化把指令直接跑在物理 CPU 上,快。两者配合:KVM 提供加速,QEMU 提供设备模拟,合起来就是常说的 "qemu-kvm"。
Q:装完 KVM 宿主机,原有业务会受影响吗?
不会,KVM 是内核模块,宿主机本身还是正常运行业务的 Linux。但虚拟机运行时会消耗 CPU、内存、磁盘 IO 和网络,所以要在宿主机上给虚拟机预留资源并做 CPU/IO 限制,别让虚拟机把宿主机业务拖垮。
Q:虚拟机用桥接还是 NAT?
需要被外部直接访问(当服务器用、要独立公网/内网 IP)就用桥接;只是内部测试、不要求入站访问,用默认 NAT 更省事、更安全。
Q:能不能在一台 KVM 上再跑 KVM(嵌套)?
可以,如果宿主机 CPU 支持且把 vmx/svm 特性透传给子虚拟机(--cpu host-passthrough 且暴露嵌套特性)。但嵌套会带来额外性能损耗和兼容性问题,非必要不用。
Q:虚拟机硬盘用 qcow2 还是 raw?
qcow2 支持快照、精简置备、加密,功能多但有一点性能开销;raw 性能略好、不支持快照、按需分配空间差。一般业务用 qcow2 更灵活,追求极致 IO 且用 LVM/直通时可用 raw。
总结
搭建 KVM 的完整顺序是:egrep -c '(vmx|svm)' /proc/cpuinfo 确认支持 → 装 qemu-kvm/libvirt/virt-install(RHEL 用 dnf、Debian 用 apt)→ 配 br0 网桥(nmcli 或 netplan)→ virt-install 建虚拟机 → virsh 管理 → 配存储池和 VNC 控制台。
排障优先级:先确认 /dev/kvm 存在和 virt-host-validate 全绿,再查网桥连通性,最后才怀疑性能参数。90% 的"搭不起来"都卡在这三处。
安全红线:改网桥前先备份原网卡配置并在带外控制台操作;VNC 不要裸暴露公网,用 SSH 隧道;virsh destroy/undefine、qemu-img resize 缩容、分区操作等危险命令执行前必须备份。
生产使用建议:装 qemu-guest-agent、给虚拟机配 virtio 设备、在宿主机层做资源限制防止邻居噪音、给重要虚拟机定期快照并测试恢复,而不是只留快照不验证。
企业QQ咨询




