下面是整理后的事故报告:
事故概述
公司午高峰期间,支付服务的k8s 执行了pod的扩容操作,但由于id生成器服务资源不足,导致新增的pod无法成功连接到id生成器服务。由于id生成器服务采用懒加载方式,只有写操作才会用到,因此所有的查询请求都可以执行,但所有的写入操作全部失败。这导致了流量成倍增加,pod继续扩容,一度达到了14个,正常中午5个就够用了,虽然pod增加了,但是一些支付逻辑并未执行,超时关单了,或者支付失败,造成非常差的用户体验。
事故原因
id生成器服务采用懒加载方式,没有在启动时初始化连接池,只有第一个使用时才会初始化连接池。同时,aws那边回收了机器(node节点),但id生成器服务所在的pod并没有回收成功,导致部分连接失败。
运维侧原因
运维侧相关人员表示,aws那边回收了机器,但id生成器服务所在的pod并没有回收成功,这是因为应该先把pod对应的地址在服务发现之类的路由表移除以后,再去回收pod,但此次没有按照正常流程进行。对于这个问题,虽然我不是运维,但是在go语言2023年开发者大会上,我有幸观看了一些k8s运维相关的讲座,里面提到了k8s的不足,里面提到关于pod的容器退出是不保证顺序的。
image.png
image.png
解决思路
为了避免类似事故再次发生,建议在服务启动时调一下id生成器、ping一下数据库,成功以后再启动grpc服务器。同时,后续健康检查也要重写一下,加入其它更合理的逻辑,如ping数据库,一些grpc服务等等。
总结
本次事故主要是由于id生成器服务的懒加载方式和运维侧的不当操作导致的。通过在服务启动时进行初始化连接池和重写健康检查,可以有效避免类似事故再次发生。