现在越来越多的人开始写自己的博客,有自己的网站,或者在云服务器上部署了自己的应用。通常这些服务都能够稳定地运行,几个月一年都不会出错。然而有的时候,会由于网络波动,云服务器的底层硬件出现故障或者等等各种不可预见的问题而导致服务不可用。这个时候如果能够尽早地发现服务已下线,也就能够更快地从故障中恢复过来。

而我今早就遇到了这样的事情…

早上一起床,我就在手机上收到了 LetsMonitor.org 在 06:36 时发来的推送邮件说是 Connection error

Let's Monitor 监控提醒邮件

登入 Let's Monitor 控制面板也能够看到相关信息:

Let's Monitor 控制面板

起初我还不在意,毕竟我的服务器运行在亚马逊的 AWS 云服务上,自我前一次启动以后已经连续稳定运行了约 3 个月。

EC2 实例启动时间

然而随后不久的 09:08 分,我又收到了来自亚马逊的邮件:

[Retirement Notification] Amazon EC2 Instance scheduled for retirement.

We have important news about your account (AWS Account ID: xxxxxxxxxxxx). EC2 has detected degradation of the underlying hardware hosting your Amazon EC2 instance (instance-ID: i-xxxxxxxx) in the us-east-1 region. Due to this degradation, your instance could already be unreachable. After 2017-03-30 01:00 UTC your instance, which has an EBS volume as the root device, will be stopped.

亚马逊 EC2 硬件故障通知

此时,我意识到我的服务器应当是已经下线了,而来自 Let's Monitor 告警甚至还比亚马逊 EC2 的故障通知还早来了两个半小时。

通过访问我的网站,ping 服务器 IP,以及尝试 SSH 连接服务器,我确认了服务器此时已无法访问。

后来登入 AWS 控制台,发现系统状态检查以及实例状态检查也均已不能通过。

AWS 控制台状态检查报错

其中,状态检查失败的时间是在 10:33 分,比起亚马逊的邮件通知又晚了有一个半小时。

从以上 3 个时间点:

  1. 06:36 Let's Monitor 发出连接错误的告警;
  2. 09:08 亚马逊发出硬件故障的邮件通知;
  3. 10:33 AWS 控制台显示出系统及实例状态检查无法通过。

可以看出,拥有一份外部的可用性检测系统,还是能够给及时地了解网站的在线情况很大帮助的。 而亚马逊在硬件故障检测及通知上也还是有所准备的,能够比其内部的软件检查更快速地发现问题。

当然,没有任何硬件能够无差错地无限运行下去。底层硬件出现故障后,我需要做的也只是重新启动一个新的实例,挂载原先系统上的磁盘镜像,转移原先系统上的 IP 地址到新的实例即可。

不过在此次硬件故障中,原先系统上的一块磁盘始终无法从原系统上卸载,但是仍然可以为这块磁盘创建镜像,而且我原先也有设定定时自动创建镜像,因此,虽然无法使用原先的磁盘,我也只是需要通过磁盘镜像创建一块新的磁盘并挂载而已。

新系统上线!
新系统上线!

至此,虽然网站下线了一段时间,但是我也算是尽可能地在第一时间了解到了故障,并从备份中恢复了系统,未有丢失数据。算是在云上部署应用一次难得的体验。


更新:

回过头来查看服务器当时发送至 Papertrail 的日志,可以发现服务器上记载到的故障时间开始于 06:36:40,此时 kernel 打印出 [sched_delayed] sched: RT throttling activated,表明 CPU 资源占用已经出现问题,无法进行正常的进程调度。随后 2 秒 chronyd 报出 Forward time jump detected!,可以看出系统的时钟也出现了问题。再往后的第 8 秒,运行在服务器上的 gitlab-runner 报出无法与安装在同一机器上的 gitlab 通信的错误。再往后,系统应当是完全宕机,再没有日志发送出去。

关于 Papertrail,我曾写过使用 Papertrail 服务进行远程日志记录

Papertrail 日志

有日志记录的错误开始于 06:36:40,实际服务器出现异常应当会比日志记录再略微早一些,而此时 Let's Monitor 恰好及时地发现了服务器已无法正常连接,并发出了邮件。

(Let's Monitor 的检测间隔为 30 分钟。)

(Let's Monitor 的日志时区为太平洋时区,夏令时间为 UTC-7。)

Let's Monitor 日志