好的,我已经将您提供的文本内容整理成了 Markdown 格式的文档。以下是整理后的内容,其中您的原始命令保持不变,并在每个主要部分后面增加了“优化建议与说明”部分。
# Linux KVM 虚拟机部署与配置指南
本文档提供了在 Linux 系统上安装和配置 KVM 虚拟机环境,并创建 Debian 和 Windows 虚拟机的步骤。
## 一、系统内核参数优化 (KVM 相关)
这些设置旨在优化宿主机的虚拟化性能和网络处理能力。
```shell
cat <<EOF> /etc/sysctl.d/99-kvm.conf
vm.swappiness=0
vm.dirty_background_ratio=5
vm.dirty_ratio=10
net.core.default_qdisc = fq
net.ipv4.tcp_congestion_control = bbr
net.ipv4.tcp_rmem = 4096 87380 67108864
net.ipv4.tcp_wmem = 4096 16384 67108864
net.ipv4.tcp_mem = 67108864 67108864 67108864
net.core.rmem_max = 67108864
net.core.wmem_max = 67108864
EOF
优化建议与说明
即时生效:创建或修改
/etc/sysctl.d/
下的配置文件后,需要执行以下命令之一使设置立即生效,而无需重启:sudo sysctl -p /etc/sysctl.d/99-kvm.conf # 或者,如果系统中还有其他 sysctl 配置文件,可以使用: sudo sysctl --system
参数说明:
vm.swappiness=0
: 最小化交换分区的使用,倾向于将不活动内存保留在 RAM 中,对于内存充足的服务器,这可以提高性能。vm.dirty_background_ratio=5
: 当脏页(已修改但未写入磁盘的内存页)达到系统内存的 5% 时,内核开始在后台将其异步写入磁盘。vm.dirty_ratio=10
: 当脏页达到系统内存的 10% 时,产生IO的进程会被强制同步写入磁盘,这可能导致进程阻塞。这两个比例的设置需要根据磁盘性能和应用负载进行调整。net.core.default_qdisc = fq
: 设置默认的排队规则为 Fair Queue (FQ),有助于减少缓冲区膨胀 (bufferbloat)。net.ipv4.tcp_congestion_control = bbr
: 启用 BBR 拥塞控制算法,通常能显著提高网络吞吐量和降低延迟,尤其是在有一定丢包率的长距离链路上。net.ipv4.tcp_rmem
,net.ipv4.tcp_wmem
,net.core.rmem_max
,net.core.wmem_max
: 这些参数调整 TCP 接收和发送缓冲区的大小以及核心套接字缓冲区的最大值。较大的缓冲区可以提高高带宽、高延迟网络下的性能,但也会消耗更多内存。net.ipv4.tcp_mem
控制TCP协议栈使用的总内存页数。这些值通常是针对特定网络环境优化的,给定的值 (67108864
bytes = 64MB) 属于较大设置。
二、CPU 性能配置
将 CPU 调速器设置为 performance
模式,以确保 CPU 运行在最高频率,有利于虚拟机性能。
apt-get -y install cpufrequtils linux-cpupower
cpupower frequency-info | grep -i governor
watch -n 1 'cat /proc/cpuinfo | grep MHz'
cpupower frequency-set -g performance
cat <<EOF> /etc/default/cpufrequtils
ENABLE_CPufreq=true
GOVERNOR="performance"
EOF
优化建议与说明
包管理:
linux-cpupower
是较新的工具,通常已取代cpufrequtils
。在某些发行版中,安装linux-cpupower
可能就足够了。watch
命令:watch -n 1 'cat /proc/cpuinfo | grep MHz'
是一个交互式命令,用于实时监控 CPU 频率。在脚本中执行时,它会持续运行直到手动停止 (Ctrl+C)。如果这是自动化脚本的一部分,您可能需要移除此行或将其后台运行并稍后杀死。持久化设置:写入
/etc/default/cpufrequtils
文件并通过cpufrequtils
服务来持久化 CPU governor 设置是一个传统方法。现代 systemd 系统可能有其他方式来管理 CPU governor,例如通过tuned
服务或自定义 systemd 服务单元。确保cpufrequtils
服务(如果存在的话)已启用并在启动时运行,以使/etc/default/cpufrequtils
中的设置生效。systemd
方式:对于使用systemd
的系统,可以创建一个服务单元来在启动时设置 governor,例如:# /etc/systemd/system/cpupower-performance.service [Unit] Description=Set CPU Frequency Governor to performance [Service] Type=oneshot ExecStart=/usr/bin/cpupower frequency-set -g performance [Install] WantedBy=multi-user.target
然后运行:
sudo systemctl daemon-reload sudo systemctl enable --now cpupower-performance.service
三、安装基础软件包与 KVM 组件
安装必要的工具和 KVM/Libvirt 相关的软件包。
apt-get install -y curl wget vim net-tools git cpu-checker
kvm-ok
apt-get -y install -y qemu-kvm libvirt-daemon-system libvirt-clients bridge-utils virtinst libosinfo-bin
优化建议与说明
合并安装命令:可以将多个
apt-get install
命令合并为一个,以减少命令数量并可能优化依赖解析过程。sudo apt-get update # 始终建议在安装前更新包列表 sudo apt-get install -y curl wget vim net-tools git cpu-checker \ qemu-kvm libvirt-daemon-system libvirt-clients \ bridge-utils virtinst libosinfo-bin
kvm-ok
:kvm-ok
命令用于检查系统是否支持 KVM 以及 KVM 是否已正确启用。在脚本中,其输出可用于条件判断,但在这里它仅用于显示信息。
四、配置 Libvirt 服务和网络
启用并启动 libvirtd
服务,并配置默认的虚拟网络。
systemctl enable libvirtd --now
virsh net-list --all
virsh net-start default
virsh net-autostart default
优化建议与说明
- 步骤清晰,通常这些命令足以确保
libvirtd
运行并使default
网络可用。 - 错误检查:在脚本中,可以在关键命令后添加错误检查,例如
|| exit 1
,以确保在发生错误时脚本停止执行。
五、安装 noVNC 和配置 QEMU VNC
安装 noVNC 和 Websockify 以便通过浏览器访问虚拟机控制台,并修改 QEMU 配置以允许 VNC 访问。
apt-get install -y novnc websockify
cat <<EOF>> /etc/libvirt/qemu.conf
vnc_listen = "0.0.0.0"
vnc_keymap = "en-us"
vnc_sasl = 0
vnc_tls = 0
EOF
systemctl restart libvirtd
优化建议与说明
- 包安装:
novnc
和websockify
也可以合并到前面提到的综合apt-get install
命令中。 qemu.conf
修改:vnc_listen = "0.0.0.0"
: 使 VNC 服务监听所有网络接口,允许从外部访问。请务必注意这带来的安全风险,并确保有防火墙规则保护。vnc_keymap = "en-us"
: 设置 VNC 键盘映射。vnc_sasl = 0
和vnc_tls = 0
: 禁用 SASL 认证和 TLS 加密。在生产环境中,强烈建议启用 TLS 以确保 VNC 连接的安全性,并考虑使用 SASL 或其他认证机制。
libvirtd
重启:修改qemu.conf
后重启libvirtd
服务是必要的,以使配置生效。
六、准备虚拟机镜像和 ISO 文件
6.1 下载 Debian ISO
下载 Debian 安装镜像。
mkdir -p /data/libvirtd/iso
screen -S wget-debian
# 在 screen 会话中执行:
# wget https://mirrors.tuna.tsinghua.edu.cn/debian-cd/12.10.0/amd64/iso-dvd/debian-12.10.0-amd64-DVD-1.iso
(注意:wget
命令通常在 screen
会话内部手动执行)
优化建议与说明
screen
命令:screen -S wget-debian
启动一个新的screen
会话。wget
命令通常是在进入该会话后手动输入的,以便下载过程可以在后台持续进行,即使用户断开 SSH 连接。如果希望在脚本中自动开始下载,可以这样做:mkdir -p /data/libvirtd/iso wget -P /data/libvirtd/iso -c https://mirrors.tuna.tsinghua.edu.cn/debian-cd/12.10.0/amd64/iso-dvd/debian-12.10.0-amd64-DVD-1.iso & # 或者使用 screen 并在其中执行命令(更复杂): # screen -dmS wget-debian wget -P /data/libvirtd/iso -c https://mirrors.tuna.tsinghua.edu.cn/debian-cd/12.10.0/amd64/iso-dvd/debian-12.10.0-amd64-DVD-1.iso
wget -P /path/to/dir
直接下载到指定目录。-c
参数用于断点续传。ISO 版本:ISO 文件的 URL 包含版本号 (
12.10.0
)。此版本可能会过时。考虑使用指向stable
或最新版本的通用链接,或定期更新此链接。
6.2 创建 Debian 虚拟机磁盘镜像
为 Debian 虚拟机创建一个 qcow2 格式的磁盘镜像。
mkdir -p /data/libvirt/qcow2
qemu-img create -f qcow2 /data/libvirt/qcow2/debian12-vm1-forTest.qcow2 100G
优化建议与说明
- 目录结构和磁盘创建命令是标准的。
qcow2
支持快照和稀疏分配(按需增长),是不错的选择。
七、安装 Debian 虚拟机
7.1 查询可用操作系统变体
osinfo-query os
优化建议与说明
- 此命令列出
libosinfo
数据库中所有已知的操作系统变体,帮助为virt-install
的--os-variant
参数选择合适的值。为了获得最新的列表,确保libosinfo-bin
包是最新的。
7.2 使用 virt-install
创建 Debian VM
virt-install \
--name debian12-vm1-forTest \
--cpu host-passthrough \
--ram 8192 \
--vcpus 4 \
--disk path=/data/libvirt/qcow2/debian12-vm1-forTest.qcow2,format=qcow2,bus=virtio \
--network network=default,model=virtio \
--graphics vnc,listen=0.0.0.0,port=-1,keymap=en-us \
--cdrom /data/libvirt/iso/debian-12.10.0-amd64-DVD-1.iso \
--boot uefi,cdrom,hd \
--noautoconsole \
--os-variant debian10
优化建议与说明
--os-variant
:您使用的是 Debian 12.10.0 的 ISO,但指定了--os-variant debian10
。如果osinfo-query os
的输出中包含debian12
或更新的 Debian 版本(如debiantesting
,unstable
),使用更匹配的版本(如--os-variant debian12
)通常更好,因为它会为 libvirt 提供更准确的关于操作系统特性和推荐配置的信息。如果找不到精确匹配,generic
也是一个选项。--cpu host-passthrough
: 这会将宿主机的 CPU 特性直接暴露给虚拟机,通常能提供最佳性能,但可能影响虚拟机的迁移性到不同 CPU 型号的宿主机。--graphics vnc,listen=0.0.0.0,port=-1
:port=-1
表示 libvirt 会自动选择一个可用的 VNC 端口,从 5900 开始。--boot uefi,...
: 指定使用 UEFI 固件启动。这需要宿主机安装了 OVMF 包 (通常是ovmf
或qemu-efi-aarch64
/qemu-efi-arm
取决于架构)。apt search ovmf
可以查找。--noautoconsole
: 安装后不自动连接到虚拟机控制台。
7.3 访问 Debian VM 的 VNC 控制台
以下命令和注释演示了如何查找 VNC 端口并使用 websockify
启动 noVNC 访问。
virsh vncdisplay debian12-vm1-forTest
# 假设上面的命令输出 :0 (表示端口 5900)
# :0
websockify -D --web /usr/share/novnc/ 6080 localhost:5900
# 然后通过浏览器访问:
# http://<公网IP>:6080/vnc.html
# 如果是另一个 VM 或者 VNC display 是 :1 (表示端口 5901)
# virsh vncdisplay some-other-vm
# :1
# websockify -D --web /usr/share/novnc/ 6081 localhost:5901
优化建议与说明
VNC 端口解释:
virsh vncdisplay <VM_NAME>
会返回 VNC 显示号,如:0
,:1
等。VNC 真实端口号是5900 + 显示号
。例如,:0
对应端口5900
,:1
对应端口5901
。websockify
:-D
: 以守护进程模式运行。--web /usr/share/novnc/
: 指定 noVNC 网页文件所在的目录。这个路径可能因发行版或 noVNC 安装方式而异。6080
: noVNC 对外服务的端口。localhost:5900
:websockify
连接的本地 VNC 服务地址和端口。
动态化脚本:如果想在脚本中自动获取 VNC 端口并启动
websockify
,可以这样做:VM_NAME="debian12-vm1-forTest" VNC_DISPLAY_INFO=$(virsh vncdisplay "$VM_NAME") # 例如输出 "127.0.0.1:0" 或 ":0" # 提取显示号 VNC_DISPLAY_NUM=$(echo "$VNC_DISPLAY_INFO" | awk -F':' '{print $NF}') VNC_PORT=$((5900 + VNC_DISPLAY_NUM)) WEBSOCKIFY_PORT=$((6080 + VNC_DISPLAY_NUM)) # 确保 websockify 端口不冲突 echo "Starting websockify for $VM_NAME on port $WEBSOCKIFY_PORT (VNC on $VNC_PORT)" websockify -D --web /usr/share/novnc/ "$WEBSOCKIFY_PORT" "localhost:$VNC_PORT" echo "Access noVNC at http://<Your_Public_IP>:$WEBSOCKIFY_PORT/vnc.html"
防火墙:确保宿主机的防火墙允许访问
websockify
使用的端口(例如 6080, 6081)。
八、安装 Windows Server 2022 虚拟机
8.1 创建 Windows Server 虚拟机磁盘镜像
qemu-img create -f qcow2 /data/libvirt/qcow2/winServer2022-vm1-forTest.qcow2 200G
优化建议与说明
- 创建过程与 Debian VM 类似。
8.2 使用 virt-install
创建 Windows Server VM
virt-install \
--name win2022-vm1-forTest \
--ram 16384 \
--vcpus 8 \
--cpu host-passthrough \
--disk path=/data/libvirt/qcow2/winServer2022-vm1-forTest.qcow2,format=qcow2,bus=scsi \
--controller type=scsi,model=virtio-scsi \
--disk path=/data/libvirt/iso/winServer2022.iso,device=cdrom,bus=sata \
--disk path=/data/libvirt/iso/virtio-win-0.1.271.iso,device=cdrom,bus=sata \
--network network=default,model=virtio \
--graphics vnc,listen=0.0.0.0,port=-1 \
--boot uefi \
--noautoconsole \
--os-variant win2k19
优化建议与说明
--os-variant
:对于 Windows Server 2022,如果osinfo-query os
中存在win2k22
或类似条目,则使用它会更好 (--os-variant win2k22
)。否则win2k19
通常也能工作。- VirtIO 驱动:
--disk ...,bus=scsi --controller type=scsi,model=virtio-scsi
: 为主硬盘使用virtio-scsi
是 Windows 虚拟机获取良好磁盘性能的推荐方式。--disk path=/data/libvirt/iso/virtio-win-0.1.271.iso,...
: 附加 VirtIO 驱动 ISO 非常重要。Windows 安装程序默认可能不包含 VirtIO 驱动,因此在安装过程中需要从此 ISO 加载驱动程序(特别是磁盘和网络驱动)。- VirtIO ISO 版本 (
0.1.271
):建议从 Fedora 的 VirtIO-win ISO 仓库 下载最新的稳定版 VirtIO 驱动 ISO。
- ISO 路径:确保
/data/libvirt/iso/winServer2022.iso
和/data/libvirt/iso/virtio-win-0.1.271.iso
路径正确且文件存在。
8.3 访问 Windows VM 的 VNC 控制台
virsh vncdisplay win2022-vm1-forTest
# 假设返回 :1
# :1
websockify -D --web /usr/share/novnc/ 6081 localhost:5901
优化建议与说明
- 同 Debian VM 的 VNC 访问说明。如果这是继 Debian VM 之后创建的第二个 VM,并且 VNC 端口是自动分配的,那么
:1
(端口 5901) 是一个合理的预期。使用上面提到的动态化脚本获取端口会更可靠。
九、管理 Libvirt 存储池和虚拟机 (示例)
这些命令演示了如何销毁(使非活动)、禁用自动启动和取消定义一个名为 iso
的存储池,以及如何销毁一个虚拟机。
virsh pool-list --all
virsh pool-destroy iso
virsh pool-autostart iso --disable
virsh pool-undefine iso
virsh destroy win2022-vm1-forTest
优化建议与说明
- 存储池
iso
:脚本前面并未显式创建名为iso
的virsh
存储池。这些命令假设该存储池已存在。通常,ISO 文件可以直接通过--cdrom /path/to/iso
使用,而不必一定在virsh
存储池中管理。如果您确实创建了iso
存储池(例如,类型为dir
,路径为/data/libvirtd/iso
),那么这些命令是相关的。 - 销毁顺序:
virsh pool-destroy <pool_name>
: 使存储池变为非活动状态。virsh pool-delete <pool_name>
: (可选) 如果是基于目录的池,这可能会删除池的定义(但不删除目录内容)。对于其他类型的池,它会执行相应的删除操作。virsh pool-undefine <pool_name>
: 从 libvirt 配置中彻底移除存储池的定义。必须先destroy
并且可能delete
。
virsh destroy <vm_name>
: 强制关闭虚拟机(相当于拔电源)。如果想尝试正常关机,应先使用virsh shutdown <vm_name>
,等待一段时间后再用destroy
(如果shutdown
未成功)。
十、IPTables 端口转发规则 (示例)
为虚拟机 192.168.122.102
的 22
端口(SSH)设置端口转发,使得访问宿主机的 30001
端口时流量被转发到虚拟机的 SSH 服务。
iptables -t nat -I PREROUTING -p tcp --dport 30001 -j DNAT --to-destination 192.168.122.102:22
iptables -I FORWARD -p tcp -d 192.168.122.102 --dport 22 -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
iptables -t nat -I POSTROUTING -p tcp -d 192.168.122.102 --dport 22 -j MASQUERADE
优化建议与说明
虚拟机 IP 地址:
192.168.122.102
是一个示例 IP。虚拟机的实际 IP 地址可能因 libvirt 的 DHCP 配置而异。您可能需要先启动虚拟机,然后通过virsh domifaddr <vm_name>
或登录虚拟机内部查看其 IP。规则解释:
PREROUTING
规则 (DNAT): 将目标为宿主机30001
端口的 TCP 流量的目的地址和端口修改为192.168.122.102:22
。FORWARD
规则: 允许这些被修改目的地址(现在是192.168.122.102:22
)的数据包通过宿主机的FORWARD
链。POSTROUTING
规则 (MASQUERADE):这最后一条规则
iptables -t nat -I POSTROUTING -p tcp -d 192.168.122.102 --dport 22 -j MASQUERADE
是比较特殊的。它表示当流量从宿主机发出,目标是192.168.122.102:22
时,进行源地址伪装(SNAT)。这通常用于虚拟机主动向外访问时,而非端口转发的返回流量。对于libvirt的默认
nat
网络(通常是virbr0
接口,IP段192.168.122.0/24
),通常已经有一条更通用的MASQUERADE
规则,例如:sudo iptables -t nat -A POSTROUTING -s 192.168.122.0/24 ! -d 192.168.122.0/24 -j MASQUERADE
这条规则确保从
192.168.122.0/24
网络出去的流量(目的地不是该网络本身)都会被伪装成宿主机的出口IP。在端口转发场景下,返回流量通常会自动匹配连接跟踪条目,并通过宿主机正确路由回源客户端,不需要针对特定转发目标再设置
MASQUERADE
。如果您的通用MASQUERADE
规则已存在(libvirt 通常会自动设置),则您提供的第三条规则可能是不必要的,甚至可能与通用规则冲突或产生意外行为。
持久化 IPTables 规则:这些
iptables
命令添加的规则在系统重启后会丢失。要使它们持久化,您需要使用类似iptables-persistent
(Debian/Ubuntu) 或netfilter-persistent
的工具:sudo apt-get install iptables-persistent # 添加规则后执行: sudo netfilter-persistent save # 或者: # sudo iptables-save > /etc/iptables/rules.v4
IP 转发启用:确保内核 IP 转发已启用:
# 检查 (0 表示禁用, 1 表示启用) cat /proc/sys/net/ipv4/ip_forward # 临时启用 sudo sysctl net.ipv4.ip_forward=1 # 永久启用 (取消注释或添加以下行到 /etc/sysctl.conf 或 /etc/sysctl.d/ 中的配置文件) # net.ipv4.ip_forward=1 # 然后 sudo sysctl -p
Libvirt 在创建 NAT 网络时通常会自动处理这个。
# 克隆一台虚拟机
virt-clone -o debian12-vm1-forTest -n debian12-k8s-node2 --auto-clone
# 让virsh console可以连接虚拟机
vim /etc/default/grub
GRUB_CMDLINE_LINUX="console=ttyS0"
update-grub
systemctl enable serial-getty@ttyS0 --now