设服务启动后状态为 ,员工 A 执行了若干操作动作后状态为 ,对外正常提供服务。
某时刻,人员 B 重启服务,状态重置为 ,因为 B 不知道 A 执行的操作,甚至 A 已离职或早已忘记曾做过哪些操作,导致服务异常。
解决方案:
❌ 人员 A 的操作动作记录到 checklist 上
✅ 服务器默认状态为 ,通过设置启动项等方式使得服务是自配置的、自封闭的,也是易于迁移的。
前言
2025年6月11日,公司某支撑系统经历了一起较大系统故障,因为某模块的一个 Nginx 服务(虚拟机)无法正常响应,导致1/3的请求流量报超时错误。从终端用户收到反馈,系统不可用。
这次故障从早上6时59分开始,8时30分恢复,共持续91分钟。
好在该系统每天9:00前用户访问量很小,没有造成较大的负面影响。
故障直接原因
服务负载均衡采用 keepalived + LVS + DR 方案。
故障产生的直接原因是: Nginx 服务虚拟机迁移后,进行了重启动作,导致网络配置(具体地:lo 回环地址静态路由)失效,与软负载 LVS 网络断连。
PS:该 Nginx 服务虚拟机已经800多天未重启。
LVS(负载均衡) + Keepalived(高可用)参考文章:
- Keepalived(高可用)和LVS(负载均衡)试用,zhuanlan.zhihu.com/p/690388453
- LVS+Keepalived 实现高可用负载均衡,www.cnblogs.com/Sinte-Beuve…
故障分析
LVS 的 DR 模式
Nginx 服务所在虚拟机进行了重启操作,通过指令添加的回环地址 lo 未加载(丢失),导致无法正常处理请求包(及检查目标 IP 不是自身,丢弃包)。
DR 模式下,简述请求转发过程:
- 客户端发送数据包请求到 LVS 的 VIP;
- LVS 将数据包的目标 MAC 地址更替为 RS(Real Server,真实服务器)的 Mac 地址,目标 IP 不变。
- RS 接收到数据包后,发现目标 IP 是自己的 VIP,正常处理请求。
- RS 直接将响应数据包返回给客户端(源 IP 为 VIP,目标 IP 为客户端 IP),不经过 LVS。
如果没有在 RS 中配置 VIP,那么将不会认为数据包是发给自己的,直接丢弃而不进行服务处理。
PS:计算机网络基础知识,数据链路层(Mac 层,同一广播域)的数据转发的过程。
后续改进计划
对故障进行回溯分析后,进行了较为全面的故障反思,包括测试不充分、监控缺失等。
其中最重要的一项是,形成 LVS + keepalived 的配置标准规范,加入代维人员检查项checklist,甚至修改路由模式。
我的思考
1. 在技术上,根本原因是代维人员缺乏对 LVS + keepalived + DR 负载均衡方案的认识?
我的观点:责任不是代维人员的,而是方案专家的。
联想和类比 Kubernetes(K8s)中有状态服务(Stateful Services)和无状态服务(Stateless Services)的概念,Nginx 服务是“无状态”的,我认为应由方案专家来考虑服务的可移植性问题,不应该出现重启服务后配置丢失的问题。
PS:Nginx 是无状态的,这里的网络配置项状态与 K8s 中服务状态不等价。
Nginx 及其所在虚拟机应该被制作为可重启的、自配置的,而不应该在启动后手动添加配置或检查网络配置等。
- 将配置写入到脚本中,并配置开机自启动。
- 将配置写入到 Dockefile 中
- 服务发现与自动注册机制
试想,本次故障后在检查清单上增加了检查网络配置一项,那么其他配置写入需求,是否地位等价,也应该加入一条检查项。只要重启时,遗漏或错误地配置了任何一项,那么将会导致系统故障,这显然是不合理的。
在 Linux 的 shell 中手动执行以下命令,导入 aliyun OSS 访问的 KEY_ID 和 KEY_SECRET。
export OSS_ACCESS_KEY_ID=YOUR_ACCESS_KEY_ID_xxxx
export OSS_ACCESS_KEY_SECRET=YOUR_ACCESS_KEY_SECRET_xxxx
上述配置是一次性的,一旦服务器重启,则上述2个变量将会丢失。
正确的做法是:
echo "export OSS_ACCESS_KEY_ID='YOUR_ACCESS_KEY_ID'" >> ~/.bashrc
echo "export OSS_ACCESS_KEY_SECRET='YOUR_ACCESS_KEY_SECRET'" >> ~/.bashrc
将变量写入服务自启动配置中,这样可以保证服务重启后,仍然“状态保持”。
2. 基于 Nginx 访问日志作故障预警。
在系统架构中,Nginx 服务虚拟机有3台,其他2台正常接收访问请求。通过 Nginx 的访问日志可以实现故障预警,故障发生的 Nginx 访问日志中,只有 curl 命令健康探测的日志,而没有普通用户请求的访问日志。
直观地,三台 Nginx 服务地位等价,正常响应服务请求的2台 Nginx 截至6:59各产生了约120条访问日志,而非正常Nginx 访问日志中访问日志为0条(排除 curl 类 agent 触发的健康检查日志)。
更多 Nginx 访问日志在故障预防和故障发现中的用法,后续会专门讨论。
关注微信公众号,获取运维资讯
如果此篇文章对你有所帮助,感谢你的点赞与收藏,也欢迎在评论区友好交流。
微信搜索关注公众号:持续运维