代码靠谱多重要

48 阅读3分钟

最近组内发生了一起线上事故,简直可以定义为低级事故,随即触发了自己的一点思考,靠谱健壮的代码以及规善的测试流程在生产环境是多么重要

事故描述

事故描述如下:当时平台发现很多容器执行扩容失败,一直存在某个服务的接口报错,随即立马告警出来,有服务的实例存在panic,而且扩容的越多,panic的实例也越多,因为panic会有栈调用,当时一下就定位了代码如下

发现是这里空指针异常

止损如下

该函数上层的逻辑发现是因为SRE在往平台加机器导致触发了这个逻辑导致服务panic,进而导致连锁反应就是服务的接口访问失败,平台出现SLA告警以及进程退出告警

于是立马请SRE先退水加入平台的机器,panic告警随即停止,然后服务趋于稳定

事故分析

那为什么会panic呢,我们仔细查看研读上面的代码逻辑,发现逻辑也比较简单,就是从一个ServiceAccount账号里面获取对应的 secret 的名称

然后再通过这个获取到的 secret 的名称去访问对应的 token

于是初步怀疑是因为这个secret没有导致的,去线上查看对应的服务账号的 sercret,发现果然是没有的

那为什么会没有呢,仔细观察集群的版本,发现新加机器的集群的版本是 k8s-1.24

于是去找到对应的 changelog

发现 k8s-1.24 版本有一个很大的变更就是 ServiceAccount 不再支持自动创建 secret 了

但是代码里面又是 hardcode 直接取数组的索引,导致程序 panic,至此

思考如下

为什么要hard-code取下标?

个人觉得这里犯了一个最低级的错误,对待外部的数据我们没有任何保护性以及防御性的错误,居然直接 hard-code 取了下标,而不是先检查数组的索引?

而且这里有一个点就是理论上是A功能失效了,为什么会影响到B功能;理论上是A功能挂了直接导致了进程退出,进而服务直接挂了无法直接提供服务,为什么做不到A/B互相隔离?理论上这两个没有任何关连,不能因为某一部分挂了影响到全局所有的功能

测试缺失

这么重要的功能,尤其是版本升级没有考虑到兼容性,居然直接在生产环境做实验,这着实是不应该;流程测试应该全局覆盖到开发的测试环境以及预发布的e2e测试环境

不够重视版本差异

理论上大版本之间的升级我们都必须先通读一下changelog,看一下差异点;尤其是类似这种官网已经明确强调了升级一定要注意的事项