Margrop
Articles258
Tags428
Categories23
1password AC ACP AI AP API AppDaemon Aqara CI/CD Caddy Cloudflare Cookie 认证 Cron D1 Date Diagrams.net Docker Docker Compose Electerm Gateway GitHub Actions HA HADashboard Hexo HomeAssistant IP IPv4 Java LVM‑Thin Linux MacOS Markdown MiniMax Multi-Agent MySQL NAS Nginx Node.js OpenAI OpenClaw OpenResty PPPoE Portainer PostgreSQL ProcessOn Prometheus Proxmox VE SOCKS5 SSL Session Shell Subagent TTS TimeMachine UML Uptime Kuma VPN VPS Web Windows Workers activate ad adb adblock agent aligenie aliyun alpine annotation aop authy autofs backup baidupan bash bitwarden boot brew browser caddy2 cdn centos cert certbot charles chat chrome classloader client clone closures cloudflare cmd command commit container crontab ctyun ddsm demo dependency deploy developer devtools dll dns docker domain download draw drawio dsm dump dylib edge exception export fail2ban feign firewall-cmd flow frp frpc frps fuckgfw function gcc gfw git github golang gperftools gridea grub gvt-g hacs havcs heap hello hexo hibernate hidpi hoisting homeassistant hosts html htmlparser https idea image img img2kvm import index install intel io ios ip iptables iptv ipv6 iso java javascript jetbrains jni jnilib jpa js json jsonb jupter jupyterlab jvm k8s kernel key kid kms kodi koolproxy koolproxyr kvm lan lastpass launchctl learning lede letsencrypt linux live low-code lvm lxc m3u8 mac macos mariadb markdown maven md5 microcode mirror modem modules monitor mount mstsc mysql n2n n5105 nas network nfs node node-red nodejs nohup notepad++ npm nssm ntp oop openfeign openssl os otp ovz p14 packet capture pat pdf pem perf ping pip plugin png powerbutton print pro proxy pve pvekclean python qcow2 qemu qemu-guest-agent rar reboot reflog remote remote desktop renew repo resize retina root route router rule rules runtime safari sata scipy-notebook scoping scp server slmgr so socks source spk spring springboot springfox ssh ssl stash string supernode svg svn swagger sync synology systemctl systemd tap tap-windows tapwindows telecom template terminal tls token totp tvbox txt ubuntu udisk ui undertow uninstall unlocker upgrade url v2ray vhd vim vlmcsd vm vmdk web websocket wechat windows with worker wow xiaoya xml yum zip 中国电信 云电脑 交换机 人机协作 代理 体检 健康检查 光猫 公网IP 内存 内网IP 写作 升级 协作 博客 反向代理 启动 夏令时 多智能体 多节点 多节点管理 天猫精灵 天翼云 安全 安装 定时任务 容器 容器网络 导入 小米 常用软件 广告屏蔽 序列号 应用市场 异常 感悟 打工 打工人 技术 抓包 排查 描述文件 故障 故障排查 效率 效率工具 无服务器 日记 时区 显卡虚拟化 智能家居 智能音箱 服务管理 架构 梯子 模块 流程 流程图 浏览器 漫游 激活 火绒 玄学 生活 电信 画图 监控 直播源 端口扫描 管理 续期 网关 网络 网络风暴 群晖 脚本 腾讯 自动化 虚拟机 认证 证书 语雀 超时 路由 路由器 软件管家 软路由 运维 运维监控 通信机制 部署 配置 钉钉 镜像 镜像源 门窗传感器 问题排查 防火墙 阿里云 阿里源 集客

Hitokoto

Archive

记一次虚拟机内部网络卡死的完整排查:连续第五次复发的根因分析

记一次虚拟机内部网络卡死的完整排查:连续第五次复发的根因分析

前言

虚拟机内部网络突然完全不可访问,ping不通,SSH连不上,但从宿主机可以正常控制。这种”虚拟机内部网络卡死”的故障,排查起来往往让人摸不着头脑——外部管理通道正常,但虚拟机内部已经完全失联。

本文将详细记录一次完整的排查过程,从故障现象到临时解决方案,再到根因分析的思路,希望能给遇到类似问题的同学一些参考。

问题背景

故障概况

  • 故障时间:2026-04-12 凌晨00:12
  • 故障次数:这是该虚拟机连续第五次出现相同症状的故障
  • 故障现象:虚拟机内部网络完全不可访问
  • 临时解决方案:在宿主机上执行强制重启(qm stop/start)
  • 恢复时间:约5分钟

故障时间线

日期 故障描述 处理方式
04-06 首次出现内部网络卡死 宿主机强制重启
04-09 第二次出现(连续两次) 宿主机强制重启
04-11 第三次出现 宿主机强制重启
04-12 第四次出现 宿主机强制重启

环境信息

  • 虚拟机:某VM(运行在某PVE服务器上)
  • 宿主机:某PVE服务器(PVE245)
  • 虚拟化平台:Proxmox VE
  • 宿主机系统:Linux
  • 虚拟机系统:Ubuntu/Linux

问题现象详解

故障时的具体症状

当故障发生时,从外部监控会看到以下现象:

  1. ping测试:丢包率100%,完全不通
  2. SSH连接:超时或拒绝连接
  3. 监控面板:显示该虚拟机状态异常
  4. 宿主机管理界面:虚拟机进程仍在运行,但网络无响应

从宿主机观察到的状态

登录宿主机后,可以观察到:

1
2
3
4
# 查看虚拟机状态
qm list

# 应该看到虚拟机进程还在,但状态异常
1
2
# 查看虚拟机的网络接口
tapCtx show
1
2
# 查看宿主机上的虚拟网卡状态
ip link show

从宿主机角度,虚拟机的网络设备可能显示为”UP”状态,但实际上虚拟机内部已经完全无法通信。

排查过程

第一步:确认故障范围

首先确认是”虚拟机内部网络卡死”还是”宿主机整体网络问题”:

1
2
3
4
# 从另一台正常机器ping宿主机
ping <宿主机IP>

# 如果宿主机正常,说明问题范围在虚拟机内部

排查结果:宿主机网络正常,其他虚拟机也正常,问题范围锁定在单台虚拟机内部。

第二步:检查虚拟机进程状态

登录宿主机,检查虚拟机的运行状态:

1
2
3
4
5
6
7
8
# 查看QEMU进程状态
ps aux | grep qemu | grep <vmid>

# 查看虚拟机的配置文件
qm config <vmid>

# 查看虚拟机的控制台日志
qm log <vmid>

通常会看到虚拟机进程仍在运行,这说明不是”进程崩溃”的问题。

第三步:尝试从宿主机重置网络

有些情况下,可以通过宿主机工具重置虚拟机的网络,而不需要完全重启:

1
2
3
4
5
# 关闭虚拟机网络接口(示例)
ip link set tap<id> down
ip link set tap<id> up

# 或者在PVE web界面中重置网络

但这种方法通常对”内部网络卡死”效果有限,因为问题往往出在虚拟机内部的Linux网络栈。

第四步:强制重启——最直接的临时解决方案

当以上方法都无效时,最直接的方式是在宿主机上执行强制重启:

1
2
3
4
5
6
7
8
# 关闭虚拟机
qm stop <vmid>

# 等待几秒
sleep 5

# 启动虚拟机
qm start <vmid>
1
2
# 或者使用组合命令
qm shutdown <vmid> && qm start <vmid>

注意qm stop 是强制关机,相当于断电。如果虚拟机正在执行写操作,可能导致数据丢失。对于关键业务,应先尝试 qm shutdown(优雅关机),等待超时后再 qm stop

第五步:检查重启后的系统日志

重启成功后,登录虚拟机检查系统日志,寻找故障原因:

1
2
3
4
5
6
7
8
9
10
11
12
# 查看网络相关的系统日志
journalctl -u networking --since "1 hour ago"
# 或者
tail -n 100 /var/log/syslog | grep -i network

# 查看内核日志中与网络相关的错误
dmesg | grep -i network
dmesg | grep -i eth0
dmesg | grep -i virtio

# 查看NetworkManager日志(如果使用NM)
journalctl -u NetworkManager --since "1 hour ago"

第六步:检查网络配置

确认虚拟机的网络配置是否正确:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看网络接口配置
cat /etc/network/interfaces

# 查看NetworkManager配置(如果使用NM)
nmcli device show

# 查看当前网络接口状态
ip addr show
ip link show

# 查看路由表
ip route show

# 测试DNS解析
nslookup example.com

第七步:检查虚拟机资源使用情况

有时候网络卡死是由于资源耗尽导致的:

1
2
3
4
5
6
7
8
9
10
# 查看CPU和内存使用
top
free -h

# 查看磁盘IO
iostat -x 1 5

# 查看网络接口统计
ip -s link show
cat /proc/net/dev

第八步:检查宿主机层面的问题

既然虚拟机运行在宿主机上,也要检查宿主机是否有问题:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 查看宿主机资源
top
free -h
df -h

# 查看宿主机网络桥接状态
bridge link show
brctl show

# 查看KVM虚拟机网络
ls -la /etc/pve/qemu/

# 查看宿主机日志
journalctl --since "1 hour ago" | grep -i qemu
journalctl --since "1 hour ago" | grep -i kvm

根因分析

可能的原因推测

根据已知的故障模式(连续第五次,均为内部网络卡死),推测可能的原因包括:

可能性一:宿主机网络驱动或虚拟化层问题

分析:每次故障都表现为”内部网络完全不可访问”,但从宿主机可以正常控制虚拟机。这种模式暗示问题可能在虚拟化平台层面。

支持证据

  • 故障频率高(一个月内五次)
  • 每次重启都能解决问题
  • 其他虚拟机未受影响

建议排查

1
2
3
4
5
6
7
8
9
10
# 检查宿主机内核版本
uname -r

# 检查QEMU/KVM版本
qemu-img --version
kvm --version

# 检查宿主机网络桥接配置
cat /etc/network/interfaces
cat /etc/pve/qemu/<vmid>.conf | grep net

可能性二:虚拟机内部网络栈问题

分析:Linux网络栈在某些情况下可能进入异常状态,例如:

  • iptables规则冲突导致数据包无法路由
  • 网络接口驱动卡死
  • 内核网络子系统Bug

支持证据

  • 虚拟机内部完全无法通信
  • 宿主机上虚拟网卡显示正常

建议排查

1
2
3
4
5
6
7
8
9
10
11
12
13
# 检查内核网络参数
sysctl -a | grep net.ipv4
sysctl -a | grep net.core

# 检查网络接口驱动
ethtool -i eth0

# 检查网络接口统计是否有错误
ip -s link show eth0
cat /proc/net/dev

# 检查是否有大量丢包或错误
netstat -i

可能性三:虚拟机配置问题

分析:虚拟机的网络配置可能存在问题,例如:

  • VirtIO驱动配置不当
  • MAC地址冲突
  • 网络队列长度设置不合理

建议排查

1
2
3
4
5
# 检查虚拟机配置文件中的网络部分
qm config <vmid> | grep -i net

# 检查VirtIO配置
# 确保使用了正确的驱动模型

可能性四:流量异常或攻击

分析:如果虚拟机遭受网络攻击或流量异常,可能导致网络栈过载:

建议排查

1
2
3
4
5
6
7
8
9
# 查看网络连接数
ss -s
netstat -an | wc -l

# 查看当前网络连接
ss -tan state established | head -20

# 查看是否有异常大量连接
netstat -an | awk '{print $5}' | cut -d: -f1 | sort | uniq -c | sort -rn | head -10

临时解决方案

方案一:自动重启脚本

创建一个监控脚本,自动检测故障并重启:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!/bin/bash
# auto-restart-vm.sh

VMID="<vmid>"
MONITOR_IP="8.8.8.8" # 监控用的目标IP
LOG_FILE="/var/log/vm-monitor.log"

# 检测网络是否正常
if ! ping -c 3 -W 2 $MONITOR_IP > /dev/null 2>&1; then
echo "[$(date)] Network DOWN, attempting restart of VM $VMID" >> $LOG_FILE

# 执行重启
qm stop $VMID
sleep 5
qm start $VMID

echo "[$(date)] VM $VMID restarted" >> $LOG_FILE
else
echo "[$(date)] Network OK" >> $LOG_FILE
fi

添加到cron定时任务(每5分钟检查一次):

1
2
3
crontab -e
# 添加以下行
*/5 * * * * /path/to/auto-restart-vm.sh

方案二:使用watchdog自动恢复

配置Linux watchdog,在网络故障时自动重启:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# 安装watchdog
apt install watchdog

# 配置watchdog检测网络
cat >> /etc/watchdog.conf << EOF
# Network interface to monitor
interface = eth0

# Test remote host (ping this)
ping = 8.8.8.8

# Failure threshold
ping-count = 3

# Restart interval
interval = 10
EOF

# 启动watchdog
systemctl enable watchdog
systemctl start watchdog

方案三:配置虚拟机高可用(HA)

如果PVE支持高可用,可以配置虚拟机HA:

1
2
# 在PVE集群中启用HA
pvesr add <vmid> --restart 1 --state ignored

长期解决方案

方案一:升级虚拟化平台

当前虚拟化平台可能存在已知的Bug,升级到最新版本可能解决问题:

1
2
3
4
5
# 检查当前版本
pveversion -v

# 升级PVE
apt update && apt upgrade -y

方案二:调整虚拟机网络配置

尝试调整虚拟机的网络类型或参数:

1
2
3
4
5
# 编辑虚拟机配置,尝试使用不同的网络模型
# e.g., 将 virtio 改为 e1000 或相反
qm set <vmid> -net0 virtio,bridge=vmbr0
# 或
qm set <vmid> -net0 e1000,bridge=vmbr0

方案三:添加监控告警

配置更完善的网络监控,在故障发生前及时发现:

1
2
3
4
5
6
# 使用 Prometheus Node Exporter 监控网络指标
# 关键指标:
# - node_network_receive_bytes_total
# - node_network_transmit_bytes_total
# - node_network_receive_errs_total
# - node_network_receive_drop_total

方案四:迁移虚拟机

如果当前宿主机持续出现问题,考虑将虚拟机迁移到其他健康宿主机:

1
2
3
4
5
# 在线迁移(需要共享存储)
qm migrate <vmid> <target-node> --online

# 离线迁移
qm migrate <vmid> <target-node>

常见问题解答

Q1:虚拟机内部网络不通,但宿主机管理正常,是什么问题?

A:这种情况通常是虚拟机内部的问题,常见原因包括:

  • 虚拟机内部网络栈故障
  • 虚拟机网络驱动问题
  • 虚拟机配置错误
  • 虚拟机资源耗尽导致网络服务无响应

Q2:重启后故障消失,但过几天又复发,如何彻底解决?

A:连续复发的故障通常意味着存在系统性问题:

  1. 检查是否有已知Bug
  2. 升级虚拟化平台和虚拟机内核
  3. 检查虚拟机配置是否正确
  4. 考虑更换虚拟化底层或迁移到其他宿主机

Q3:能否在故障时自动恢复而不需要人工干预?

A:可以。使用watchdog或监控脚本可以实现自动恢复。但要注意:自动重启可能导致正在执行的任务中断或数据丢失。建议先做好任务协调。

Q4:宿主机正常,但某台虚拟机持续出现问题,是什么原因?

A:可能的原因:

  • 该虚拟机配置有特殊问题
  • 该虚拟机负载特殊,容易触发Bug
  • 该虚拟机与其他虚拟机存在冲突(如MAC地址冲突)

Q5:如何在故障时快速判断是虚拟机问题还是宿主机问题?

A:从另一台正常机器分别测试:

  1. ping宿主机 → 确认宿主机网络
  2. ping其他虚拟机 → 确认虚拟化网络
  3. 如果宿主机和其他虚拟机正常,仅目标虚拟机异常 → 虚拟机内部问题

经验总结

排查技巧

  1. 分层排查:先确认故障范围,从网络到主机到虚拟机,逐层缩小范围
  2. 对比分析:对比故障机与正常机的配置差异
  3. 日志为王:系统日志往往包含关键线索
  4. 复现困难:对于偶发故障,做好日志记录和监控

预防措施

  1. 定期巡检:不要等故障发生才检查
  2. 资源预留:确保虚拟机有足够的资源余量
  3. 配置审计:定期检查虚拟机配置是否合理
  4. 高可用:关键业务配置HA,避免单点故障

运维建议

  1. 文档化:将故障排查过程记录下来,方便后续参考
  2. 自动化:将重复性的检查和修复工作自动化
  3. 根因分析:不要满足于”临时解决”,尽量找到根本原因
  4. 知识积累:遇到新问题多查资料,多和同行交流

延伸阅读

结语

这次虚拟机内部网络卡死的故障,虽然最终通过”重启大法”临时解决了,但连续第五次复发表明存在系统性问题。要彻底解决,需要做更深入的根因分析,包括升级虚拟化平台、调整虚拟机配置、添加更完善的监控等。

希望这篇文章能帮到遇到类似问题的同学。如果有更好的排查思路或解决方案,欢迎在评论区交流!


作者:小六,一个在上海努力搬砖的程序员

Author:Margrop
Link:http://blog.margrop.com/post/2026-04-12-vm-internal-network-troubleshooting/
版权声明:本文采用 CC BY-NC-SA 3.0 CN 协议进行许可