1.4 镜像、快照与弹性伸缩:半夜宕机后的补救方案

写这一节的时候,窗外刚下完雨。上个月某个凌晨两点,我的社区服务器毫无征兆地挂了——监控告警狂响,SSH 连不上,页面 502。那一晚之后,我把快照、镜像和弹性伸缩这几件事从知道变成了做到。这一节就是那次事故的完整复盘,以及之后定下的备份规矩。

一、事故:凌晨两点的一声告警

先说结论式的经验:宕机不可怕,可怕的是你没有快速恢复的手段。

那天两点出头,云监控的离线告警把我吵醒。我爬起来试 SSH,连接超时;控制台看实例状态是运行中,但 CPU 监控曲线在一点五十左右突然拉到 100% 然后变成一条直线——服务器卡死了,不是进程崩了,是整个系统都不响应了。

我在控制台点了重启,等了五分钟,服务回来。日志里没留下有效线索,大概是某个突发流量把内存和 IO 都压垮了。机器活着,但故障时间已经过去四十分钟——对一个刚起步的社区来说,凌晨挂四十分钟影响不大,但如果是白天搞的活动高峰呢?我不敢想。

事后我把这次故障的处理过程也复盘了一遍:

阶段 耗时 本可以缩短的办法
发现故障 约 10 分钟 告警唤醒,无法更快
确认原因 约 15 分钟 监控曲线只看到 CPU 飙升,缺少内存明细
重启恢复 约 15 分钟 有快照可回滚就不靠重启赌运气
验证服务 约 5 分钟 加健康检查接口,自动化验证

真正让我难受的是中间那十五分钟:明知道机器卡死,却不知道是哪个进程的问题。从那天起我给监控加了内存、磁盘 IO 两类指标,又在应用里埋了健康检查接口。告警和监控的完整配置在第五篇,这里只说一句:出事时看得见现场,比事后猜原因重要一百倍。

二、快照:云硬盘时间点的副本

事后我做的第一件事是给系统盘和数据盘都拍快照。快照就是云硬盘在某个时间点的数据副本,详细的概念说明可以参考云服务器概述里的存储相关章节。它的价值在于:

  • 回滚:系统搞坏了、数据误删了,一键回滚到快照时刻。
  • 重建:用快照做镜像,新机器开出来环境一模一样。
  • 零中断:拍快照不用停机。

我给自己定的快照策略:

项目 系统盘 数据盘
快照频率 每周一次(改动少) 每天一次(数据多)
保留数量 最近 4 份 最近 7 份
触发方式 定时快照策略 定时快照策略
回滚前注意 先确认问题已定位 回滚会覆盖现有数据

提醒一点:快照回滚是覆盖操作,当前数据会没掉。不确定的时候,先手动拍一份当前状态的快照再回滚旧的。

还有两件小事值得知道:快照是按容量收费的,我两块盘加起来 150G,每月快照费用就几块钱,性价比很高;另外快照只覆盖云硬盘上的数据,内存里的数据是保不住的——所以应用层面自己该做的持久化(缓冲数据落地、定时保存)一件都不能少,快照不是应用层持久化的替代品。

定了策略不代表能用,我后来每个月会做一次故障演练:挑凌晨没什么用户的时候,关掉一台机器,逼自己用快照和镜像在十五分钟内把服务恢复到另一台机器上。前两次演练手忙脚乱,第三次就熟练了。真出事的时候能不能稳住,全靠平时练过。

三、自定义镜像:十分钟重建一套环境

快照救的是数据,自定义镜像救的是时间。

我第一次迁移服务器时,新机器开出来,环境重装一遍:Nginx、Python、1Panel、各种配置文件、系统调优参数,前前后后搞了两小时。第二个月我就学乖了:把调好的系统做成自定义镜像,以后开新实例直接用镜像启动,开机就是一套配好的环境,十分钟就能拉起一台新机器。

恢复手段 耗时 效果
手动重装环境 1~2 小时 容易漏配
自定义镜像开机 约 10 分钟 环境与原机一致
快照回滚 约 10 分钟 数据回到快照时刻

我的做法是每季度更新一次自定义镜像:系统大更新之后、装了新组件之后,都重新做一份。镜像做多了也占空间,保留最近两三份够用。

另外还有个小技巧:重要节点前手动拍一份快照。我每次升级大版本、改数据库结构之前,都先拍快照再动手。成本几乎为零,但把不可逆操作变成了可逆的——这套习惯在家里自建服务器时也适用,自建环境怎么做备份可以参考NAS 与家庭服务器实战。

顺带一提,服务器上的应用环境如果用面板管理,备份和迁移会简单不少。我用的是 1Panel,它有自动备份和快速迁移功能,面板相关的玩法见1Panel 运维面板实战,遇到迁移后服务起不来的问题,排查思路可以翻1Panel 常见问题。

四、弹性伸缩:让流量高峰自己过去

那次宕机的根源是突发流量。云服务器有个功能叫弹性伸缩,能根据负载自动加减实例:CPU 超过设定阈值就自动扩容,降下去再自动缩回来,配合负载均衡把流量分发到多台机器。

这个方案我最终没一上来就用,原因是:我的应用当时是有状态的(会话存在本地),多台实例之间没做好共享,贸然扩容会有登录态丢失的问题。正确的姿势是先把会话挪到外层(比如数据库或缓存),再开伸缩组。我的打算是等下一波活动流量来了再上,先把单机的容灾做好。

伸缩策略的参考配置:

指标 扩容阈值 缩容阈值 说明
CPU 利用率 > 70% 持续 5 分钟 < 30% 持续 10 分钟 最常用的指标
外网带宽 > 80% 持续 5 分钟 < 20% 持续 10 分钟 流量型场景
最小实例数 1 — 保证任何时候有机器兜底

几个配置上的提醒:冷却时间别忘了设,不然机器刚扩容指标还没稳定,系统反复增增减减;最大实例数要结合预算封顶,不然一次异常流量可能把你账单拉爆;缩容阈值要比扩容阈值低足够多,避免在临界点附近震荡。弹性伸缩救的是预期内的流量波动,如果是被恶意流量打了,伸缩只会帮攻击者占用更多资源,那种情况得靠防护策略,是另一个话题。

五、做一次故障演练

方案写在文档里和真的会做,是两回事。我第二个月搞了一次演练:挑一个周日凌晨,故意在控制台把实例关机,然后计时,看自己多久能把服务恢复。

结果很受刺激:第一次演练我花了五十分钟,中间因为没记住 1Panel 的后台端口又去翻文档。但收获很大——我发现恢复流程里真正卡时间的是那些平时不在意的细节:域名的 DNS 缓存、Nginx 的证书路径、数据库里 remembered 的连接串。后来我把恢复手册细化成了三页纸:第一页是联系人和服务清单,第二页是每个服务的恢复命令,第三页是验证步骤。真出事的时候按页翻,不用动脑子——凌晨两点的大脑,是不值得信任的。

演练次数 恢复耗时 卡在哪里
第 1 次 50 分钟 端口、证书路径都要现翻文档
第 2 次 25 分钟 手册不全,少了 DNS 切换步骤
第 3 次 12 分钟 只差开机和验证

如果没有快照和镜像,演练根本无从谈起——重装环境就不是几十分钟的事了。这也是我把这两件事看得比弹性伸缩还重的原因:伸缩是优化项,恢复能力是保命项。

六、现在的容灾方案

一套组合拳下来,我现在的基础设施长这样:

  • 云数据库 MySQL 主从自动切换,数据库层故障不怕(第二篇细讲)。
  • 每日快照 + 每季度镜像,系统和数据都能快速恢复。
  • 云监控盯着 CPU、内存、带宽,超阈值先告警再升级。
  • COS 里存着图片原文件,服务器挂了图片也不丢(第三篇细讲)。

这一套配下来,单点故障的风险降低了很多。半夜再被吵醒的概率小了,醒来了也知道下一步该点什么。云监控和告警会先于用户告诉我哪里不对(第五篇细讲),数据库主从切换替我兜住数据层的故障,快照和镜像兜住机器层面的故障。层层兜底,才是一个小项目能安心跑下去的底气。

上云这件事,最贵的成本不是服务器费用,是出了事没有预案。快照和镜像就是给自己留的后悔药,平时不起眼,出事时能救命——这是我花了一个凌晨两点换来的教训。

延伸阅读