菜单

Administrator
发布于 2024-03-24 / 28 阅读
0

KVM基础使用

好的,我已经将您提供的文本内容整理成了 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-okkvm-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

优化建议与说明

  • 包安装novncwebsockify 也可以合并到前面提到的综合 apt-get install 命令中。
  • qemu.conf 修改
    • vnc_listen = "0.0.0.0": 使 VNC 服务监听所有网络接口,允许从外部访问。请务必注意这带来的安全风险,并确保有防火墙规则保护。
    • vnc_keymap = "en-us": 设置 VNC 键盘映射。
    • vnc_sasl = 0vnc_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 包 (通常是 ovmfqemu-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:脚本前面并未显式创建名为 isovirsh 存储池。这些命令假设该存储池已存在。通常,ISO 文件可以直接通过 --cdrom /path/to/iso 使用,而不必一定在 virsh 存储池中管理。如果您确实创建了 iso 存储池(例如,类型为 dir,路径为 /data/libvirtd/iso),那么这些命令是相关的。
  • 销毁顺序
    1. virsh pool-destroy <pool_name>: 使存储池变为非活动状态。
    2. virsh pool-delete <pool_name>: (可选) 如果是基于目录的池,这可能会删除池的定义(但不删除目录内容)。对于其他类型的池,它会执行相应的删除操作。
    3. virsh pool-undefine <pool_name>: 从 libvirt 配置中彻底移除存储池的定义。必须先 destroy 并且可能 delete
  • virsh destroy <vm_name>: 强制关闭虚拟机(相当于拔电源)。如果想尝试正常关机,应先使用 virsh shutdown <vm_name>,等待一段时间后再用 destroy(如果 shutdown 未成功)。

十、IPTables 端口转发规则 (示例)

为虚拟机 192.168.122.10222 端口(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。

  • 规则解释

    1. PREROUTING 规则 (DNAT): 将目标为宿主机 30001 端口的 TCP 流量的目的地址和端口修改为 192.168.122.102:22
    2. FORWARD 规则: 允许这些被修改目的地址(现在是 192.168.122.102:22)的数据包通过宿主机的 FORWARD 链。
    3. 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