上一篇 下一篇 分享链接 返回 返回顶部

如何在香港服务器的 Windows Server 2022 上启用 Hyper-V Storage QoS,避免虚拟机磁盘 I/O 争用

发布人:Minchunlin 发布时间:2025-09-04 10:04 阅读量:743


凌晨两点半,深水埗机房的空调像列车一样轰鸣。监控大屏上某台 SQL VM 的磁盘时延突然飙到了 80~100ms,旁边几台 Web VM 的登录页开始转圈。我把咖啡搁在机柜底层的理线板上,RDP 到 Hyper-V 主机,一边抓 PerfMon,一边用 Get-StorageQosFlow 看实时流量。果不其然:一台新上的“批处理”VM 在做大块随机 IO,把同一条 CSV 上的其他 VHDX 全压到了地板。那晚我没有加盘、没有迁移存储,只是启用了 Storage QoS,给不同业务分了清晰的 IOPS 配额,10 分钟后,时延曲线像拉直的心电图一样稳了下来。下面,就是我在香港机房这一套从规划、落地到排错的完整过程与心得。

场景与基线

角色 数量 CPU / 内存 系统盘 数据盘/池 网络 备注
Hyper-V/S2D 节点(WS2022 Datacenter) 3 Xeon Silver 4314 ×2 / 256GB SATA SSD 480GB U.2 NVMe(PCIe4.0) 3.84TB ×4,S2D 聚合为 CSV 卷(Mirror+) 25GbE ×2(SMB 多路径) 超融合,CSV 均衡
业务 VM 40+ 28 vCPU / 432GB VHDX OS+Data 分盘 vSwitch(SR-IOV 关) 混合读写,多租户噪声邻居明显

为什么选 Storage QoS(要点)

按 VHD/VHDX 的 IOPS 上下限做“硬约束”,从根上解决噪声邻居;支持集中策略(Dedicated/Aggregated),可统一下发并监控流量。

两条常用路径:

  1. 单主机/小规模:直接在 VM 的 VHDX 上设 -MinimumIOPS/-MaximumIOPS;
  2. 中大型/集群:在存储侧创建策略,用 PolicyId 绑定到 VHDX,集中治理,并可配 最大带宽与IOPS 归一化。

小注:Storage QoS 作用于虚拟硬盘流(VHD/VHDX/VHD Set)。直通盘(Pass-through)或来宾里自己连的 iSCSI不在 Hyper-V 主机的 QoS 控制路径内(因此无法被限制);并且官方也不推荐直通盘用于可迁移/弹性场景。

上线前:用 DiskSpd 打一条“地平线”

要合理设 IOPS 上下限,先压测基线能力与业务侧需求。我用微软的 DiskSpd 生成读写负载做对照:

  • # 以 8KB 随机读(匹配 QoS 的默认归一化块 8KB)测 IOPS 上限
    diskspd.exe -c8G -d60 -r -b8K -t8 -o8 -Sh -w0 E:\io\rd8k.dat
  • # 以 8KB 随机写测写路径表现
    diskspd.exe -c8G -d60 -r -b8K -t8 -o8 -Sh -w100 E:\io\wr8k.dat
  • # 以 64KB 顺序读测吞吐(QoS 也可按带宽限流)
    diskspd.exe -c16G -d60 -b64K -t4 -o4 -Sh -w0 E:\io\seq64k.dat

这里用 8KB 是因为 Storage QoS 用“归一化 IOPS”(默认 8KB)计算,一个 ≤8KB 的 IO 记为 1 IOPS。你也可以在集群上改归一化尺寸(后文有命令)。

压测后按 VM 类型粗分三档(供参考,请按你的盘阵/业务再调):

等级 典型业务 最小 IOPS 最大 IOPS 最大带宽(可选)
Bronze 轻量 Web/批处理 50 500 10–20 MB/s
Silver 应用/接口 200 2000 50–100 MB/s
Gold 数据库/搜索 1000 8000 150–300 MB/s

治理思路:两种 QoS 模式选型

Dedicated(专用型):每个 VHDX 单独获得 Min/Max 配额。适合“一个策略管 N 台相同规格 VM”。

Aggregated(聚合型):多个 VHDX 共享同一配额池(上/下限)。适合“同一项目的多台开发/测试机共享上限”。

二者都支持最大带宽(-MaximumIOBandwidth),与 IOPS 上限并行生效,先到先限。

实战建议:生产库盘用 Dedicated;测试/CI 用 Aggregated。聚合策略不建议挂太多(官方建议 20 个以内)避免调度复杂。

路线 A:单主机/小规模,直接给 VHDX 设 IOPS

当你没有 SOFS/S2D 集中存储,或只想快速拦住“肇事者”时,这路子最快。

# 给单个 VHDX 设置 IOPS 上下限(单位为“归一化 IOPS”,默认 8KB)
Set-VMHardDiskDrive -VMName "JOB-ETL01" -ControllerType SCSI -ControllerNumber 0 -ControllerLocation 1 `
  -MinimumIOPS 200 -MaximumIOPS 1500

# 批量给前缀为 WEB- 的 VM 的所有数据盘统一上限
Get-VM -Name "WEB-*" | Get-VMHardDiskDrive | Where-Object {$_.Path -match "DATA"} |
  Set-VMHardDiskDrive -MaximumIOPS 800

这些参数(-MinimumIOPS/-MaximumIOPS)以及随后会用到的 -QoSPolicyID 都是 Set-VMHardDiskDrive 的内置能力,在 WS2022 可直接用。

路线 B:集群/中大型,用集中策略(强烈推荐)

前提:你的 VM VHDX 放在 CSV/SOFS(S2D/Scale-Out File Server)之上;Hyper-V/存储均为 Windows Server 2016+(我们是 WS2022)。

1)在存储集群(SOFS/S2D 其中一节点)创建策略

# Bronze:限制较紧,适合轻载
$bronze = New-StorageQosPolicy -Name Bronze -PolicyType Dedicated -MinimumIops 50 -MaximumIops 500 -MaximumIOBandwidth 20MB

# Silver:中等保障与上限
$silver = New-StorageQosPolicy -Name Silver -PolicyType Dedicated -MinimumIops 200 -MaximumIops 2000 -MaximumIOBandwidth 100MB

# Gold:高保障,配数据库/搜索
$gold = New-StorageQosPolicy -Name Gold -PolicyType Dedicated -MinimumIops 1000 -MaximumIops 8000 -MaximumIOBandwidth 300MB

# 一个聚合池:给测试环境 10 台共享上限
$devpool = New-StorageQosPolicy -Name DevPool -PolicyType Aggregated -MinimumIops 500 -MaximumIops 4000

MaximumIOBandwidth 与 IOPS 上限同时受控;IOPS 归一化默认 8KB,也可以在集群级别调整:
Get-StorageQosPolicyStore / Set-StorageQosPolicyStore -IOPSNormalizationSize 32KB。

2)在 Hyper-V 主机上给 VHDX 绑定策略

# 把 Silver 策略绑到应用服务器盘
$pol = (Get-StorageQosPolicy -Name Silver).PolicyId
Get-VM -Name "APP-*" | Get-VMHardDiskDrive | Where-Object {$_.Path -match "DATA"} |
  Set-VMHardDiskDrive -QoSPolicyID $pol

# 把 DevPool 绑到若干测试 VM 的系统盘 + 数据盘
$pool = (Get-StorageQosPolicy -Name DevPool).PolicyId
"DEV01","DEV02","DEV03","DEV04","DEV05" | %{
  Get-VM -Name $_ | Get-VMHardDiskDrive | Set-VMHardDiskDrive -QoSPolicyID $pool
}

创建策略(New-StorageQosPolicy)、绑定 PolicyId 到 VHDX(Set-VMHardDiskDrive -QoSPolicyID)以及 Dedicated/Aggregated 两类策略,均有官方说明与范例。

监控与验收(非常关键)

A. 用 Get-StorageQosFlow 看“谁在吃盘”

# 以 IOPS 降序罗列当前所有流,并显示 VHDX 文件名
Get-StorageQosFlow | Sort-Object StorageNodeIOPS -Descending |
  ft InitiatorName, StorageNodeIOPS, MinimumIOPS, MaximumIOPS, Status,
     @{Expression={$_.FilePath.Split('\')[-1]};Label="File"} -AutoSize

InitiatorName 是 VM 名;File 是具体 VHDX。

注意:这个命令展示的是滑动 5 分钟平均,策略生效在数秒内,但完全反映到该输出可能需要几分钟。

B. 用 Get-StorageQosVolume/PerfMon 双校验

卷级吞吐/时延看 Get-StorageQosVolume;

来宾内看 PhysicalDisk\Avg. Disk sec/Read/Write 是否回落到目标区间(如 4–8ms)。

C. 典型“前后对比”(我们真实现场)

指标 治理前(某晚高峰) 治理后(策略上线 10 分钟)
高峰时延(Web VM,读) 60–100ms 4–8ms
业务核心 VM 抖动 明显(接口超时) 基本消失
“批处理”VM 峰值 IOPS 12k+ 限幅至 4k(DevPool 共享池)

现场自动化脚本(落地即用)

1)按命名规则批量分配策略

# 规则:SQL* -> Gold,APP* -> Silver,WEB* -> Bronze
$map = @{
  "SQL"   = (Get-StorageQosPolicy -Name Gold).PolicyId
  "APP"   = (Get-StorageQosPolicy -Name Silver).PolicyId
  "WEB"   = (Get-StorageQosPolicy -Name Bronze).PolicyId
}

Get-VM | ForEach-Object {
  $prefix = ($_ .Name -split "-|_")[0].ToUpper()
  if($map.ContainsKey($prefix)){
    Get-VMHardDiskDrive -VMName $_.Name | Set-VMHardDiskDrive -QoSPolicyID $map[$prefix]
    Write-Host "Applied QoS to $($_.Name)"
  }
}

2)巡检:找出“不达标/无策略”的 VHDX

# 不达标(Min 未满足)/无策略/超限 的流
$flows = Get-StorageQosFlow
$bad   = $flows | Where-Object {$_.Status -ne 'Ok'}
$nop   = $flows | Where-Object {$_.PolicyId -eq $null}

$bad | ft InitiatorName, MinimumIops, MaximumIops, StorageNodeIops, Status, @{Label="VHDX";Expression={$_.FilePath.Split('\')[-1]}}
$nop | ft InitiatorName, @{Label="VHDX";Expression={$_.FilePath.Split('\')[-1]}}

常见坑与我的处理办法

把归一化 IOPS 当真实 IOPS

QoS 默认按 8KB 归一化。你用 DiskSpd 跑 4KB/64KB,看到的“归一化 IOPS”会与业务观感不完全一致。解决:压测尽量覆盖 8KB 随机场景;必要时调整归一化尺寸(影响全局,要慎重)。

策略一改就刷命令,结果“数值没变”

Get-StorageQosFlow 是5 分钟滑动,需要一点时间才体现在平均值上;实际限流已秒级生效。

在直通盘/iSCSI 客户端里“怎么限都不生效”

因为 QoS 控的是 VHDX 上的“流”,直通/来宾内 iSCSI不走那条路径。建议把数据放回 VHDX;直通只在少数硬件直连场景使用(也不利于迁移/备份)。

聚合策略一次挂太多 VM

聚合池建议≤20 个流,更易于公平调度与排错。大型环境分项目建多个聚合池。

CSV 所有权与热点

高峰时段检查 CSV Owner(Get-ClusterSharedVolume),避免所有热点卷都落在同一节点;必要时切换 Owner 做横向均衡。

备份与 RCT 干扰

备份窗口与 I/O 峰值重叠,会导致“看似限流失效但其实是备份抢 IO”。错峰或给备份 VM 单独建聚合上限池。

带宽与 IOPS 双限的优先级

同时配置时,先触达的那个限制生效(常见于 64KB 顺序读写易先触达带宽上限)。

运维手册式流程(可贴到 Runbook)

  • 压测基线:用 DiskSpd 跑 8KB/随机读写与 64KB/顺序吞吐,记录各卷上限。
  • 分级建策:按业务金/银/铜设置 Min/Max 与 MaximumIOBandwidth。
  • 批量绑定:Set-VMHardDiskDrive -QoSPolicyID 按命名规则或标签一次绑全。
  • 验证回归:Get-StorageQosFlow、PerfMon 内外双视角看 IOPS/时延回落;必要时微调策略。
  • 巡检与告警:对 Status != Ok 的流做每日巡检(可接入脚本/邮件)。
  • 变更纪律:高峰前 30 分钟不做策略大调整;聚合池不超过 20 流。

附:高级玩法与命令速查

# 1) 查看所有策略
Get-StorageQosPolicy

# 2) 去绑策略(恢复为“无 QoS”)
Get-VM -Name "WEB-*" | Get-VMHardDiskDrive | Set-VMHardDiskDrive -QoSPolicyID $null

# 3) 找到某 VM 的所有流与实时状态
Get-StorageQosFlow -InitiatorName "SQL-PRD01" |
  fl InitiatorName, PolicyId, MinimumIOPS, MaximumIOPS, StorageNodeIOPS, FilePath

# 4) 调整集群的 IOPS 归一化尺寸(默认 8KB,慎用)
Get-StorageQosPolicyStore
Set-StorageQosPolicyStore -IOPSNormalizationSize 32KB
Get-StorageQosPolicyStore

以上命令与参数在微软文档中均有定义与示例(New-StorageQosPolicy、Set-VMHardDiskDrive、Get-StorageQosFlow、Set-StorageQosPolicyStore)。

第二天早班交接,我把那张“飙升又回落”的时延图贴在运维群里,大家都松了口气。后来我们把策略固化到部署流水线里:新 VM 贴标签、自动分配 QoS、上线前跑一遍 DiskSpd“体检”。再也没有谁会在夜深人静时把整条 CSV 吃满。机房依旧冷,但屏幕上的线条很温柔。

如果你也在香港或其他节点做多租户/多业务的 Hyper-V,按上面的流程跑一遍,先“量体”,再“裁衣”,你会看到那条最难看的曲线先变平,再消失。

目录结构
全文