简介:《虚拟化实施遇到问题的解决方案》面向虚拟化项目实施人员、运维工程师及刚接触平台搭建的技术人员,聚焦VMware与Citrix两类虚拟化环境在落地过程中出现的故障与常见疑难,提供可参考的处理思路和解决记录。内容源于作者个人实施经历,兼顾问题现象、排查方向与应对方法,适合在部署、调试和日常维护阶段对照查阅,帮助读者减少重复试错。压缩包为zip格式,整体约15.45MB;上游未提供文件总数与类型明细,故不展开具体文件构成。该资源已有502人浏览学习,说明其对虚拟化实施场景具有一定参考价值。读者可从中获取VMware、Citrix虚拟化常见问题的解决经验,理解实施环节的排错路径,并据此整理自己的故障处理清单,提升现场问题定位与处置效率。
1. 虚拟化上线首周常见问题:三台宿主机上的四十个业务
「虚拟化」在方案书里只是架构图上的一个分层,落到实施现场却完全不是一回事。我见过一个模拟项目 X,四十多台业务机从物理机搬进虚拟化池,白天一切正常,晚上备份窗口一到,监控全红:虚拟机没宕、业务没挂,就是慢得没法用。跑得起来和跑得好,中间隔着一整套资源分配、指标和演练。这份资源讲的不是某个平台的安装向导,而是虚拟化实施过程中真正会卡住人的那批问题:超分怎么定、内存回收开不开、迁移为什么失败、快照为什么不回滚、慢到底慢在哪一层。适合正在做或即将做虚拟化改造的运维、实施和架构同学,也适合已经上线、但总觉得「有点慢又说不出哪慢」的团队。下面按我踩过的顺序,一条条拆。
2. 先把资源分配算清:vCPU 超分、内存回收与存储链路的三个定量问题
虚拟化实施里最容易被含糊带过的就是「资源够不够」。方案评审时写一句「CPU 超分比 1:3、内存不超分」,实施时没人核,上线后就开始互相指责。这三个数字必须在上线前落在纸面上:vCPU 分配总量与物理核的比例、内存回收机制开哪几个、存储后端能扛多少 IOPS。它们不是独立的三件事,CPU 超分定得太激进,虚拟机抢 CPU 时就绪时间上升,业务感知到的就是「卡顿」;内存不设预留,气球驱动一回收,客户机内部就开始换页;存储链路没压过,前面两项调得再漂亮,一个备份窗口照样打回原形。下面按这三个维度分别给出可落地的算法和验证命令。
2.1 vCPU 超分比:从 1:1 到 1:4 之间怎么算出应用比例
超分比的分母一定要用物理核数,不是逻辑 CPU 数。开了超线程的机器nproc返回的是线程数,拿线程数当分母算出来的比例天生偏乐观,实际每核要承担两倍的压力。常见做法是:交易类、数据库类业务 1:1 到 1:2;通用 Web、中间件 1:2 到 1:4;桌面虚拟化或测试环境可以到 1:6 甚至 1:8。但这些数字只是起点,真正的判据是 CPU 就绪时间(ready time / steal time)——虚拟机想跑但物理核被别人占着,排队等待的时间占比一旦长期超过 5%,业务侧就开始有可感知的抖动。
先把账面数字统计出来,用下面这段脚本在每台宿主机上跑一遍:
#!/bin/bash # 统计当前宿主机所有虚拟机的 vCPU 分配总量,用于计算真实超分比 total_vcpu=0 for dom in $(virsh list --name); do [ -z "$dom" ] && continue vcpu=$(virsh dominfo "$dom" | awk '/CPU\(s\)/ {print $2}') total_vcpu=$((total_vcpu + vcpu)) printf "%-30s %s\n" "$dom" "$vcpu" done # 物理核数 = 每路核数 × 路数,注意不含超线程 pcores=$(lscpu | awk -F: ' /Core\(s\) per socket/ {gsub(/ /,"",$2); c=$2} /Socket\(s\)/ {gsub(/ /,"",$2); s=$2} END {print c*s}') lcores=$(nproc) echo "----------------------------------------" echo "vCPU 分配总量: $total_vcpu" echo "物理核数: $pcores 逻辑 CPU 数: $lcores" awk -v v="$total_vcpu" -v p="$pcores" 'BEGIN{printf "按物理核超分比: %.2f:1\n", v/p}' awk -v v="$total_vcpu" -v p="$lcores" 'BEGIN{printf "按逻辑核超分比: %.2f:1\n", v/p}'逻辑说明:virsh dominfo输出里的CPU(s)字段就是这台虚拟机配置的 vCPU 数,遍历所有域累加得到分配总量;lscpu里Core(s) per socket乘Socket(s)得到物理核数,这个值才是分母。参数上唯一要改的是虚拟机名前缀过滤——生产环境里往往混着模板机和测试机,建议在循环里加一层case判断,只统计纳管业务。
拿到账面比例后,还要看实际使用率。这两件事经常背道而驰:比例 1:2 但实际平均利用率只有 8%,说明资源是浪费的;比例 1:1.5 但峰值利用率 90%,说明再搬一台机器进来就会翻车。下表是我在项目里用的对照参照,注意最后一列才是决定是否继续扩容的依据。
| 业务类型 | 建议超分比 | 峰值利用率参考 | 就绪时间告警线 |
|---|---|---|---|
| 数据库 / 交易核心 | 1:1 ~ 1:2 | 不高于 60% | 2% |
| 通用应用 / 中间件 | 1:2 ~ 1:4 | 不高于 75% | 5% |
| 文件、打印、测试环境 | 1:4 ~ 1:6 | 不高于 85% | 10% |
| 桌面 / 池化办公 | 1:6 ~ 1:8 | 不高于 85% | 10% |
注意:超分比是结果,不是目标。先按业务重要级别定就绪时间阈值,再倒推能超分到多少,而不是先定一个 1:4 的漂亮数字再往里塞机器。
2.2 内存回收:气球驱动、页合并与预留内存的取舍
内存这块最常见的误解是「虚拟机里free看着还有富余,宿主机就该够用」。实际上虚拟化层有三种机制在中间来回操作,每一种都有代价:
气球驱动(balloon)是宿主机向客户机「借」内存的通道,靠客户机内的驱动配合。它的前提是驱动装了、服务起来了,否则宿主机以为能回收,客户机一点没让出来,两边账对不上。同页合并(KSM)把多台虚拟机里内容相同的物理页合并成一份,对同模板克隆出来的机器效果明显,代价是持续扫描消耗 CPU,且与静态大页互斥。预留内存(reservation)是反方向操作,锁定一部分内存不给回收,适合数据库这类对内存延迟敏感的虚拟机。
| 机制 | 作用方向 | 主要代价 | 什么时候必须开 |
|---|---|---|---|
| 气球驱动 | 宿主机回收客户机空闲内存 | 客户机内部可能触发换页 | 超分比高于 1:1 且业务空闲内存多 |
| 同页合并 | 合并重复物理页 | 持续 CPU 扫描开销 | 大量同模板克隆的桌面/测试机 |
| 内存预留 | 锁定内存不被回收 | 降低整体可调度内存 | 数据库、缓存类核心业务 |
| 静态大页 | 减少 TLB miss | 需预分配,不能动态调整 | 大内存、低延迟业务 |
验证气球和页合并是否真的在生效,别只看管理平台的开关状态:
# 宿主机侧:页合并是否开启,已合并多少页(页数 × 4KB 约为节省内存) cat /sys/kernel/mm/ksm/run # 1 = 开启,0 = 关闭 grep -E 'pages_shared|pages_sharing|pages_unshared' /sys/kernel/mm/ksm/* # 虚拟机侧:查看内存上限、当前分配与实际使用(单位 KiB) virsh dominfo app01 | grep -E 'Max memory|Used memory' virsh dommemstat app01 # 关注 actual / available / unused / rss逻辑说明:dommemstat输出里的actual是当前真正分给这台虚拟机的内存,available是客户机报告的可回收量,两者差值接近零就说明气球已经压到头了,再压只能靠客户机自己换页。参数上要留意单位是 KiB,写监控脚本时别按字节算,否则阈值会差三个数量级。
我一般的做法是:核心业务一律加预留,预留量取近 30 天内存峰值的 1.1 倍;非核心业务开气球但不设强制下限,让它自然回收;页合并只在克隆密度高的池子里开,开了之后盯两天宿主机 CPU 的 sys 占比,涨超过 3 个百分点就关掉。
2.3 存储链路:本地盘、共享块存储与分布式存储的边界
存储是虚拟化实施里唯一一项「事后补不回来」的资源。虚机、网络、CPU 都能在线调,存储的 IOPS 和时延是物理决定的,容量买够了不等于性能够用。一条虚拟磁盘的 IO 路径是:客户机文件系统 → 虚拟磁盘格式(qcow2 / raw)→ 宿主机缓存策略 → 后端存储。每一层都能成为瓶颈,而绝大多数「虚拟化之后数据库变慢」的案例,问题都出在第二层和第三层。
先明确边界:本地 SSD 时延最低,但不支持在线迁移和跨主机高可用;共享块存储支持迁移,代价是多一层网络和控制器;分布式存储扩展性好,但随机小 IO 的时延通常是本地盘的 3 到 10 倍,写放大还会额外消耗带宽。把核心数据库放在分布式存储上,然后抱怨「虚拟化性能不行」,是最常见的误判。
虚拟磁盘创建时有两个参数值得在实施阶段就定死:预分配策略和簇大小。精简置备省空间,但首次写入时要分配块,表现为「新机器前几天特别慢」;元数据预分配能缓解这个问题,几乎不占额外空间。
# 创建 200G 虚拟磁盘,元数据预分配,簇大小 64K(适合随机 IO 为主的业务) qemu-img create -f qcow2 \ -o preallocation=metadata,cluster_size=64k \ /var/lib/libvirt/images/app01.qcow2 200G # 对后端存储做一次真实压测:4K 随机读,队列深度 32,4 并发,持续 60 秒 fio --name=randread --filename=/dev/mapper/vg_data-lv_vm --direct=1 \ --rw=randread --bs=4k --iodepth=32 --numjobs=4 \ --time_based --runtime=60 --group_reporting逻辑说明:preallocation=metadata只预分配元数据,创建快、后续写入不产生额外的元数据膨胀;cluster_size=64k适合随机小 IO,顺序大 IO 为主的业务(备份盘、日志盘)用默认 64K 或调大反而更省。fio这行里--direct=1绕过系统页缓存,测的才是真实后端;--iodepth=32模拟虚拟化层多个虚机并发的情况,队列深度设在 1 测出来的数字好看但没有参考价值。
压测结果对照下表判断能不能承接业务,达不到就不要靠调超分比去「优化」:
| 后端类型 | 4K 随机读时延(p99) | 适用场景 | 不建议承载 |
|---|---|---|---|
| 本地 NVMe | < 0.5 ms | 核心数据库、高 IO 中间件 | 需要在线迁移的业务 |
| 共享块存储(FC/iSCSI) | 1 ~ 3 ms | 通用业务、需要高可用的场景 | 极高 IOPS 的写入密集业务 |
| 分布式存储 | 3 ~ 10 ms | 容量优先、弹性扩展 | 低时延交易类 |
| NFS / 文件级共享 | 5 ms 以上 | 镜像库、备份、归档 | 数据库数据文件 |
3. 性能瓶颈定位:CPU 就绪时间、内存争抢与 IO 等待的排查路径
性能问题是虚拟化实施里最难交差的一类:业务方说慢,平台方看监控一切正常,最后往往以「再观察观察」收场。原因很简单——两边看的不是同一层指标。虚拟化环境有三层观测点:宿主机、虚拟机内部、业务应用自身。定不到层,后面所有调优都是猜测。这一章给一条固定的排查顺序:先在业务侧锁定时间点和现象类型,再去宿主机同一时间窗看资源竞争,最后进虚拟机内部看是不是客户机自己的问题。顺序不能反,反了就容易在错误的层上做无效优化。
3.1 三层指标对齐:把「慢」拆成可观测的量
业务侧的「慢」至少有三种形态,对应的根因完全不同:响应时间整体抬高(通常是 CPU 争抢或存储时延上升)、周期性卡顿(通常是内存回收或备份任务)、少量请求超时(通常是网络丢包或队列打满)。所以第一步不是登宿主机,而是问清楚:什么时间、持续多久、是所有请求还是部分请求、有没有伴随错误率上升。这四个问题的答案基本能把范围缩小一半。
拿到时间窗后,按下面的顺序取数:
# 第一层:宿主机整体 CPU,重点看 %steal 与 %sys mpstat -P ALL 1 30 # 第二层:按进程看,qemu-kvm 进程的 CPU 占用是否异常,以及是否频繁上下文切换 pidstat -u -w -p ALL 1 30 | grep -E 'qemu|UID' # 第三层:虚拟机内部看 stolen time 与运行队列(在客户机里执行) vmstat 1 30 # 关注 st 列与 r 列逻辑说明:mpstat里的%steal是虚拟 CPU 等待物理 CPU 的时间占比,这个值在宿主机上看不出来,必须在客户机内或者通过 hypervisor 的就绪时间指标获取;pidstat -w的cswch/s如果某台虚机的 qemu 进程远高于同级别机器,通常意味着客户机内部有自旋锁竞争或者 vCPU 数量配多了。参数上1 30表示每秒采样一次共 30 次,取数窗口要覆盖业务反馈的故障时段,事后补采没有意义。
对齐的关键是时间戳统一。我踩过的坑是宿主机用 UTC、业务侧日志用本地时间,差了 8 小时,对着「同一时间窗」查了半天什么也没查到。实施阶段就应该把宿主机、虚拟机、监控系统三处时区全部对齐,这一步花五分钟,能省掉后面几天。
3.2 CPU 就绪时间与亲和性:把抖动压下去
确认是 CPU 侧竞争之后,先分清两种情形。一种是总量不够——超分比过高或业务峰值叠加,表现为所有虚机的就绪时间一起上涨,这种只能扩容或者把业务迁走,调参数没用。另一种是分布不均——总量够,但某些 vCPU 老是落在被系统进程和其他虚机争抢的物理核上,表现为个别虚机抖动、其他正常,这种可以通过绑核和 NUMA 亲和解决。
绑核之前先确认 NUMA 拓扑,跨节点的内存访问延迟能高出 40% 以上,vCPU 绑在同一节点、内存也落在同一节点才有意义:
# 查看 NUMA 节点与各节点上的 CPU 编号 numactl --hardware # 查看虚拟机当前 vCPU 落在哪些物理 CPU 上 virsh vcpuinfo app01 # 把 4 个 vCPU 绑定到同一 NUMA 节点内的物理核 8-11 virsh vcpupin app01 0 8 virsh vcpupin app01 1 9 virsh vcpupin app01 2 10 virsh vcpupin app01 3 11 # 检查宿主机调频策略,节能模式会引入频率切换带来的抖动 cpupower frequency-info | grep -E 'current policy|governor'逻辑说明:vcpupin的第一个参数是虚拟机名,第二个是 vCPU 序号(从 0 开始),第三个是物理 CPU 编号,一个 vCPU 只能绑一个核才能做到严格隔离。参数上要避开 0 号核——很多系统中断和处理内核线程都在 0 号上,绑过去等于给自己找麻烦。governor建议设为 performance,代价是功耗上升,但在虚拟化宿主机上这个代价换来的稳定性是值得的。
严格绑核的副作用是牺牲了调度弹性:绑死的核在虚机空闲时不能被别人用,整体利用率会下降。所以只对核心业务做严格绑核,普通业务保持共享,用 CPU 份额(shares)做软性优先级就够了。
3.3 内存争抢与 swap:从现象到检查链
内存争抢的表现比 CPU 更不直观。典型现象是:宿主机内存使用率看着 90% 出头不算离谱,虚拟机里free也显示有缓存可回收,但业务就是间歇性卡顿几秒。这种「玄学卡顿」九成和内存回收有关——气球反复伸缩、客户机在 swap 里进进出出、页合并扫描占用 CPU,任何一个都会造成短时抖动。
证据链要按「宿主机是否在换页 → 哪台虚机在换 → 换页是否与卡顿时间吻合」三步走:
# 宿主机层面:pswpin/pswpout 持续增长说明物理内存确实不够,不是虚机自己的问题 grep -E 'pswpin|pswpout|pgmajfault' /proc/vmstat # 单台虚拟机:swap_in / swap_out 是否在增长(单位 KiB) virsh dommemstat app01 | grep -E 'swap_in|swap_out|major_fault' # 宿主机内存水位与可用量 grep -E 'MemAvailable|SwapTotal|SwapFree|Dirty' /proc/meminfo逻辑说明:/proc/vmstat里的计数是累计值,必须隔一段时间取两次做差才有意义,单次读数的绝对值没有参考价值。dommemstat的major_fault增长快,说明客户机在频繁地从磁盘换入内存页,这种现象在虚机上被放大了——因为它要经过两层页表。参数上建议把采样间隔设为 10 秒,连续采 5 分钟,与业务侧记录的卡顿时间点做叠加对比,两个曲线对得上才算定位成功。
处理方式分三档:轻度争抢就调整气球下限,别让它压到业务的工作集以下;中度争抢给核心业务加内存预留,把压力转移给非核心业务;重度争抢只能加内存或迁走业务,任何参数调优都救不了物理内存不足。
4. 网络不通、迁移失败、快照回滚不了:三类高频故障的复现与处置
这三类问题有个共同点:报错信息都很含糊。网络不通只告诉你「目标不可达」,迁移失败只说「操作超时」,快照回滚失败更干脆,直接给一个内部错误码。含糊的报错意味着必须靠分层验证去逼近根因,而不是靠搜索错误码。下面每一类都给一条固定的验证路径,按顺序走,走到哪一步断了就是哪一层的问题。
4.1 虚拟交换机与 VLAN:不通、丢包、环路三种表现
网络故障先分清楚是哪一种,因为处置方式完全不同。完全不通,通常是 VLAN 或者端口组配错;能通但丢包,通常是 MTU 不一致或者安全策略拦截;时通时断、广播风暴,通常是环路或者 MAC 地址冲突。分清之后再动手,比一上来就抓包高效得多。
最常见的配置错误是上游物理交换机的 Trunk 允许列表没放开对应的 VLAN ID,虚拟化平台这边端口组配得再对,包到物理口上也被丢掉。这类问题在宿主机上就能验证:给虚拟交换机配一个同 VLAN 的临时接口,看能不能拿到地址。
MTU 问题更隐蔽。VXLAN 封装会在外层多加 50 字节,如果物理口是 1500 而虚机也是 1500,大包全部被丢,表现为「小包通、大包不通,SSH 能连但传文件卡死」:
# 在虚拟机内部验证路径 MTU:1472 + 28 = 1500 ping -M do -s 1472 10.0.0.1 # VXLAN 场景下虚机侧建议 8950,对应物理口 9000 ping -M do -s 8950 10.0.0.1 # 宿主机侧确认物理口、网桥、vnet 接口的 MTU 是否一致 ip link show | grep -E 'mtu|vnet' bridge link show逻辑说明:-M do强制不分片,-s指定数据部分长度,加上 28 字节的 IP+ICMP 头正好是探测的 MTU 值。逐级递减探测(1472 → 1450 → 1400)能快速找到路径上的真实 MTU。参数上注意 ICMP 可能被防火墙拦,如果一直不通但业务正常,换tcpdump抓包看是否真有分片重组的痕迹。
注意:虚拟交换机上如果开了 MAC 防伪造、混杂模式限制等安全策略,集群心跳、负载均衡的 VRRP 报文都可能被拦掉,表现为「网络通但主备切换不成功」,这类问题查配置比抓包快。
4.2 在线迁移失败:五个检查点按顺序过
迁移失败的原因五花八门,但检查顺序是固定的,按这个顺序走,绝大多数问题三步之内能定位:
| 顺序 | 检查点 | 典型现象 | 处置 |
|---|---|---|---|
| 1 | 目标机资源预留 | 提示内存不足、CPU 不兼容 | 预留至少等于源机已用内存,关闭目标机超分挤占 |
| 2 | CPU 特性兼容 | 迁移到老旧机型直接失败 | 集群内统一 CPU 基线(主机掩码),屏蔽新指令集 |
| 3 | 迁移网络 | 进度卡在 10% 以下或超时 | 独立迁移网络,检查带宽与 MTU |
| 4 | 存储可见性 | 提示磁盘不可访问 | 共享存储路径、多路径、LUN 掩码一致性 |
| 5 | 直通设备 | 提示设备不支持迁移 | PCI 直通、vGPU、USB 映射的虚机只能关机迁移 |
第三点最容易被忽略。迁移是把内存页通过网络复制到目标机,同时跟踪脏页,如果迁移网络和业务网络共用一条千兆链路,热迁移一个大内存虚机基本没有成功的可能——脏页产生速度超过传输速度,永远追不上。给迁移单独划一个网络,并显式限制带宽,避免迁移把业务网络打满:
# 走独立迁移网络,带宽限制 800 MB/s,保持持久化配置 virsh migrate --live --verbose --persistent \ --migrateuri tcp://10.0.20.11 \ --bandwidth 800 \ app01 qemu+ssh://10.0.20.11/system逻辑说明:--migrateuri指定迁移数据走哪个地址,这是把迁移流量和业务流量分开的关键;--bandwidth单位是 MB/s,取值建议是迁移网络物理带宽的 70%,留出余量给心跳和监控;--persistent保证迁移完成后目标机上的配置落盘,否则重启就丢了。参数上还有一个容易漏的:大内存虚机建议先确认能否开启后拷贝(post-copy),但这会带来源机挂起后不可回滚的风险,生产环境我一般不主动开。
4.3 快照链与磁盘格式:回滚失败的真实原因
快照回滚失败几乎只有两个原因:链断了,或者格式根本不支持。qcow2 的快照是基于写时复制(COW)的链式结构,每打一次快照就多一层,读操作要逐层回溯,快照层数越多 IO 越慢;一旦某一层的 backing file 被移动、重命名或者被其他工具改过,整条链就失效,回滚时直接报错。
更隐蔽的是「有快照时做了扩容或迁移」。给带快照的磁盘扩容,老快照记录的还是原来的虚拟大小,回滚时尺寸对不上,直接失败。用备份工具直接读基础镜像做备份,拿到的是快照创建那一刻的旧数据,恢复出来的业务数据是错的——这个坑我在模拟项目 X 里遇到过,等到恢复演练才发现,代价是整个备份策略重做。
# 查看快照链的深度与每层实际占用 qemu-img info --backing-chain /var/lib/libvirt/images/app01.qcow2 # 列出快照,确认是否存在多余层级 virsh snapshot-list app01 # 把活动层合并回基础层并翻转,合并期间 IO 会短暂停顿,必须放维护窗口 virsh blockcommit app01 vda --active --pivot --verbose逻辑说明:--backing-chain会把整条链逐层打出来,如果某一层显示backing file: (null)但又不是最底层,说明链已经断了。blockcommit --active --pivot是把当前活动层的数据合并到底层并切换过去,合并过程中虚拟机保持运行但 IO 有停顿,务必放在维护窗口执行。参数vda是磁盘目标名,多磁盘虚机要逐块处理,一次性对整机操作容易触发超时。
实施阶段就应该定死一条规矩:快照只用于变更前的短期保护,存活时间不超过 72 小时,超过就合并掉;长期备份走独立备份链路,不依赖快照链。这条规矩能省掉后面 80% 的存储空间告警和回滚失败。
5. 避坑清单:五个现场常见问题,按现象、原因、处置拆开
前面四章讲的是方法,这一章讲记录。下面五条都是我在实施现场真实遇到过的,每一条都按「现象 → 原因 → 处置」写清楚,可以直接拿去当上线检查项用。分成两类:前三条是配置层的,当场能改;后两条是流程层的,改起来慢但影响更大。
5.1 配置层:三个当场能改但极易遗漏的坑
坑一:模板克隆后主机名、IP、MAC 三件套冲突。现象:克隆出来的几台机器网络时通时断,监控上丢包率忽高忽低,看日志有 IP 冲突告警。原因:模板机制作时没做通用化处理,克隆继承了同一份网络配置和机器标识,虚拟化层虽然会给新网卡分配新 MAC,但客户机内部还留着旧的静态配置。处置:模板首次启动必须走一遍初始化(cloud-init或系统自带的通用化工具),自动生成主机名和机器 ID,静态 IP 改由地址池分配或者 DHCP 保留;克隆完成后在虚拟化层核对一遍 MAC 唯一性。
坑二:磁盘缓存策略为了性能调到回写模式,宿主机断电丢数据。现象:日常跑分很好看,一次机房供电切换之后,几台虚机的数据库出现页损坏,恢复出来数据不一致。原因:缓存策略选了回写,数据先落在宿主机的内存缓存里,客户机以为写成功了,实际没落盘。处置:有掉电保护的阵列缓存可以继续用回写;没有保护的一律改成直写或者不缓存,代价是 IOPS 下降 20% 到 40%,这个代价必须让业务方在上线前知情。核心库所在的存储,我一般直接设成不缓存,性能靠后端 SSD 补。
坑三:时间同步配置成多源头,虚拟机时钟越走越偏。现象:日志时间戳错乱,集群节点之间心跳间歇性超时,排查时发现几台虚机的系统时间差了几十秒。原因:客户机同时配了宿主机同步和外部时间源,两边都在拉,加上虚机暂停恢复后时钟没校正。处置:虚拟机内部只向一个内部时间源同步,关掉与宿主机同步的选项;宿主机自身向同一时间源同步;对时间敏感的业务(证书校验、分布式锁)单独加时钟漂移监控,阈值设 500 毫秒。
5.2 流程层:两个不会立刻报错但会拖垮项目的习惯
坑四:只监控容量使用率,不监控精简置备的分配比。现象:存储显示还有 20% 空闲,某天突然所有虚机写入失败,平台告警「数据存储空间不足」。原因:精简置备的磁盘是按需分配的,账面分配的容量远大于物理容量,使用率指标看的是物理已用,看不到「已承诺但未分配」的缺口。处置:同时监控两个数——物理使用率和置备比(已分配容量 / 物理容量),置备比超过 1.5 就要预警;给数据存储设 80% 硬阈值,到线就禁止新建虚机,别等 95% 再处理,那个阶段连迁移都做不了。
坑五:变更前打快照,但从不演练回滚。现象:一次平台升级出问题,按预案回滚,发现快照回滚失败,业务停了四个小时。原因:快照打了几十个,链深得离谱,中间还有一次磁盘扩容,回滚路径早就不可用了。处置:变更前的快照数量控制在两层以内,变更完成后 24 小时内合并;每季度做一次回滚演练,随机挑一台非核心业务实打实回滚一次,验证从快照到业务启动的完整链路。演练这件事,做过一次和没做过,出事时的处置速度差一个数量级。
6. 验收前的压测与基线:把「感觉还行」换成一组数字
虚拟化项目最容易糊弄过去的环节就是验收。虚机都起来了、业务都能访问、监控都有曲线,就算交付了。等到三个月后业务量上来,才发现当初根本不知道这套环境的极限在哪。我现在的做法是:上线前必须跑完四项压测,出一张基线表,把「感觉还行」换成具体数字,后面所有扩容和调优都以这张表为依据。
6.1 四项必做的压测与通过标准
| 压测项 | 方法 | 通过标准 | 常见不通过原因 |
|---|---|---|---|
| CPU 混合负载 | 满载跑 30 分钟,混合计算型与 IO 型 | 就绪时间 < 5%,业务 RT 抬升 < 20% | 超分比过高、未做绑核 |
| 存储随机 IO | 4K 随机读写,队列深度 32,多虚机并发 | p99 时延 < 基线 1.5 倍 | 后端缓存不足、未预分配 |
| 东西向网络 | 跨宿主机虚机间打流,逐步加压 | 无丢包,带宽达链路 80% | MTU 不一致、上行收敛比不足 |
| 迁移演练 | 带业务负载热迁移,再迁回 | 业务中断 < 1 秒,迁移耗时可预期 | 迁移网络与业务网络共用 |
第四项最容易被跳过,但它是最值钱的一项。迁移能不能成功、要多久、业务有没有感知,只有真跑一次才知道。压测时要在业务侧同时记录响应时间,光看迁移任务成功不够——迁移成功但业务抖了 8 秒,对小额交易类系统来说已经算事故。
6.2 基线表与三个必须设置的告警
压测跑完,把结果固化成基线表,同步配进监控。三个告警是我认为必须有的:CPU 就绪时间、内存气球回收频率、存储 p99 时延。前两个反映资源竞争,第三个反映后端瓶颈,三个都正常的情况下,业务再慢基本就是应用自己的问题,可以把责任边界划清楚。
| 指标 | 采集位置 | 基线取值 | 告警线 |
|---|---|---|---|
| CPU 就绪时间 | 宿主机 / 客户机 stolen | 压测峰值的一半 | 超过 5% 持续 5 分钟 |
| 内存气球回收 | 宿主机 dommemstat | 压测期间回收次数 | 单机每小时 > 10 次 |
| 存储 p99 时延 | 后端存储 / 宿主机 | 压测 p99 值 | 超过基线 1.5 倍 |
| 网络丢包 | 虚拟交换机端口 | 0 | 任意非零持续 1 分钟 |
基线不是一次性的。业务扩容、平台升级、存储扩容之后都要重跑一遍,把新基线覆盖旧的。我见过太多环境,基线表还是两年前首版上线的数字,监控阈值一直没动,告警天天响,最后所有人都学会了忽略告警——这比没有监控更危险。
从那以后我每次交付虚拟化项目,都会在验收前强制走一遍迁移演练和快照回滚,两项都过才签字;基线表打印出来贴在机房,扩容前先对照看一眼。这两个习惯没有技术含量,但救过我三次。希望帮到你。
本文还有配套的精品资源,点击获取