目录
一、KVM 虚拟化基础原理
1.1 KVM 概述
1.2 KVM 架构组成
1.3 KVM 运行模式
1.4 KVM 工作原理
二、KVM 虚拟化平台部署环境准备
2.1 案例环境概述
2.2 硬件虚拟化支持验证
2.3 安装 KVM 所需软件
2.4 设置系统默认运行模式为图形界面
2.5 开启 libvirtd 服务
三、KVM 网络配置
3.1 网络模式介绍
3.2 桥接网络配置
四、使用 virt-manager 图形界面管理 KVM
4.1 启动 virt-manager
4.2 创建存储池
4.3 创建镜像存储池
4.4 创建存储卷
4.5 新建虚拟机
五、KVM 命令行管理虚拟机
5.1 KVM 基本命令集
5.2 虚拟机状态管理
5.3 虚拟机删除与添加
5.4 修改虚拟机配置
六、KVM 文件管理
6.1 磁盘格式管理
6.2 虚拟机文件操作
七、虚拟机克隆与快照管理
7.1 虚拟机克隆
7.2 虚拟机快照
八、总结与注意事项
8.1 关键步骤总结
8.2 注意事项
KVM 虚拟化平台高级管理与故障处理
九、KVM 网络高级配置与优化
9.1 虚拟网络隔离与安全组配置
9.2 绑定多物理网卡提升网络性能
9.3 配置 VLAN 实现网络分段
十、KVM 存储高级管理
10.1 使用 LVM 作为 KVM 存储池
10.2 动态扩展虚拟机磁盘
10.3 配置 iSCSI 共享存储
十一、KVM 虚拟机迁移
11.1 实时迁移(Live Migration)
11.2 冷迁移(Cold Migration)
十二、KVM 性能监控与优化
12.1 性能监控工具
12.2 性能优化措施
十三、KVM 故障处理
13.1 常见启动故障
13.2 网络连接故障
13.3 磁盘空间不足处理
十四、KVM 自动化管理与脚本开发
14.1 批量创建虚拟机脚本
14.2 虚拟机状态监控脚本
十五、KVM 最佳实践与企业应用案例
15.1 企业级 KVM 架构设计
15.2 资源分配策略
15.3 高可用性方案
15.4 备份与容灾策略
十六、KVM 与容器技术结合应用
16.1 KVM 宿主机上部署 Docker 容器
16.2 虚拟机中部署 Kubernetes 集群
16.3 虚拟机与容器资源隔离
十七、KVM 安全加固
17.1 宿主机安全配置
17.2 虚拟机安全隔离
17.3 数据安全保护
十八、KVM 日志管理与审计
18.1 配置详细日志记录
18.2 日志分析与告警
18.3 审计追踪虚拟机变更
十九、KVM 进阶技巧与疑难解答
19.1 解决虚拟机卡顿问题
19.2 修复损坏的 qcow2 磁盘文件
19.3 解决桥接网络丢包问题
二十、KVM 未来发展与新技术应用
20.1 KVM 与 PCIe 设备透传
20.2 KVM 与 ARM 虚拟化支持
20.3 KVM 与容器混合编排
20.4 KVM 性能优化新技术
二十一、KVM 故障处理实战案例
21.1 虚拟机启动报错:"Failed to start domain"
21.2 桥接网络下虚拟机无法获取 IP
21.3 虚拟机频繁卡顿
二十二、KVM 管理自动化脚本集
22.1 虚拟机批量备份脚本
22.2 虚拟机资源监控 Dashboard
二十三、总结与技术演进展望
23.1 KVM 核心优势总结
23.2 未来技术趋势
23.3 运维能力提升建议
KVM(Kernel-based Virtual Machine)是 Linux 内核原生支持的虚拟化技术,自 Linux 2.6.20 版本后整合到内核中。它依托 CPU 虚拟化指令集(如 Intel-VT、AMD-V)实现高性能虚拟化支持,在性能、安全性、兼容性和稳定性上表现优异。
在 KVM 环境中,每个虚拟化操作系统都表现为单个独立的系统进程,可方便地与 Linux 系统中的安全模块(如 SELinux)整合,灵活实现资源管理及分配。
广义的 KVM 包含两部分:
Qemu 本身是一套完整的虚拟化解决方案,纯软件实现虚拟化,但性能较低。KVM 与 Qemu 结合,构成完整的虚拟化平台。
KVM 模块使 Linux 主机成为虚拟机监视器(VMM),在原有 Linux 内核模式和用户模式基础上新增客户模式,客户模式也拥有自己的内核模式和用户模式:
三种模式层次关系如图 1.2 所示,用户模式的 Qemu 通过 ioctl 系统调用进入内核模式,KVM Driver 为虚拟机创建虚拟 CPU 和虚拟内存,执行 VMLAUNCH 指令进入客户模式运行 Guest OS。
KVM 工作流程如下:
cat /proc/cpuinfo | grep vmx
若输出包含 "vmx",说明 CPU 支持虚拟化。
cat /proc/cpuinfo | grep svm
若输出包含 "svm",说明 CPU 支持虚拟化。
lsmod | grep kvm
正常输出如 "kvm_intel",表示 KVM 模块已安装。
通过 YUM 安装 KVM 相关软件包:
# 安装GNOME桌面环境
yum groupinstall -y "GNOME Desktop"
# 安装KVM模块
yum -y install qemu-kvm
# 安装KVM调试工具(可选)
yum -y install qemu-kvm-tools
# 安装构建虚拟机的命令行工具
yum -y install virt-install
# 安装qemu组件
yum -y install qemu-img
# 安装网络支持工具
yum -y install bridge-utils
# 安装虚拟机管理工具
yum -y install libvirt
# 安装图形界面管理工具
yum -y install virt-manager
安装完桌面后,执行以下命令将系统默认运行 target 更改为 graphical.target:
ln -sf /lib/systemd/system/graphical.target /etc/systemd/system/default.target
重启后系统将进入图形化界面。
# 启动libvirtd服务
systemctl start libvirtd
# 设置libvirtd服务开机自启
systemctl enable libvirtd
在 libvirt 中运行 KVM 网络有两种模式:
以桥接模式为例,宿主机 IP 为 192.168.10.1,配置步骤如下:
vim /etc/sysconfig/network-scripts/ifcfg-ens33
添加或修改以下内容:
TYPE=Ethernet
BOOTPROTO=none
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=ens33
UUID=58b0765c-572c-4f63-89a7-1bf720b1fab0
DEVICE=ens33
ONBOOT=yes
BRIDGE=br0
vim /etc/sysconfig/network-scripts/ifcfg-br0
添加以下内容:
TYPE=Bridge
BOOTPROTO=static
DEFROUTE=yes
PEERDNS=yes
PEERROUTES=yes
IPV4_FAILURE_FATAL=no
IPV6INIT=yes
IPV6_AUTOCONF=yes
IPV6_DEFROUTE=yes
IPV6_PEERDNS=yes
IPV6_PEERROUTES=yes
IPV6_FAILURE_FATAL=no
IPV6_ADDR_GEN_MODE=stable-privacy
NAME=br0
DEVICE=br0
ONBOOT=yes
IPADDR=192.168.10.1
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
/etc/init.d/network restart
ifconfig
输出中应包含 br0 接口信息,如:
br0: flags=4163 mtu 1500
inet 192.168.10.1 netmask 255.255.255.0 broadcast 192.168.10.255
inet6 fe80::3362:2f44:ebd1:62e prefixlen 64 scopeid 0x20
ether 00:0c:29:3a:81:cc txqueuelen 1000 (Ethernet)
RX packets 3 bytes 234 (234.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 19 bytes 2613 (2.5 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
说明网卡桥接成功。
virt-manager
以 root 身份执行该命令,打开虚拟系统管理器界面。
virsh -h
ls /etc/libvirt/qemu/
virsh list --all
# 正常关机
virsh shutdown test01
# 启动虚拟机
virsh start test01
virsh destroy test01
virsh create /etc/libvirt/qemu/test01.xml
virsh suspend test01
virsh resume test01
virsh autostart test01
virsh dumpxml test01 > /etc/libvirt/qemu/test02.xml
virsh shutdown test01
virsh undefine test01
cd /etc/libvirt/qemu
mv test02.xml test01.xml
virsh define test01.xml
vim /etc/libvirt/qemu/test01.xml
virsh edit test01
qemu-img info /data_kvm/store/test01.qcow2
virsh shutdown test01
qemu-img convert -f raw -o qcow2 /data_kvm/store/test01.img /data_kvm/store/test01.qcow2
virsh edit test01
修改磁盘部分为:
yum -y install libguestfs-tools-c
virt-cat -a /data_kvm/store/test01.qcow2 /etc/sysconfig/grub
virt-edit -a /data_kvm/store/test01.qcow2 /etc/resolv.conf
virt-df -h test01
virsh list --all
virt-clone -o test01 -n test02 -f /data_kvm/store/test02.qcow2
virsh start test02
virsh snapshot-create test01
virsh snapshot-current test01
virsh snapshot-list test01
virsh snapshot-revert test01 1503494464
virsh snapshot-delete test01 1503494464
通过以上步骤和命令,可完整实现 KVM 虚拟化平台的部署与管理,充分利用 Linux 服务器硬件资源,在物理机上运行多个业务系统,提高资源利用率和系统管理效率。
在企业环境中,常需要对不同业务的虚拟机进行网络隔离。可通过 libvirt 的安全组功能实现:
# 查看默认安全组配置
virsh net-dumpxml default
默认安全组允许所有出站流量,限制入站流量仅响应请求。若需自定义安全组规则,需先定义新网络:
# 创建XML格式的网络定义文件
vim mynetwork.xml
添加以下内容(示例为允许 HTTP/HTTPS 入站的网络):
web-network
创建过滤规则:
vim web-filter.xml
web-filter
应用过滤规则并定义网络:
virsh filter-define web-filter.xml
virsh net-define mynetwork.xml
virsh net-start web-network
virsh net-autostart web-network
当虚拟机网络流量较大时,可绑定多块物理网卡实现负载均衡:
# 安装bonding工具
yum -y install bonding
修改网卡配置文件:
vim /etc/sysconfig/network-scripts/ifcfg-ens33
TYPE=Ethernet
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
ONBOOT=yes
vim /etc/sysconfig/network-scripts/ifcfg-ens34
TYPE=Ethernet
BOOTPROTO=none
MASTER=bond0
SLAVE=yes
ONBOOT=yes
vim /etc/sysconfig/network-scripts/ifcfg-bond0
TYPE=Bond
BOOTPROTO=static
IPADDR=192.168.10.1
NETMASK=255.255.255.0
GATEWAY=192.168.10.254
BONDING_OPTS="mode=4 miimon=100 lacp_rate=1"
ONBOOT=yes
重启网络服务:
systemctl restart network
验证绑定状态:
cat /proc/net/bonding/bond0
在 KVM 中配置 VLAN 可将不同业务虚拟机划分到不同网络段:
# 创建VLAN 100接口
vconfig add ens33 100
# 配置VLAN接口IP
ifconfig eth0.100 192.168.100.1 netmask 255.255.255.0 up
# 保存配置到文件
vim /etc/sysconfig/network-scripts/ifcfg-ens33.100
DEVICE=ens33.100
BOOTPROTO=static
IPADDR=192.168.100.1
NETMASK=255.255.255.0
ONBOOT=yes
VLAN=yes
在 libvirt 中定义使用 VLAN 的网络:
vim vlan-network.xml
vlan100
应用网络定义:
virsh net-define vlan-network.xml
virsh net-start vlan100
virsh net-autostart vlan100
LVM 提供更灵活的存储管理能力,适合动态调整虚拟机磁盘大小:
# 创建物理卷
pvcreate /dev/sdb
# 创建卷组
vgcreate kvm-vg /dev/sdb
# 创建逻辑卷
lvcreate -L 50G -n vm-store kvm-vg
# 格式化逻辑卷
mkfs.ext4 /dev/kvm-vg/vm-store
# 挂载到存储目录
mkdir /data_kvm/lvm-store
mount /dev/kvm-vg/vm-store /data_kvm/lvm-store
# 设置开机自动挂载
echo "/dev/kvm-vg/vm-store /data_kvm/lvm-store ext4 defaults 0 0" >> /etc/fstab
在 virt-manager 中创建存储池时,选择 "逻辑卷" 类型,指定卷组和逻辑卷名称。
当虚拟机磁盘空间不足时,可动态扩展:
# 关闭虚拟机
virsh shutdown test01
# 扩展磁盘文件(假设原大小10G,扩展到15G)
qemu-img resize /data_kvm/store/test01.qcow2 15G
# 启动虚拟机
virsh start test01
# 登录虚拟机扩展文件系统(以ext4为例)
fdisk /dev/vda
# 在fdisk中删除原有分区并重新创建(保留原有数据)
partprobe
resize2fs /dev/vda1
通过 iSCSI 共享存储可实现虚拟机迁移:
在存储服务器上配置 iSCSI Target:
yum -y install iscsitarget
vim /etc/iet/ietd.conf
添加:
Target iqn.2025-06.com.example:kvm-store
BackingStore /dev/sdc1
AuthUser admin admin123
启动服务:
systemctl start iscsitarget
systemctl enable iscsitarget
在 KVM 宿主机上连接 iSCSI:
yum -y install iscsi-initiator-utils
vim /etc/iscsi/initiatorname.iscsi
设置唯一 ID:
InitiatorName=iqn.2025-06.com.example:bdqn-host
发现并登录 iSCSI Target:
iscsiadm -m discovery -t st -p 192.168.10.200
iscsiadm -m node -T iqn.2025-06.com.example:kvm-store -p 192.168.10.200 -l
格式化并挂载:
mkfs.ext4 /dev/sdc
mkdir /data_kvm/iscsi-store
mount /dev/sdc /data_kvm/iscsi-store
在 virt-manager 中创建存储池时,选择 "iSCSI" 类型,指定目标地址和认证信息。
在不中断服务的情况下迁移虚拟机:
前提条件:
配置 libvirtd 支持迁移:
# 修改libvirtd配置文件
vim /etc/libvirt/libvirtd.conf
取消以下行的注释并修改:
listen_tls = 0
listen_tcp = 1
tcp_port = "16509"
listen_addr = "0.0.0.0"
auth_tcp = "sasl"
# 配置SASL认证
vim /etc/sasl2/libvirt.conf
添加:
mech_list: DIGEST-MD5
创建认证用户:
saslpasswd2 -a libvirt admin
重启 libvirtd 服务:
systemctl restart libvirtd
执行实时迁移:
# 在源宿主机上执行迁移
virsh migrate --live --persistent --verbose test01 qemu+ssh://192.168.10.110/system
关闭虚拟机后迁移,适用于非关键业务:
# 关闭虚拟机
virsh shutdown test01
# 导出虚拟机配置
virsh dumpxml test01 > test01.xml
# 复制磁盘文件到目标宿主机
scp /data_kvm/store/test01.qcow2 192.168.10.110:/data_kvm/store/
# 复制配置文件到目标宿主机
scp test01.xml 192.168.10.110:/etc/libvirt/qemu/
# 在目标宿主机上定义并启动虚拟机
virsh define /etc/libvirt/qemu/test01.xml
virsh start test01
# 查看虚拟机CPU和内存使用情况
virsh domtop test01
# 查看虚拟机详细信息
virsh dominfo test01
# 安装libvirt-python
yum -y install libvirt-python
# 使用Python脚本监控
vim monitor.py
import libvirt
conn = libvirt.open("qemu:///system")
vm = conn.lookupByName("test01")
stats = vm.getCPUStats(0)
print("CPU Usage:", stats[0]['cpu_time'] / 10**9, "seconds")
# 设置虚拟机CPU拓扑
virsh setvcpus test01 4 --maximum 8 --config
# 绑定虚拟机CPU到物理核心
virsh vcpupin test01 0 1 --config
# 启用大页内存
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
# 在虚拟机配置中添加大页内存支持
virsh edit test01
添加:
# 使用VirtIO驱动
virsh edit test01
修改磁盘设备为:
# 查看宿主机内存使用情况
free -h
# 调整虚拟机内存设置
virsh setmaxmem test01 2G --config
virsh setmem test01 1G --config
# 检查磁盘文件完整性
qemu-img check /data_kvm/store/test01.qcow2
# 修复磁盘文件(仅适用于qcow2格式)
qemu-img repair /data_kvm/store/test01.qcow2
# 检查宿主机NAT或桥接配置
iptables -t nat -L
ifconfig br0
# 检查虚拟机网络配置
virsh console test01
ip addr show
route -n
# 检查桥接接口配置
brctl show br0
# 检查宿主机防火墙设置
firewall-cmd --list-all
firewall-cmd --permanent --add-masquerade
firewall-cmd --permanent --add-port=80/tcp
firewall-cmd --reload
virsh console test01
du -sh /var/log
rm -rf /var/log/*.log
yum clean all
qemu-img convert -c /data_kvm/store/test01.qcow2 /data_kvm/store/test01-compressed.qcow2
#!/bin/bash
# batch_create_vms.sh
BASE_DIR="/data_kvm/store"
ISO_DIR="/data_kvm/iso"
ISO_FILE="CentOS-7-x86_64-DVD-2009.iso"
NUM_VMS=5
for i in $(seq 1 $NUM_VMS); do
VM_NAME="web-server-$i"
DISK_FILE="$BASE_DIR/$VM_NAME.qcow2"
CONFIG_FILE="/etc/libvirt/qemu/$VM_NAME.xml"
# 创建磁盘文件
qemu-img create -f qcow2 $DISK_FILE 20G
# 使用virt-install创建虚拟机
virt-install --name $VM_NAME \
--ram 1024 \
--vcpus 1 \
--disk path=$DISK_FILE,size=20 \
--cdrom $ISO_DIR/$ISO_FILE \
--network bridge=br0 \
--noautoconsole \
--os-type linux \
--os-variant rhel7 \
--initrd-inject post-install.sh \
--extra-args "ks=file:/post-install.ks" \
--quiet
# 配置自动启动
virsh autostart $VM_NAME
echo "虚拟机 $VM_NAME 创建完成"
done
#!/bin/bash
# vm_monitor.sh
VM_LIST="test01 web-server-1 web-server-2"
LOG_FILE="/var/log/vm_monitor.log"
echo "=== $(date) ===" >> $LOG_FILE
for vm in $VM_LIST; do
status=$(virsh list --all | grep $vm | awk '{print $2}')
cpu=$(virsh domtop $vm | tail -1 | awk '{print $2}')
mem=$(virsh domtop $vm | tail -1 | awk '{print $3}')
echo "虚拟机: $vm" >> $LOG_FILE
echo " 状态: $status" >> $LOG_FILE
echo " CPU使用率: $cpu%" >> $LOG_FILE
echo " 内存使用率: $mem%" >> $LOG_FILE
done
# 发送告警邮件(示例)
if grep -q "关闭" $LOG_FILE; then
echo "虚拟机状态异常,请查看日志" | mail -s "KVM虚拟机告警" [email protected]
fi
某企业 IT 部门为提高服务器资源利用率,设计了以下 KVM 架构:
# 绑定web-server-1的CPU 0到物理核心1
virsh vcpupin web-server-1 0 1 --config
# 设置数据库服务器最大可使用8个CPU核心
virsh setvcpus db-server 4 --maximum 8 --config
# 为web-server-1预留2GB内存,最大可使用4GB
virsh setmem web-server-1 2G --config
virsh setmaxmem web-server-1 4G --config --live
# 配置大页内存
echo 1024 > /sys/kernel/mm/hugepages/hugepages-2048kB/nr_hugepages
通过 pacemaker+corosync 实现 KVM 宿主机集群高可用:
yum -y install pacemaker corosync pcs
pcs cluster auth node1 node2 node3 node4 -u hacluster -p cluster123
pcs cluster setup --name kvm-cluster node1 node2 node3 node4
pcs cluster start --all
pcs cluster enable --all
# 添加IP资源
pcs resource create vip ocf:heartbeat:IPaddr2 ip=192.168.1.100 cidr_netmask=24
# 添加NFS共享存储资源
pcs resource create nfs-store ocf:heartbeat:NFS server=192.168.20.100 path=/kvm-store
# 添加libvirtd服务资源
pcs resource create libvirtd systemd:libvirtd
# 创建资源组
pcs resource group add kvm-resources vip nfs-store libvirtd
pcs constraint colocation add libvirtd with nfs-store INFINITY
pcs constraint colocation add vip with nfs-store INFINITY
pcs constraint order nfs-store then libvirtd
#!/bin/bash
BACKUP_DIR="/backup/kvm/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR/config $BACKUP_DIR/disks
for vm in $(virsh list --all | grep -v "名称" | awk '{print $2}'); do
# 备份配置文件
virsh dumpxml $vm > $BACKUP_DIR/config/$vm.xml
# 备份磁盘文件(仅增量修改部分)
for disk in $(virsh domblklist $vm | grep -v "目标" | awk '{print $2}'); do
disk_path=$(virsh domblklist $vm | grep $disk | awk '{print $1}')
if [ -f $disk_path ]; then
qemu-img create -f qcow2 -b $disk_path $BACKUP_DIR/disks/$vm-$disk.qcow2
fi
done
done
# 压缩备份并删除7天前的旧备份
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR
rm -rf $(find /backup/kvm/ -type d -mtime +7)
rsync -avz -e "ssh -p 2222" /backup/kvm/ remote-host:/异地备份/kvm/
# 在异地宿主机上恢复虚拟机
virsh define /异地备份/kvm/20250616/config/test01.xml
virsh start test01
在 KVM 宿主机上同时运行虚拟机和容器,实现混合架构:
yum -y install docker
systemctl start docker
systemctl enable docker
# 运行MySQL容器
docker run -d --name mysql-container \
-e MYSQL_ROOT_PASSWORD=password \
-p 3306:3306 \
-v /data/mysql:/var/lib/mysql \
mysql:8.0
# 创建桥接网络
docker network create -d bridge --subnet=172.18.0.0/16 kvm-docker-network
# 将容器连接到桥接网络
docker network connect kvm-docker-network mysql-container
# 在虚拟机中添加路由
virsh console test01
route add -net 172.18.0.0 netmask 255.255.0.0 gw 192.168.10.1
在 KVM 虚拟机中搭建容器编排平台:
# web-node-1: 192.168.10.110
# web-node-2: 192.168.10.111
# master-node: 192.168.10.112
kubeadm init --pod-network-cidr=192.168.0.0/16
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
kubeadm join 192.168.10.112:6443 --token --discovery-token-ca-cert-hash sha256:
通过 cgroups 和 namespace 实现资源隔离:
# 限制容器使用1个CPU核心和512MB内存
docker run -d --name app-container \
--cpus=1 --memory=512m \
-p 8080:8080 \
myapp:v1
# 创建cgroup控制器
mkdir -p /cgroup/cpu/vm-test01
echo "1024" > /cgroup/cpu/vm-test01/cpu.shares
# 将虚拟机进程添加到cgroup
echo $(pgrep -f qemu-system-x86) > /cgroup/cpu/vm-test01/tasks
systemctl disable --now avahi-daemon firewalld
vim /etc/ssh/sshd_config
修改:
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
vim /etc/selinux/config
设置:
SELINUX=enforcing
重启后应用策略:
setenforce 1
# 允许libvirt访问网络
semanage permissive -a virt_t
# 创建Web服务器安全组
virsh secgroup-add web-secgroup
virsh secgroup-rule-add web-secgroup ipv4 ingress tcp --dport 80 -j ACCEPT
virsh secgroup-rule-add web-secgroup ipv4 ingress tcp --dport 443 -j ACCEPT
# 将安全组应用到虚拟机
virsh domsecgroup-add web-server-1 web-secgroup
# 限制虚拟机最大CPU使用率为50%
virsh setvcpus web-server-1 2 --maximum 2 --config --live
# 禁用虚拟机USB接口
virsh detach-device web-server-1 '{"@type":"usb-host","host":{"vendor-id":"0x1234","product-id":"0x5678"}}'
# 对虚拟机磁盘文件加密
qemu-img convert -f qcow2 -O qcow2 -o encryption=on,encrypt.key-file=/root/key.txt /data_kvm/store/test01.qcow2 /data_kvm/store/test01-encrypted.qcow2
# 修改虚拟机配置使用加密磁盘
virsh edit test01
添加:
12345678-1234-1234-1234-1234567890ab
# 创建加密密钥
dd if=/dev/urandom of=/root/key.txt bs=32 count=1
chmod 600 /root/key.txt
# 注册密钥到libvirt
virsh secret-define --file secret.xml
secret.xml 内容:
12345678-1234-1234-1234-1234567890ab
/data_kvm/store/test01-encrypted.qcow2
vim /etc/libvirt/libvirtd.conf
取消注释并修改:
log_level = 7
log_facility = "local0"
log_outputs = "file:/var/log/libvirt/libvirtd.log"
重启服务:
systemctl restart libvirtd
# 创建审计脚本
vim /usr/local/sbin/virsh-audit.sh
内容:
#!/bin/bash
if [ $# -gt 0 ]; then
action=$1
vm=$2
user=$(who am i | awk '{print $1}')
ip=$(who am i | awk '{print $5}' | sed 's/[()]//g')
echo "[$(date)] $user($ip) 执行: virsh $action $vm" >> /var/log/virsh-audit.log
fi
赋予执行权限:
chmod +x /usr/local/sbin/virsh-audit.sh
创建软链接:
ln -s /usr/local/sbin/virsh-audit.sh /usr/bin/virsh
# 查找最近1小时内的错误日志
grep "ERROR" /var/log/libvirt/libvirtd.log | grep "$(date -d '1 hour ago' '+%b %d %H')"
# 查看特定虚拟机日志
grep "test01" /var/log/libvirt/libvirtd.log
#!/bin/bash
# alert.sh
ERROR_COUNT=$(grep -c "ERROR" /var/log/libvirt/libvirtd.log)
if [ $ERROR_COUNT -gt 5 ]; then
error_msgs=$(grep "ERROR" /var/log/libvirt/libvirtd.log | tail -5)
echo "KVM出现异常错误,错误数量: $ERROR_COUNT" | mail -s "KVM日志告警" [email protected] <<< "$error_msgs"
fi
添加定时任务:
crontab -e
*/10 * * * * /bin/bash /usr/local/sbin/alert.sh
# 安装etckeeper跟踪配置文件变化
yum -y install etckeeper
cd /etc/libvirt/qemu
etckeeper init
git add *.xml
git commit -m "初始化KVM配置文件"
# 查看虚拟机配置变更历史
cd /etc/libvirt/qemu
git log test01.xml
# 查看谁何时操作了虚拟机
grep "virsh start" /var/log/virsh-audit.log | grep "test01"
dmesg | grep -i virtualization
# 若未启用,需进入BIOS开启Intel-VT或AMD-V
virsh edit test01
添加:
# 备份原磁盘文件
cp /data_kvm/store/test01.qcow2 /data_kvm/store/test01.qcow2.bak
# 使用qemu-img修复
qemu-img check -r all /data_kvm/store/test01.qcow2
# 若修复失败,尝试转换格式后修复
qemu-img convert -f qcow2 -O qcow2 /data_kvm/store/test01.qcow2 /data_kvm/store/test01-fixed.qcow2
# 增加桥接接口队列长度
ethtool -G br0 rx 4096 tx 4096
# 启用RSS功能
ethtool -L ens33 combined 8
vim /etc/sysctl.conf
添加:
net.core.rmem_max = 16777216
net.core.wmem_max = 16777216
net.ipv4.tcp_rmem = 4096 87380 16777216
net.ipv4.tcp_wmem = 4096 65536 16777216
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_fin_timeout = 30
应用配置:
sysctl -p
将物理设备直接分配给虚拟机,提升性能并支持 GPU 等专用硬件:
vim /etc/default/grub
GRUB_CMDLINE_LINUX
中添加: plaintext
intel_iommu=on iommu=pt
grub2-mkconfig -o /boot/grub2/grub.cfg
reboot
lspci -nn | grep -i "physical function"
virsh edit test01
01:00.0
为实际设备 PCI 地址):
随着 ARM 服务器普及,KVM 对 ARM 架构的支持逐渐完善:
# 在ARM版CentOS中安装KVM
yum -y install qemu-kvm-arm libvirt
virt-install --name arm-vm --arch aarch64 --machine virt-4.0 --ram 2048 --disk path=/data_kvm/arm-vm.qcow2,size=10 --cdrom /data_kvm/arm-centos.iso --network bridge=br0 --noautoconsole
通过 KubeVirt 项目在 Kubernetes 中管理虚拟机:
# 安装Operator SDK
curl -LO https://github.com/operator-framework/operator-sdk/releases/download/v1.22.0/operator-sdk_v1.22.0_linux_amd64.tar.gz
tar -xzf operator-sdk_v1.22.0_linux_amd64.tar.gz -C /usr/local/bin
# 部署KubeVirt
operator-sdk run --local --namespace kubevirt
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: vm-example
spec:
running: true
template:
metadata:
labels:
vm: vm-example
spec:
domains:
- name: vm-example
resources:
requests:
memory: "1Gi"
volumes:
- name: containerdisk
containerDisk:
image: quay.io/kubevirt/cirros-container-disk-demo:latest
networks:
- name: default
pod: {}
echo 128 > /sys/kernel/mm/hugepages/hugepages-1048576kB/nr_hugepages
virsh edit test01
qemu-img create -f qcow2 -o iothread=on /data_kvm/fast-vm.qcow2 20G
故障现象:
virsh start test01
error: Failed to start domain test01
error: internal error: process exited while connecting to monitor: 2025-06-16T10:30:00.123Z qemu-system-x86_64[12345]: -drive file=/data_kvm/store/test01.qcow2,if=virtio,cache=none: Could not open '/data_kvm/store/test01.qcow2': No such file or directory
解决方案:
ls -la /data_kvm/store/test01.qcow2
chown libvirt:libvirt /data_kvm/store/test01.qcow2
virsh undefine test01
virsh define /etc/libvirt/qemu/test01.xml
故障现象:
虚拟机启动后ip addr
显示无 IP 地址,dmesg
提示:
[ 1234.567] e1000: eth0: Link is down
解决方案:
brctl show br0
virsh domiflist test01
systemctl restart network
virsh console test01
ifconfig eth0 192.168.10.100 netmask 255.255.255.0 up
route add default gw 192.168.10.254
故障现象:
虚拟机操作延迟高,virsh domtop
显示 CPU 使用率波动大。
解决方案:
top -c
virsh migrate test01 qemu+ssh://node2/system
virsh setvcpus test01 2 --config --live
virsh setvcpupin test01 0 2 --config --live
virsh edit test01
2
#!/bin/bash
# KVM虚拟机批量备份脚本
# 功能:自动备份所有虚拟机配置和磁盘文件
DATE=$(date +%Y%m%d_%H%M)
BACKUP_DIR="/backup/kvm/$DATE"
LOG_FILE="/var/log/kvm_backup.log"
# 确保备份目录存在
mkdir -p $BACKUP_DIR/{config,disks,logs}
# 记录备份开始
echo "=== KVM Backup Start at $DATE ===" >> $LOG_FILE
# 遍历所有虚拟机
for VM in $(virsh list --all | grep -v "名称" | awk '{print $2}'); do
VM_LOG="$BACKUP_DIR/logs/$VM.log"
echo "=== Backup VM: $VM ===" >> $VM_LOG
# 备份配置文件
virsh dumpxml $VM > $BACKUP_DIR/config/$VM.xml
if [ $? -eq 0 ]; then
echo "Config backup success for $VM" >> $VM_LOG
else
echo "Config backup failed for $VM" >> $VM_LOG
continue
fi
# 备份磁盘文件
DISK_PATHS=$(virsh domblklist $VM | grep -v "目标" | awk '{print $1}')
for DISK in $DISK_PATHS; do
if [ -f "$DISK" ]; then
DISK_NAME=$(basename $DISK)
BACKUP_DISK="$BACKUP_DIR/disks/$VM-$DISK_NAME"
cp "$DISK" "$BACKUP_DISK"
if [ $? -eq 0 ]; then
echo "Disk $DISK_NAME backup success" >> $VM_LOG
else
echo "Disk $DISK_NAME backup failed" >> $VM_LOG
fi
fi
done
echo "=== VM $VM backup completed ===" >> $VM_LOG
done
# 压缩备份并清理旧数据
tar -czf $BACKUP_DIR.tar.gz $BACKUP_DIR
find /backup/kvm -type d -mtime +7 -exec rm -rf {} \;
# 记录备份结束
END_TIME=$(date +%H%M)
echo "=== KVM Backup End at $END_TIME, Duration: $(($(date -d $END_TIME +%s) - $(date -d $DATE +%s)))s ===" >> $LOG_FILE
#!/usr/bin/env python3
# KVM虚拟机资源监控Dashboard
import libvirt
import psutil
import time
from flask import Flask, render_template
app = Flask(__name__)
conn = libvirt.open("qemu:///system")
def get_vm_stats(vm_name):
vm = conn.lookupByName(vm_name)
stats = vm.getCPUStats(0)
cpu_time = stats[0]['cpu_time'] / 10**9
memory = vm.memoryStats()
return {
'name': vm_name,
'state': vm.info()[0],
'cpu_usage': cpu_time,
'memory_used': memory['actual'] / 1024**3,
'memory_total': vm.maxMemory() / 1024**3
}
@app.route('/')
def index():
vms = []
for vm_name in conn.listDefinedDomains() + conn.listRunningDomains():
vms.append(get_vm_stats(vm_name))
host_stats = {
'cpu_percent': psutil.cpu_percent(interval=1),
'memory_percent': psutil.virtual_memory().percent,
'disk_usage': psutil.disk_usage('/').percent
}
return render_template('index.html', vms=vms, host=host_stats)
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000)
部署步骤:
pip install flask libvirt-python psutil
index.html
python kvm_dashboard.py