做运维这些年,我往服务器上装系统的频率比点外卖还高。物理机装系统、上架、部署一套流程下来,麻烦不说,遇到需要同时跑多个系统的时候就特别头疼。后来我把主力的物理服务器改造成KVM虚拟化平台,一台机器上同时跑Ubuntu和Rocky Linux虚拟机,再配合桥接网络,从外部看这几台机器和物理机几乎没有区别。这篇文章就完整记录我这次KVM部署的全过程:从硬件确认、宿主机配置,到依次创建Ubuntu和Rocky虚拟机,最后把踩过的坑全部交代清楚,希望能帮到同样在做虚拟机搭建的朋友。
1. 环境准备与KVM基础
1.1 KVM到底是什么
KVM全称Kernel-based Virtual Machine,是Linux内核自带的一个虚拟化模块。它利用CPU的硬件辅助虚拟化能力(Intel VT-x或者AMD-V),让Linux内核直接充当一个虚拟机监视器。简单理解:KVM是发动机,QEMU是变速箱和车身,libvirt是方向盘和仪表盘。发动机负责把CPU的算力切给虚拟机,QEMU负责模拟网卡、磁盘、显卡这些设备,libvirt则提供一套统一的命令行和API来管理这一切。
我见过不少朋友在选型时纠结用VMware还是KVM,我的建议是:如果是纯Linux环境、追求性能、不想掏授权费,KVM基本是首选。KVM的虚拟机性能损耗比传统软件虚拟化低很多,因为它直接走硬件虚拟化指令,不需要像模拟器那样一条一条翻译CPU指令。实际体感上,跑编译任务或者数据库这类吃CPU的活,KVM虚拟机和物理机大概只有几个百分点的差距,这个表现是QEMU纯软件模拟完全比不了的。
KVM的应用场景也很有讲究。大多数人拿它做两件事:一是服务器整合,把多台利用率不高的物理机合并到一台宿主机上,省电省空间;二是做开发测试环境,一台物理机上随便开几个不同发行版的虚拟机,随便折腾也不影响宿主机。现在很多私有云和桌面虚拟化方案的底座就是KVM,这个技术本身已经相当成熟。
1.2 硬件确认与宿主机规划
动手之前先确认硬件够不够格。CPU必须支持虚拟化,这是硬门槛。在Linux终端里敲下面这条命令:
bash复制egrep -c '(vmx|svm)' /proc/cpuinfo
返回的数字大于0就代表支持,vmx对应Intel的VT-x,svm对应AMD的AMD-V。如果返回0,不用继续看了,先去BIOS里找找有没有被关掉,或者考虑换机器。老实说我碰到过好几台服务器,CPU型号明确支持虚拟化,就是BIOS默认关着,开机按F2进BIOS,在Processor Configuration或者Security菜单里找到Virtualization Technology,设为Enabled,重启就好。
内存和磁盘的规划要提前做除法。假设宿主机有64GB内存,我一般预留8到16GB给宿主机自己跑系统和服务,剩下的全部按需分给虚拟机。比如计划跑两台4GB内存的Ubuntu测试机、两台8GB内存的Rocky业务机,加起来24GB左右,那这台机器就很从容。磁盘同理,qcow2格式的镜像文件虽然是动态增长的,但运行起来之后虚机里的实际数据量会慢慢占满你分配的空间,所以物理磁盘至少要留出所有虚机分配容量总和的1.2倍才安心。
我个人推荐宿主机用Ubuntu Server 22.04 LTS或者24.04 LTS。为什么不用Rocky做宿主机?也不是不行,但Ubuntu的apt包管理在安装KVM相关组件时依赖处理得更省心,libvirt相关包的版本也比较新。如果你本身主力就是Debian系,用Ubuntu做宿主机不会有什么学习成本。这篇文章的示例就以Ubuntu 22.04 LTS为例,Rocky Linux在后面作为虚拟机登场。
1.3 安装KVM组件包
Ubuntu上安装KVM全家桶很简单,一条命令搞定:
bash复制sudo apt update
sudo apt install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst virt-manager
逐个解释一下这些包是干什么的。qemu-kvm是核心的QEMU/KVM模拟器;libvirt-daemon-system和libvirt-clients提供libvirtd服务端和virsh等管理命令;bridge-utils提供网桥管理工具brctl,后面配置桥接网络要用;virtinst是创建虚拟机的主力工具,里面的virt-install命令我们马上就用;virt-manager是图形化管理工具,如果宿主机有桌面环境或者通过X11转发可以用,没有桌面环境也可以靠它生成虚拟机后远程用VNC连接。
装完启动libvirtd服务:
bash复制sudo systemctl enable --now libvirtd
sudo systemctl status libvirtd
看到active (running)就对了。接着把当前用户加入libvirt用户组,这样平时操作不用老挂sudo:
bash复制sudo usermod -aG libvirt $USER
sudo usermod -aG kvm $USER
newgrp libvirt
最后确认KVM模块真的加载成功了:
bash复制virsh list --all
这条命令如果返回空列表或者显示"Id Name State"表头,说明一切正常。如果你在这里看到错误,先检查有没有装cpu-checker并运行kvm-ok,这个工具能直观告诉你KVM加速能不能用。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 宿主机网络与存储配置
2.1 三种网络模式怎么选
KVM创建虚拟机时最常遇到的三个网络选择是:NAT模式、桥接模式、隔离模式。这块好多新手容易懵,我直接说结论:默认的virbr0 NAT模式适合临时测试,虚拟机可以访问外网但外部访问不进来;隔离模式适合做封闭实验网络,虚拟机之间能互通但上不了外网;生产环境和需要外部直接访问的场景,一律上桥接模式。
桥接模式的核心操作是把物理网卡和一个虚拟网桥绑定,虚拟机的虚拟网卡也挂到这个网桥上。这样虚拟机相当于和宿主机在同一个二层网络里,局域网内的其他设备能直接访问虚拟机IP,虚拟机也能正常上网。打个比方:NAT模式是几个人合租一间房,房东统一管网络进出;桥接模式是每人独立办一条宽带,各有各的公网入口。
三个模式的特点我给整理成一张表,方便后面选型:
| 模式 | 外网访问 | 外部访问虚拟机 | 配置复杂度 | 适用场景 |
|---|---|---|---|---|
| NAT(默认virbr0) | 可以 | 不可以 | 低 | 临时测试、仅需虚拟机上网 |
| 桥接(自定义br0) | 可以 | 可以 | 中 | 生产服务、需要局域网直连 |
| 隔离(自定义virbr1) | 不可以 | 不可以 | 低 | 安全实验、教学演练 |
我这次两台虚机都选了桥接,因为后续要对外提供SSH和Web服务,NAT模式还得想办法做端口转发,纯属给自己找麻烦。
2.2 用netplan配置桥接网卡
Ubuntu 22.04用的网络管理工具是netplan,配置文件在/etc/netplan/目录下。开始改之前先用ip a确认一下物理网卡名称,常见的是enp3s0、ens33、eno1这类名字。我的机器上是enp3s0。
备份原配置后,编辑配置文件,把物理网卡绑进网桥:
bash复制sudo cp /etc/netplan/01-netcfg.yaml /etc/netplan/01-netcfg.yaml.bak
sudo vim /etc/netplan/01-netcfg.yaml
下面是关键示例,注意缩进必须严格对齐:
yaml复制network:
version: 2
ethernets:
enp3s0:
dhcp4: no
bridges:
br0:
interfaces: [enp3s0]
dhcp4: yes
解释一下每个字段的用途。ethernets段把物理网卡enp3s0的DHCP关掉,因为IP地址要让给网桥来获取;bridges段创建了一个名为br0的网桥,把enp3s0作为成员接口挂进去,br0自己通过DHCP获取IP。这样配置完成后,宿主机对外通信的网卡实际是br0,而enp3s0已经沦为透明通道。
应用配置:
bash复制sudo netplan apply
然后确认生效:
bash复制ip a show br0
ip a show enp3s0
正常情况是br0拿到IP,enp3s0没有IP。如果你的环境需要固定IP,把dhcp4: yes改成静态配置即可,后面Rocky虚拟机里我也会演示静态IP设置,原理类似。
需要注意,有些云服务器或者托管机房不支持把物理网卡直接桥接,会限制MAC地址或者只允许一个IP。这种环境切换桥接后网络可能会断。我自己就踩过一次:在机房远程连服务器,手速太快apply完直接失联,最后只能让机房小哥帮忙接显示器才救回来。操作前最好确认下手上有没有带外管理,或者把SSH连接超时时间拉长,给自己留退路。
2.3 存储准备与qcow2格式
存储这块我习惯用目录存储池,就是给虚拟机镜像文件指定一个目录,简单直接。libvirt默认的存储池就在/var/lib/libvirt/images/,我懒得折腾,就直接用它。
镜像格式我强烈推荐qcow2。这个格式自带三个好处:按需增长(刚创建时只占很小空间,用到多少占多少)、支持快照、支持压缩。另一种raw格式性能略好,但创建时一次性分配全部空间,而且不支持快照。对大部分人来说,qcow2是综合体验最舒服的,我的建议是无脑用,磁盘性能那点差异你在实际使用中根本感觉不出来。
查看当前存储池:
bash复制virsh pool-list
virsh vol-list default
如果列表为空,可以先看下默认池有没有被自动定义,没有就手动定义一个:
bash复制virsh pool-define-as --name default --type dir --target /var/lib/libvirt/images
virsh pool-start default
virsh pool-autostart default
这样后面virt-install创建磁盘时,系统会自动往这个池里塞镜像文件,不用手动指定完整路径。
3. 创建Ubuntu虚拟机
3.1 镜像下载与校验
创建Ubuntu虚拟机前,先下载安装镜像。Ubuntu官方镜像站提供ISO下载,Server版体积小适合命令行安装。下载完一定要校验checksum,这个习惯能避免很多奇怪问题。从镜像站下载对应的SHA256SUMS文件,然后对比:
bash复制sha256sum ubuntu-22.04.5-live-server-amd64.iso
cat SHA256SUMS | grep ubuntu-22.04.5-live-server-amd64.iso
两个输出一致再往下走。我还遇到过一种情况:ISO下载不完整,安装到中间步骤报找不到文件或者解压出错,最后排查半天,回源头一校验发现是MD5对不上。所以镜像校验这事千万别偷懒。
把ISO放到一个宿主机能读到的地方,我习惯放/var/lib/libvirt/boot/目录:
bash复制sudo mkdir -p /var/lib/libvirt/boot
sudo cp ubuntu-22.04.5-live-server-amd64.iso /var/lib/libvirt/boot/
顺带说一句,如果你打算在同一台宿主机上反复装不同版本的Ubuntu或Rocky,建议给每个ISO做个专门的子目录,避免文件混在一起。
3.2 用virt-install命令创建Ubuntu虚拟机
virt-install是创建虚拟机的核心命令,参数很多但套路固定。我给你一条我实际用过的命令,按注释解释每个参数:
bash复制sudo virt-install \
--name ubuntu-01 \
--memory 4096 \
--vcpus 4 \
--disk path=/var/lib/libvirt/images/ubuntu-01.qcow2,size=40,format=qcow2 \
--network bridge=br0 \
--os-variant ubuntu22.04 \
--cdrom /var/lib/libvirt/boot/ubuntu-22.04.5-live-server-amd64.iso \
--graphics vnc,listen=0.0.0.0 \
--noautoconsole
先解释几个关键参数的选择逻辑。
内存和CPU怎么定?4096MB内存加4个vCPU是我给这台虚机的初始配置。如果你的宿主机总内存32GB、CPU是8核,想多开几台虚机就把数字调小,比如2048和2。这里我推荐一个经验值:vCPU数量不要超过物理机逻辑核心数除以计划虚机数量,比如8核宿主机准备跑4台虚机,每台最多分2个vCPU。分配太多反而会因为CPU争抢导致整体性能下降。
--disk参数指定磁盘文件路径、大小、格式。size=40表示磁盘最大容量40GB,qcow2格式下初始只占用很少空间。
--network bridge=br0是这一步的重点,这里的br0必须是我们第二节配置的那个网桥,写virbr0就变成NAT模式了,这是新手最容易踩的坑。
--graphics vnc,listen=0.0.0.0表示开启VNC远程显示,并且监听所有网卡,方便你从局域网里任何一台电脑用VNC客户端连接图形安装界面。--noautoconsole让命令行执行完直接退出,不挂死在终端。
下方命令会输出一个VNC端口号,一般是5900。系统会提示你安装正在进行中,这时在本地电脑用VNC Viewer连宿主机IP:5900就能看到图形安装界面了。如果虚拟机没自动创建成功,看看终端有没有报错,后面第五章我会专门列常见报错。
3.3 Ubuntu Server系统安装要点
通过VNC连上后,UBUNTU Server的安装界面就出来了。整个安装过程按着提示走基本问题不大,但有两个地方需要重点注意。
第一个是网络配置。安装器默认可能选择DHCP,如果宿主机所在局域网有DHCP服务,它会自动拿到一个IP。这里我建议直接改成手动配置,和宿主机保持同一网段的静态IP。操作路径是在网络设置里关掉DHCP,填入规划好的IP、网关和DNS。为什么要这么干?因为装完系统后你大概率用SSH远程操作,如果装的时候拿的是滚动分配的DHCP IP,万一后续租约变了IP变了,你就得再回到VNC里去查新地址,很折腾。
第二个是软件包选择。Ubuntu Server安装结束后会让选安装哪些附加软件,有Docker、OpenSSH server、Snap Store等。我建议只勾选OpenSSH server,Docker等系统装好以后再用命令装,省得安装器自动配置的版本和你想要的不一致。
安装完成后会自动重启,重启后如果VNC黑屏,说明系统已经跑起来了,只是图形会话结束了。这时候直接用SSH登录虚拟机的IP:
bash复制ssh ubuntu@192.168.1.101
初次登录用你安装时设置的账号和密码。登录成功后就一切正常了,可以用sudo权力自由发挥。
3.4 顺便聊聊cloud-init自动化
如果你需要批量创建虚拟机或者追求效率,手动走一遍图形安装还是有点慢。KVM生态里更现代的做法是用cloud-init做自动化。简单说就是给虚拟机一份初始配置,里面写好主机名、用户、SSH公钥、网络配置,虚拟机首次启动时自动应用这些配置,全程无需人工干预。
virt-install配合cloud-init的示例我写在这里:
bash复制sudo virt-install \
--name ubuntu-02 \
--memory 2048 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/ubuntu-02.qcow2,size=30,format=qcow2 \
--network bridge=br0 \
--os-variant ubuntu22.04 \
--cdrom /var/lib/libvirt/boot/ubuntu-22.04.5-live-server-amd64.iso \
--graphics vnc,listen=0.0.0.0 \
--cloud-init user-data=/path/to/user-data,network-config=/path/to/network-config \
--noautoconsole
cloud-init配置属于进阶玩法,第一次搞的话建议先手动装一遍整个流程,熟悉了各个步骤再搞也不迟。我最初就是一套手动流程用到底,后来要同时开三台测试机才专门研究cloud-init,确实省事,但前提是基础要过关。
4. 搭建Rocky Linux虚拟机并完成基础配置
4.1 创建Rocky虚拟机与Ubuntu的差异
Ubuntu虚拟机跑起来后,接着在KVM里搭一台Rocky Linux虚拟机。Rocky Linux是RHEL的社区重建版,和CentOS一脉相承,生产环境里面用得非常多。创建方式和Ubuntu大同小异,核心区别在于镜像和os-variant参数。
先去Rocky官网或者阿里云等镜像站下载Rocky 9的minimal ISO,注意选x86_64架构,文件名通常是Rocky-9.x-x86_64-minimal.iso。为什么选minimal版而不是DVD版?minimal体积小,安装过程快,装完再按需安装软件包,更符合定制化习惯。DVD版自带一大堆用不到的东西,反而拖慢部署速度。
下载完ISO同样放/var/lib/libvirt/boot/,然后执行virt-install:
bash复制sudo virt-install \
--name rocky-01 \
--memory 4096 \
--vcpus 4 \
--disk path=/var/lib/libvirt/images/rocky-01.qcow2,size=50,format=qcow2 \
--network bridge=br0 \
--os-variant rocky9 \
--cdrom /var/lib/libvirt/boot/Rocky-9.x-x86_64-minimal.iso \
--graphics vnc,listen=0.0.0.0 \
--noautoconsole
参数和Ubuntu几乎一样,只有--os-variant从ubuntu22.04换成rocky9。这个os-variant参数可以理解为告诉libvirt这个操作系统用什么虚拟硬件最合适,比如使用什么类型的网卡、什么类型的显示适配器,用对了性能更好。不确定支持哪些系统可以用osinfo-query os查询:
bash复制osinfo-query os | grep -i rocky
安装界面里Rocky的Anaconda安装器比Ubuntu Server更图形化,分区、时区、网络都有向导。网络配置那块同样建议在安装过程中就设置静态IP。安装完成后系统自动重启。
4.2 Rocky静态IP配置实操
Rocky安装完后,默认用的是NetworkManager管理网络,所以配置静态IP最顺手的工具是nmcli。这也是搜索热词里"rocky linux设置静态ip"和"rocky linux系统怎么连有线网"对应的核心内容。
先查看网卡名称:
bash复制nmcli device status
一般第一台网卡叫enp1s0。然后给网卡设置静态IP:
bash复制sudo nmcli con mod enp1s0 ipv4.addresses 192.168.1.102/24
sudo nmcli con mod enp1s0 ipv4.gateway 192.168.1.1
sudo nmcli con mod enp1s0 ipv4.dns 8.8.8.8
sudo nmcli con mod enp1s0 ipv4.method manual
sudo nmcli con up enp1s0
这几条命令的逻辑是:给连接设置IP地址和掩码、设置默认网关、设置DNS、把获取方式改成手动、最后重启网卡连接让配置生效。执行完用ip addr确认IP对不对,然后ping一下网关:
bash复制ip addr show enp1s0
ping -c 4 192.168.1.1
能ping通则说明网络没问题。这里有个小坑:nmcli con mod修改的是连接配置,如果之前创建过多个连接,需要ls --active看一下当前活动连接的名字再操作。我一开始图省事直接照着网上的命令改eth0,结果那台机器网卡叫enp1s0,改了根本没生效,后来nmcli con show一看才发现配置写错地方了。
4.3 开通端口、新建用户与安装Docker
Rocky Linux防火墙默认是firewalld,默认情况下很多端口是不放行的。如果你要在这台虚拟机上跑SSH以外的服务,比如Web服务(80/443)或者自定义端口,必须手动处理。搜索热词里"检查rocky linux是否开通某个端口"说的就是这个需求。
检查端口是否监听:
bash复制ss -tlnp | grep 8080
查看防火墙放行了哪些服务:
bash复制sudo firewall-cmd --list-all
放行一个端口:
bash复制sudo firewall-cmd --permanent --add-port=8080/tcp
sudo firewall-cmd --reload
用--permanent让规则持久化,改完记得reload。不然重启后规则丢失,又要重新配。
新建用户也是日常高频操作,热词里"linux新建用户"指的就是这块。我习惯的创建方式:
bash复制sudo useradd -m -s /bin/bash devuser
sudo passwd devuser
sudo usermod -aG wheel devuser
-g参数给用户加个家目录,-s指定登录Shell为bash,最后一行是把用户加入wheel组获得sudo权限。这个操作在不同发行版下有些差异,Ubuntu里sudo组叫sudo而不是wheel,Rocky里则是wheel,需要分别记忆。
装Docker这块,Rocky和Ubuntu的差异要注意。Ubuntu可以apt install docker.io,Rocky则用dnf。不过我的建议是两个系统都装官方Docker源里的docker-ce,版本新、官方维护,别贪省事装系统自带的。Rocky装docker-ce先添加Docker官方仓库:
bash复制sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf install -y docker-ce docker-ce-cli containerd.io
sudo systemctl enable --now docker
sudo docker run hello-world
Ubuntu上的官方安装流程类似,也是添加仓库后apt install。装完docker run hello-world能出现欢迎消息,说明一切正常。
4.4 中文输入法与常用命令备查
Rocky和Ubuntu作为中文用户,经常遇到输入法问题。热词里"linux输入法"和"ubuntu中文输入法怎么设置"说的其实就是同一个痛点。Linux桌面环境的输入法方案这两年基本统一到了Fcitx5,我这里说下在Rocky图形界面里配ibus中文输入法的大致思路,因为很多云服务器装的都是minimal无图形版,所以这部分主要针对有桌面场景的朋友。
Ubuntu下推荐直接装fcitx5:
bash复制sudo apt install -y fcitx5 fcitx5-chinese-addons
在设置的区域与语言里把fcitx5设为默认输入法,重启会话后在输入法里添加拼音即可。Rocky下命令略有差异:
bash复制sudo dnf install -y fcitx5 fcitx5-chinese-addons
需要注意的是,无论哪个发行版,环境变量配置错误都可能影响输入法启动。检查~/.xprofile或/etc/environment里是否有以下两行:
code复制GTK_IM_MODULE=fcitx
QT_IM_MODULE=fcitx
少了这两行,部分GTK或Qt程序会无法调用输入法。热词里提到的"ubuntu环境变量配置错误"往往就出在这里。配置完环境变量要重新登录或重启图形会话才能生效。
顺手整理一份高频命令清单,覆盖平时用得最多的场景:
| 场景 | 命令 |
|---|---|
| 查看系统信息 | uname -a,cat /etc/os-release |
| 查看磁盘空间 | df -h |
| 查看内存 | free -h |
| 查找文件 | find /path -name "file*" |
| 查看进程 | ps aux |
| 查看服务的端口 | ss -tlnp |
| 下载文件 | wget URL 或 curl -O URL |
| 压缩解压 | tar -czvf,tar -xzvf |
| 系统更新 Ubuntu | sudo apt update && sudo apt upgrade |
| 系统更新 Rocky | sudo dnf update |
| 查看端口连通性 | nc -vz ip port |
这些命令是排查问题时用得最频繁的,建议新手在虚拟机里多敲几遍,形成肌肉记忆。
5. 常见问题与排查技巧实录
5.1 虚拟机无法启动的典型报错
创建虚拟机时最容易碰到的报错是:
code复制ERROR internal error: process exited while connecting to monitor:
kvm: -drive file=...unsupported machine type
多半是os-variant选错了,或者UEFI固件没有正确处理。处理方法是先用osinfo-query os确认正确的os-variant名称,重新执行virt-install。
还有一个高频报错:
code复制ERROR Host does not support any virtual machine acceleration
这个直接说明KVM加速不可用。排查思路三步走:CPU是否支持虚拟化、BIOS虚拟化开关是否打开、/dev/kvm设备是否存在。我之前的机器装完系统后/dev/kvm没有自动创建,后来sudo modprobe kvm_intel手动加载模块才解决。
还有一种情况是VNC连不上,提示Connection refused。先确认虚拟机的VNC端口是不是还活着:
bash复制virsh vncdisplay ubuntu-01
返回:0表示端口5900,:1表示5901。然后检查防火墙有没有放行VNC端口。Ubuntu默认没装firewalld,直接用ufw status看规则,如果是云计算环境还需要看安全组的入方向放行。
5.2 网络不通的排查顺序
虚拟机能开机、SSH连不上,这问题排在虚拟机故障榜前列。我的排查顺序固定是这样:
先看虚拟机和宿主机之间通不通。在宿主机上ping虚拟机的IP,如果ping不通,先确认虚拟机网卡是否正常:
bash复制virsh domiflist ubuntu-01
这个命令会列出虚拟机的网卡信息,重点看它挂在哪个网桥上。如果显示bridge是br0,说明桥接配置在;如果显示virbr0,说明不知什么时候跑到了NAT网络上,虚拟机IP段就会变成192.168.122.x,外部自然访问不到。
再看虚拟机内部网络状态。通过VNC登录进去,ip addr看看网卡有没有IP,ip route看看默认网关是否存在。我在Rocky虚拟机上就遇到过:安完系统网卡没自动启,NMCLI配置写好了但连接没激活。解决方式正是前面提的nmcli con up enp1s0。
如果以上都正常但局域网还是访问不了,检查宿主机是否开了防火墙或者网桥转发功能。临时开转发:
bash复制echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo sysctl -w net.ipv4.ip_forward=1
永久生效则在/etc/sysctl.conf里加net.ipv4.ip_forward=1,然后sysctl -p。
5.3 忘记密码的救援方案
虚拟机忘记密码这事我干过不止一次,还好KVM虚拟机能直接改密码,比物理机方便多了。两台系统的操作路径不太一样。
Ubuntu系进入恢复模式改密码。重启虚拟机,在GRUB菜单选Advanced options,进入recovery mode,选择root Drop to root shell prompt。然后重挂载根文件系统:
bash复制mount -o remount,rw /
passwd ubuntu
输入两次新密码,重启即可。
Rocky系稍微麻烦一点。重启虚拟机,在GRUB菜单按e编辑启动项,在linuxefi那一行的末尾加上rd.break,按Ctrl+X启动。系统会进入紧急模式,然后执行:
bash复制mount -o remount,rw /sysroot
chroot /sysroot
passwd root
touch /.autorelabel
exit
reboot
这里touch /.autorelabel在SELinux开启的Rocky系统上是必须的,不然改完密码重启后SELinux会阻止登录,出现各种诡异问题,这个细节很容易被忽略。
5.4 磁盘扩容与性能优化
虚拟机跑一段时间后,磁盘空间吃紧是最常见的需求。qcow2格式扩容很简单:
bash复制sudo qemu-img resize /var/lib/libvirt/images/ubuntu-01.qcow2 +20G
但注意,这条命令只是给底层的镜像文件扩容,虚拟机里的分区和文件系统并不知道空间变大了。需要登录虚拟机,给分区扩容:
bash复制sudo growpart /dev/sda 1
sudo resize2fs /dev/sda1
Rocky上用xfs文件系统的话,最后一步换xfs_growfs /。如果你操作错了顺序,先resize2fs再growpart,会报错甚至损坏分区表,一定按顺序来。
性能优化方面,生产环境我建议做两件事。一是给虚拟机CPU做pining,把虚拟机的vCPU固定到物理机特定的CPU核上,减少缓存抖动:
bash复制virsh vcpupin ubuntu-01 0 2
virsh vcpupin ubuntu-01 1 6
二是将磁盘缓存模式设为writeback或者none,具体看业务,写多读多次要场景选writeback效果好,还能减少宿主机IO压力:
bash复制virsh edit ubuntu-01
找到
xml复制<driver name='qemu' type='qcow2' cache='writeback'/>
如果只是开发测试环境就别折腾这些了,系统自带默认配置完全够用。生产环境想要极致性能,还可以考虑给虚拟机分配PCIe SSD直通或者SR-IOV网卡,这些都是KVM更深层的高级玩法,一般人用不到。
最后说点实际操作中的体会
这套KVM部署流程我前前后后跑了好几遍,最大的感受是:KVM这个技术栈本身并不难,难的是前期规划和网络配置。网络配置只要想清楚NAT和桥接的区别,按着本文的步骤来基本一次通过;前期规划则要考虑清楚虚拟机数量和资源分配,避免以后反复迁移扩容。
还有个经验是,创建虚拟机的virt-install命令,建议把常用的参数整理成一个脚本模板,换系统名、改IP、调资源就能复用。我现在的习惯是建一个deploy-kvm.sh脚本,每次创建新虚拟机只改开头的变量,比手敲一长串参数省心得多,也不容易出错。
最后再提醒一句,KVM虚拟机的备份很重要。qcow2支持快照,我建议在系统刚装好、还没有装各种服务之前打一个快照:
bash复制virsh snapshot-create-as --domain ubuntu-01 \
--name "sys_clean" \
--description "fresh install"
以后系统被折腾坏了,一条命令就能恢复到干净状态。这个习惯帮我在测试环境里省下了不知道多少重装系统的时间。
