一次云服务器失联:不是 SSH 坏了,是 UEFI 忘了 Debian

记录一次 AI 客服系统部署后服务器疑似 OOM、强制重启、SSH 失联,最后定位到 UEFI BootOrder 中 Debian 启动项丢失的排障经历。

今天遇到了一次挺有意思,也挺吓人的云服务器事故。

前一段时间我在服务器上部署一个 AI 客服系统。这个系统本身比较吃资源,大模型、向量库、后台服务、数据库、反向代理,几个东西叠在一起之后,内存压力一下就上来了。后来服务器疑似因为 OOM 卡死,我在火山引擎控制台里强制重启了一次。

结果重启之后,SSH 怎么都连不上。

一开始我以为是普通的网络问题,或者 sshd 没起来。真正排完之后才发现,事情比“SSH 挂了”更底层一点:系统盘和 EFI 分区都还在,Debian 的引导文件也还在,但 UEFI 固件的启动顺序里没有 Debian 启动项了。机器启动时找不到默认系统,于是直接掉进了 UEFI Boot Manager。

事故经过

这次事故的时间线大概是这样:

时间发生了什么
之前在服务器上部署 AI 客服系统,资源占用变高,疑似触发 OOM
之后服务器无响应,于是在控制台强制重启
重启后SSH 一直连接不上
提交工单后技术支持询问 VNC 是否能登录
VNC 进入后看到的不是正常系统登录界面,而是 UEFI / OpenStack 相关启动界面
工程师排查后发现 UEFI BootOrder 没有 Debian 启动项
修复后手动进入 EFI 引导,并把 Debian 的 shimx64.efi 恢复为首选启动项,服务器恢复正常

最开始我在 VNC 里看到 OpenStack / UEFI 的界面时其实有点懵。

平时连服务器都是直接 SSH,最多也就是看一下控制台监控,很少真的通过 VNC 面对一台云主机的“屏幕”。云服务器一旦掉到这个层面,就很像你远程摸到了一台没有键盘的电脑:系统明明可能还在盘里,但它就是不知道该从哪里启动。

最终原因

火山引擎技术支持给出的结论是:

云主机 UEFI 启动项异常。系统盘及 EFI 分区本身正常,Debian 的引导文件仍存在,例如 /EFI/debian/shimx64.efi/EFI/debian/grubx64.efi 等,但 UEFI 固件的 BootOrder 中未包含 Debian 启动项,导致实例启动时无法自动加载系统,而是进入 UEFI Boot Manager。通过手动进入 EFI 引导并恢复启动项,将 Debian shimx64.efi 调整为首选启动项后,实例恢复正常启动。

换句话说,这不是磁盘被删了,也不是 Debian 系统文件没了,更不是单纯的 SSH 配置坏了。

真正的问题在启动链路:

1
2
3
4
5
6
7
云主机开机
  -> UEFI 固件读取 BootOrder
  -> 找不到 Debian 启动项
  -> 进入 UEFI Boot Manager
  -> 系统没有正常启动
  -> sshd 自然也不会起来
  -> SSH 连接失败

这里有个容易误判的点:我前面确实怀疑过 OOM,但 OOM 更像是这次事故的前因,或者说是让我去强制重启服务器的诱因。最终导致 SSH 连不上的直接原因,是 UEFI 启动项异常。

这两个事情不能简单画等号。

OOM 可能让系统卡死,也可能让服务被杀掉,还可能导致应用数据来不及落盘。但“UEFI BootOrder 里 Debian 启动项丢失”属于更底层的启动配置问题,不能只靠一句“内存爆了”解释完。真实的事故往往就是这样:你看到的是 A,动手处理了 B,最后坏在 C。

为什么 SSH 排不上用场

这次最有教育意义的一点是:当系统没有真正启动时,SSH 是没有意义的。

平时 SSH 连不上,我们很容易从这些方向想:

  • 安全组是不是没放行 22 端口;
  • 公网 IP 是不是变了;
  • 密钥是不是错了;
  • sshd 服务是不是挂了;
  • 防火墙是不是把自己锁外面了。

这些排查都没错,但它们默认有一个前提:操作系统已经启动,并且网络栈和服务管理器至少跑起来了。

而我这次的问题在这个前提之前。

机器连 Debian 都没进入,当然不会有 systemd,不会有网卡初始化,也不会有 sshd。这个时候继续纠结 SSH 报错,意义就不大了,必须去看云厂商控制台里的 VNC、串口日志、启动截图或者救援模式。

如果自己排查,我会先看什么

这次是技术支持帮我恢复了启动项。如果下次需要自己判断,我会按这个顺序看。

1. 先确认系统有没有真的启动

如果 SSH 失败,先不要急着改安全组,可以先看:

  • 云监控里 CPU、内存、磁盘 IO 有没有启动后的波动;
  • 控制台 VNC 里是不是登录界面;
  • 串口日志里有没有 Linux kernel、systemd、network 相关输出;
  • 是否直接进入了 BIOS、UEFI Boot Manager、PXE、grub rescue 之类的界面。

如果 VNC 里已经是 UEFI Boot Manager,那 SSH 这一层基本可以先放下。

2. 进入系统后检查启动项

恢复进入系统之后,可以用 efibootmgr 看 UEFI 启动项:

1
sudo efibootmgr -v

正常情况下,应该能看到类似 Debian 的启动项,并且 BootOrder 里包含它:

1
2
3
BootCurrent: 0003
BootOrder: 0003,0001,0000
Boot0003* debian HD(...) File(\EFI\debian\shimx64.efi)

还可以看 EFI 分区里的文件是否存在:

1
sudo ls -R /boot/efi/EFI/debian

如果 Debian 引导文件还在,但启动项没了,就可以考虑重新创建启动项。不过这一步要非常小心,因为磁盘名和 EFI 分区编号每台机器都可能不一样。

示例命令大概长这样:

1
sudo efibootmgr -c -d /dev/vda -p 1 -L "debian" -l '\EFI\debian\shimx64.efi'

这里的 /dev/vda-p 1 只是示例,真正执行前一定要用 lsblk -fblkid 或云厂商文档确认 EFI 分区是哪一个。设置错了,可能会让启动问题变得更麻烦。

3. 再回头查 OOM

系统恢复之后,再查疑似 OOM 的证据:

1
2
3
4
free -h
journalctl -k -b -1 | grep -i -E "out of memory|oom|killed process"
journalctl -p warning..alert -b -1
last -x | head

如果是 Docker 或者 Docker Compose 部署的 AI 服务,还应该看容器日志和退出原因:

1
2
3
docker ps -a
docker inspect <container> --format '{{.State.OOMKilled}}'
docker logs --tail=200 <container>

有了这些证据,才能判断到底是整个系统内存耗尽,还是某个容器被 cgroup 限制杀掉,或者只是应用自己崩了。

这次给我的提醒

这次恢复得还算顺利,但也提醒了我几件事。

第一,云服务器也要当成真实机器看待。

平时我们会觉得云主机就是一个 IP、一个 SSH、几个面板按钮。但它底层依然有启动固件、系统盘、EFI 分区、引导文件、启动顺序。出问题时,不一定都发生在 Linux 里面,有时候问题发生在 Linux 启动之前。

第二,强制重启不是没有代价。

服务器卡死时,强制重启确实是最直接的办法。但如果机器正在写盘、正在更新内核、正在改引导、正在调整系统包,就可能留下更奇怪的状态。下次遇到类似情况,我会先看控制台监控、尝试软重启、确认是否能通过 VNC 看到系统状态,再决定是否强制操作。

第三,快照真的要提前做。

技术支持在申请授权前也提醒了:排查前最好先对云盘做快照。这个提醒很重要。因为启动项问题本身可能不难修,但只要涉及系统盘、EFI、引导修复,就应该先有回滚点。

第四,AI 服务部署要给内存留余量。

AI 客服这类系统很容易不知不觉吃掉很多资源。模型服务、Node / Python 后端、数据库、向量检索、浏览器自动化、日志系统,每个看起来都不夸张,叠起来就很可观。

后面我会更倾向于:

  • 给机器加 swap,至少避免瞬间内存压力直接把系统打死;
  • 给 Docker 容器设置合理的内存上限;
  • 把数据库、向量库、模型服务分开观察;
  • 部署前用 htopdocker stats、云监控看一轮资源曲线;
  • 对关键服务加自动重启,但不要让它无限重启制造更高压力;
  • 在上线前先准备好快照和回滚方案。

可以沉淀成一张检查表

以后如果再遇到“云服务器强制重启后 SSH 连不上”,我会按这个检查表走:

1
2
3
4
5
6
7
1. 看云控制台实例状态:是否运行中,是否有异常事件
2. 看安全组和公网 IP:确认 SSH 入口没被改掉
3. 打开 VNC / 串口:确认是不是进入系统登录界面
4. 如果进入 UEFI / BIOS:优先检查启动项和 EFI 引导
5. 如果进入 grub rescue:检查 grub 配置、分区 UUID、内核文件
6. 如果系统启动但 SSH 不通:再查 sshd、防火墙、网络配置
7. 恢复后立刻补快照,查 OOM、磁盘、日志和应用资源占用

这张表的关键点只有一个:先判断问题发生在哪一层。

不要一上来就把所有 SSH 失败都当成网络问题。也不要看到 OOM,就默认后面的所有异常都是 OOM 直接造成的。排障最怕的是把相关性当成因果关系,然后一路查偏。

最后

这次事故最后的结论很朴素:

服务器不是没了,系统盘也没坏,只是 UEFI 启动顺序里没有 Debian 了。

但它带来的提醒一点也不小。对个人开发者来说,部署一个 AI 应用已经越来越容易,几个命令、一个 Docker Compose、一个反向代理,很快就能把东西跑起来。可是当它真正跑在一台云服务器上时,系统资源、启动链路、快照、救援入口、日志证据,这些基础设施层面的东西还是绕不开。

以后再部署吃资源的服务,我大概会先多做一步:别只想着“跑起来”,也要想想“挂了以后怎么救回来”。

这次算是被云服务器认真上了一课。

Powered by Hugo & Stack