香港服务器为虚拟化选型:CPU虚拟化指令、内存超配与本地 NVMe 的平衡
技术教程 2025-09-30 09:38 207

凌晨两点的香港荃湾机房,我得在 24 小时内给 120 台 VM 找到“新家”

凌晨两点,我到香港做这次迁移,是因为旧集群撑不住了:CPU 利用率常年 70% 以上,一旦高峰就抖;内存超配比例失控,偶发 swap 抖一下就全盘卡;存储更是“瓶颈中的瓶颈”。甲方给了我一个并不好完的 KPI:同机柜功耗不增加、成本持平或略降、VM 密度至少 +25%,同时保障 99 线延迟不劣化

我把两杯冻柠茶放在最上层理线架上,拎着贴好编号的 NVMe 托架,心里明白:这活儿的关键在 硬件选型的“组合拳”——CPU 虚拟化指令集(EPT/NPT)能不能把 VM-exit 压下去;内存能超配到什么度不炸;本地 NVMe 用什么形态、怎么做阵列

这篇文章,就是我把那 24 小时里做过的对比评测、踩过的坑、现场的决策逻辑,一五一十讲出来。数据都在表里,命令都在代码块里,你照着抄也能落地。

场景与目标

目标:在香港机房内,基于 KVM/Libvirt(CentOS 7),完成新一代虚拟化节点选型与落地:

  • VM 密度(2 vCPU/4 GiB 小型实例 + 8 vCPU/16 GiB 中型实例的混布)≥ 旧集群 +25%
  • 99 线延迟不劣化,CPU 抖动 ≤ 5%,存储 p99 写入延迟 ≤ 1.0 ms
  • 单节点软预算不超旧机型 ±10%,同机柜功耗不升

约束

  • 机柜功耗:每 1/3 机柜约 2.3 kW 上限
  • 网络:25 GbE 东西向,10 GbE 下兼容;跨境链路不作为主存储(只做备份/迁移)
  • 系统栈:CentOS 7.9(原因:对方既有运维体系)、KVM/libvirt、mdadm + XFS

候选硬件清单与配置

CPU/主机三套候选(实测样机)

方案 ID 处理器 插槽 总核/线程 内存 内存通道 关键指令/特性 备注
H1 Intel Xeon Silver 4314(Ice Lake) 2P 32C/64T 512 GiB(8×64) 8 ch/CPU VT-x、EPT、VT-d、AVX-512 AVX-512 对少量特定工作负载有优势
H2 Intel Xeon Gold 6248R(Cascade Lake) 2P 48C/96T 512 GiB(12×32) 6 ch/CPU VT-x、EPT、VT-d、AVX-512 核多、频率稳,传统强项
H3 AMD EPYC 7543P(Milan) 1P 32C/64T 512 GiB(8×64) 8 ch AMD-V、NPT(RVI)、SEV、AVX2 单路性价比高,L3 大、内存带宽优

说明:我们优先看 EPT(Intel)/NPT(AMD) 的表现;H3 为单路 P 系列,成本与功耗优势明显,适合香港机房这类功耗受限场景。

本地 NVMe 三种形态

方案 ID 盘型与数量 阵列 目的 关键点
S1 2× Intel P4510 2 TB(U.2, PCIe 3.1) RAID1(mdadm) 注重可靠性 带电保护(PLP),QPS 不高但稳
S2 4× Samsung PM9A3 1.92 TB(U.2, PCIe 4.0) RAID10(mdadm) 混合负载主力 吞吐与低延迟兼顾,扩展性好
S3 1× Micron 7450 PRO 3.84 TB(U.2, PCIe 4.0) 单盘 成本敏感/轻度 IO 单盘简单,注意维护窗口

软件栈与调优(CentOS 7)

基础安装

# 基础组件(Virtualization SIG)
yum install -y centos-release-qemu-ev
yum install -y qemu-kvm-ev libvirt virt-install tuned numactl \
               mdadm lvm2 nvme-cli fio sysstat perf

systemctl enable --now libvirtd
tuned-adm profile virtual-host

内核与 KVM 参数

  • BIOS 打开 IOMMU(Intel VT-d / AMD-Vi)、SR-IOV(如需)、NUMA 显示模式
  • 大页策略:混部场景THP=always,关键低延迟 VM 用预留 1G hugepages
  • KSM:中度超配时开启,控制扫描速率
# THP 与 KSM
echo always > /sys/kernel/mm/transparent_hugepage/enabled
systemctl enable --now ksmtuned

# 预留 1G 大页(重启后生效)
# /etc/default/grub 追加:
# GRUB_CMDLINE_LINUX="... default_hugepagesz=1G hugepagesz=1G hugepages=64"
grub2-mkconfig -o /boot/grub2/grub.cfg

NVMe 与阵列

# 关闭 APST 的过激省电(避免尾延迟抖动)
echo 0 > /sys/module/nvme_core/parameters/default_ps_max_latency_us

# mdadm:S2 RAID10
mdadm --create /dev/md/raid10 --level=10 --raid-devices=4 \
      /dev/nvme{0,1,2,3}n1 --chunk=512

mkfs.xfs -f /dev/md/raid10
mount -o noatime,nodiratime,discard /dev/md/raid10 /var/lib/libvirt/images

典型 VM XML 片段(libvirt)

 
<cpu mode='host-passthrough' check='none'>
  <feature policy='require' name='vmx'/>      <!-- Intel:EPT 自动随 vmx -->
  <!-- AMD 则换成 svm;NPT 随 svm -->
  <topology sockets='1' cores='4' threads='2'/>
</cpu>
<memoryBacking>
  <hugepages/>
</memoryBacking>
<driver name='qemu' queues='4' io='native' cache='none'/>
<iothreads>2</iothreads>
<disk type='file' device='disk'>
  <driver name='qemu' type='raw' io='native' cache='none' />
  <source file='/var/lib/libvirt/images/vm01.img'/>
  <target dev='vda' bus='virtio'/>
  <discard>unmap</discard>
</disk>

测试方法学

  • CPUsysbench cpu 单核/8 vCPU,perf statkvm:*、cpu-migrations
  • 内存stream 带宽、stress-ng --vm + KSM 扫描对比
  • 存储fio 4k/128k 随机&顺序,QD1/32;p99、p99.9 关注
  • 业务端到端pgbench(PostgreSQL)、wrk(Nginx 静态/小动态)
  • 密度:按 SLA(p99 CPU runqueue < 2.0、p99 写入 < 1 ms)堆 VM 到极限

关键命令(节选):

# sysbench
sysbench cpu --threads=1 --cpu-max-prime=20000 run
sysbench cpu --threads=8 --cpu-max-prime=20000 run

# perf(测 VM-exit 等)
perf stat -a -e kvm:* -e context-switches -e migrations -I 1000 -- sleep 60

# fio(4k 随机 & 128k 顺序)
fio --name=rand4k --filename=/mnt/testfile --direct=1 --rw=randread \
    --bs=4k --iodepth=32 --numjobs=4 --runtime=60 --group_reporting
fio --name=seq128k --filename=/mnt/testfile --direct=1 --rw=read \
    --bs=128k --iodepth=32 --numjobs=4 --runtime=60 --group_reporting

# pgbench
pgbench -i -s 50
pgbench -c 64 -j 16 -T 120

# wrk
wrk -t16 -c1024 -d120s http://VIP/

结果一:CPU 虚拟化指令(EPT/NPT)对性能与 VM-exit 的影响

关闭/开启二级页表对比(以 H3/EPYC 为例,NPT=on/off)

场景 NPT sysbench(8 线程,events/s) kvm_exits/s(perf) p95 CPU 延迟
A on 13,640 8.1k 2.3 ms
B off(kvm_amd npt=0 9,220(-32%) 39k(+381%) 3.7 ms

结论:在 KVM 下,开启 NPT/EPT 是必须项。大多数混合负载下,关闭二级页表会直接让 VM-exit 飙升、延迟恶化。Intel 的 H1/H2 结论一致。

主机三方案 CPU 汇总

指标 H1(4314×2) H2(6248R×2) H3(7543P×1)
单线程 sysbench(events/s) 1,480 1,350 1,400
8 线程 sysbench(events/s) 10,820 12,540 13,640
VM 密度极限(2 vCPU/4 GiB,小型实例) 52 台 78 台 84 台
功耗(节点满载近似,W) ~520 ~780 ~430

解读:单核极限 H1 略优(Ice Lake/AVX-512 带来长尾场景优势),多核与密度 H3 领先,功耗也低,适合功耗受限的香港机房。

结果二:内存超配的“安全区间”

测试设置

  • 基线:内存不超配(overcommit=1.0×),KSM off
  • 轻度超配:1.3×,KSM on(pages_to_scan=5000,sleep_millisecs=20),balloon 打底
  • 过度超配:1.6×,KSM on,允许 zswap(仅用于保护,swap 空间保底)
场景 超配倍数 KSM VM p95 CPU steal 主机 runqueue p95 存储 p99 写延迟
基线 1.0× off 0.7% 1.2 0.68 ms
轻度 1.3× on 2.8% 1.4 0.72 ms
过度 1.6× on 6.5% 2.1 1.35 ms(越线)

建议:这批节点上,内存超配的“安全区间”≈ 1.2~1.35×。超过 1.5× 基本走向不可控。
实践要点

  • KSM 但控制扫描速率,避免 CPU 被“吃干”
  • Balloon 只做“守门员”,不要当常态调度器
  • 关键 VM 用 1G hugepages,与其他 VM 隔离抖动

结果三:本地 NVMe 形态(S1/S2/S3)对延迟与吞吐的影响

fio 基准(主机空载,直写 RAW,iothreads=2)

指标 S1:P4510×2 RAID1 S2:PM9A3×4 RAID10 S3:7450×1 单盘
4k 随机读 QD1(IOPS / p99 μs) 120k / 80 230k / 55 150k / 70
4k 随机写 QD1(IOPS / p99 μs) 52k / 150 180k / 65 110k / 90
4k 随机读 QD32(IOPS / p99 μs) 750k / 420 1.6M / 380 900k / 410
128k 顺序读(GB/s) 3.2 11.5 6.5
128k 顺序写(GB/s) 2.8 7.8 3.5

解读S2(4 盘 RAID10)是混合负载的“甜点区”,低尾延迟与高带宽兼顾。S1 的可靠性稳,但小写入 IOPS 明显劣势;S3 单盘可做轻负载或成本敏感场景。

结果四:端到端业务压测(混布 VM,Nginx + PostgreSQL)

  • 拓扑:每节点 20 台小型(2 vCPU/4 GiB)+ 6 台中型(8 vCPU/16 GiB),磁盘 vda RAW,io=native,cache=none
  • 压测 120 分钟取稳态,统计 p99 指标
组合 wrk 吞吐(req/s) wrk p99(ms) pgbench TPS pgbench p99(ms)
H1 + S2 148,200 18.6 22,900 28.4
H2 + S2 158,500 17.9 25,400 26.1
H3 + S2 165,300 16.8 27,100