我们线上云原生系统出了一次大故障,惊心动魄,今天复盘整个过程,总结经验教训,避免再犯。
我们,线上,的,云原生,系统,前段时间,出,了,一次,大故障,整个,过程,惊心动魄,从,故障,发生,到,排查,到,定位,到,恢复,再,到,复盘,总结,整个,过程,让,我,学到,了,很多,也,有,很多,经验,教训,值得,总结,和,分享。
今天,这篇,文章,就,来,复盘,这次,故障,的,整个,过程,包括,故障,背景,故障,现象,排查,过程,根本原因,恢复,措施,以及,经验,教训,和,改进,措施。
一、故障背景
先,说说,我们,系统,的,背景,我们,的,系统,是,一个,面向,C端,用户,的,互联网,应用,用户,量,比较,大,日活,几百万,峰值,QPS,几万,整个,系统,是,基于,云原生,架构,搭建,的,用,Kubernetes,做,容器,编排,Docker,做,容器化,微服务,架构,服务,之间,用,gRPC,通信,用,Istio,做,服务,网格,配置,中心,用,Nacos,注册,中心,也,用,Nacos,消息,队列,用,Kafka,缓存,用,Redis,数据库,用,MySQL,分库分表,整个,技术,栈,比较,新,也,比较,复杂,是,典型,的,云原生,架构。
我们,的,Kubernetes,集群,是,自建,的,在,云服务器,上,自己,搭建,的,K8s,集群,有,三个,master,节点,和,二十多个,worker,节点,每个,服务,都,容器化,部署,在,K8s,上,用,Deployment,管理,副本,用,Service,做,服务,发现,用,Ingress,做,入口,流量,转发,用,ConfigMap,和,Secret,管理,配置,和,密钥,用,PV/PVC,做,持久化,存储,用,Helm,做,应用,包,管理,整个,部署,和,运维,流程,都,比较,自动化,CI/CD,流水线,用,Jenkins,代码,提交,后,自动,构建,镜像,推送,到,镜像,仓库,然后,自动,部署,到,K8s,集群,整个,流程,比较,顺畅,也,比较,规范。
故障,发生,在,一个,周五,的,晚上,八点,左右,正是,用户,使用,的,高峰期,我们,当时,正在,做,一个,新版本,的,发布,这个,版本,主要,是,做,了,一些,功能,优化,和,性能,提升,改动,不,算,特别,大,但是,涉及,到,几个,核心,服务,的,修改,我们,按照,正常,的,发布,流程,先,在,测试,环境,验证,通过,然后,预发布,环境,验证,通过,然后,开始,灰度,发布,到,生产,环境,先,发布,了,10%,的,流量,观察,了,十几分钟,没有,发现,异常,然后,继续,扩大,灰度,比例,到,30%,50%,最后,全量,发布,整个,发布,过程,看起来,很,顺利,没有,什么,异常,我们,当时,还,觉得,这次,发布,挺,顺利,的,但是,没想到,全量,发布,后,不久,故障,就,发生,了。
二、故障现象
故障,是,在,全量,发布,后,大概,半个,小时,开始,出现,的,最,开始,是,运维,监控,系统,开始,告警,说,有,几个,服务,的,错误率,上升,响应,时间,变长,我们,当时,正在,做,发布,后,的,观察,以为,是,发布,后,的,正常,波动,没有,太,在意,但是,很快,告警,越来越,多,越来越,严重,错误率,从,最,开始,的,百分之几,上升,到,百分之几十,甚至,有些,接口,直接,报,503,服务,不可用,响应,时间,也,从,正常,的,几十,毫秒,上升,到,几,秒,甚至,超时,用户,开始,反馈,APP,打不开,加载,慢,报错,等等,问题,我们,才,意识到,出,大故障,了。
当时,的,现象,主要,有,几个,第一,多个,核心,服务,的,Pod,频繁,重启,CrashLoopBackOff,状态,K8s,Dashboard,上,看到,很多,Pod,在,不断,重启,日志,里,报,OOMKilled,内存,溢出,被,杀死,第二,服务,的,错误率,飙升,很多,接口,报,500,或者,503,服务,不可用,第三,服务,响应,时间,变长,很多,接口,超时,第四,Kafka,消息,堆积,消费者,消费,不,过来,消息,队列,里,堆积,了,几百万,条,消息,第五,Redis,连接,数,飙升,达到,了,连接,数,上限,很多,服务,连,不,上,Redis,第六,数据库,连接,数,也,飙升,慢查询,增多,数据库,CPU,使用率,很高,整个,系统,像,多米诺骨牌,一样,一个,接,一个,出,问题,从,最,开始,的,几个,服务,错误率,上升,很快,蔓延,到,整个,系统,多个,服务,都,出,问题,整个,系统,几乎,要,雪崩,了,情况,非常,危急,当时,我们,整个,团队,都,紧张,起来,了,开始,紧急,排查,故障。
三、排查过程
故障,发生,后,我们,立刻,启动,了,故障,应急,响应,机制,整个,团队,分工,合作,开始,排查,故障,最,开始,我们,怀疑,是,新,版本,的,代码,有,问题,因为,故障,是,在,发布,新,版本,后,发生,的,时间,点,很,吻合,所以,我们,第一,反应,就是,回滚,版本,但是,回滚,之后,发现,故障,没有,恢复,还是,一样,的,现象,服务,还是,在,频繁,重启,错误率,还是,很高,这,说明,故障,不,是,新,版本,代码,的,问题,或者,不,仅仅,是,代码,的,问题,回滚,解决,不,了,我们,当时,有点,慌,了,因为,最,可能,的,原因,被,排除,了,而且,故障,还,在,恶化,用户,反馈,越来越,多,压力,很,大。
然后,我们,开始,看,服务,的,日志,和,监控,指标,发现,出问题,的,服务,都,有,一个,共同,的,现象,就是,内存,使用率,很,高,很多,Pod,都是,因为,OOM,被,杀死,的,而且,这些,服务,的,线程,数,也,很,高,比,正常,时候,高,了,很多,我们,怀疑,是,有,内存泄漏,或者,线程,泄漏,但是,回滚,了,版本,还是,这样,说明,不,是,新,代码,引入,的,问题,那,是,什么,呢,我们,又,看,了,K8s,集群,的,状态,发现,worker,节点,的,内存,使用率,也,很,高,很多,节点,内存,使用率,超过,90%,甚至,有些,节点,达到,100%,节点,的,内存,不够,了,导致,调度,在,上面,的,Pod,内存,紧张,频繁,OOM,我们,当时,以为,是,节点,内存,不够,了,就,紧急,扩容,了,几个,worker,节点,把,一些,Pod,调度,到,新,节点,上,但是,扩容,后,发现,新,节点,的,内存,很快,又,被,占满,了,Pod,还是,在,OOM,重启,这,说明,不,是,节点,资源,不够,的,问题,而是,有,什么,东西,在,疯狂,消耗,内存,而且,是,持续,的,不断,增长,的。
然后,我们,开始,深入,看,服务,的,内存,使用,情况,用,jmap,和,jstack,看,Java,服务,的,内存,堆,和,线程,栈,因为,我们,大部分,服务,是,Java,写,的,看,了,之后,发现,一个,惊人,的,现象,每个,服务,的,线程,数,都,非常,多,正常,时候,一个,服务,大概,几百,个,线程,但是,当时,每个,服务,都,有,几千,甚至,上万个,线程,而且,大部分,线程,都,处于,等待,状态,在,等,什么,呢,看,线程,栈,发现,大部分,线程,都,在,等,Redis,连接,或者,数据库,连接,或者,Kafka,连接,也就是说,线程,都,阻塞,在,等,资源,连接,上,了,为什么,会,有,这么,多,线程,在,等,连接,呢,因为,连接,不够,用,了,很多,线程,都,在,等,空闲,连接,但是,连接,一直,被,占用,不,释放,所以,线程,越,积,越,多,每个,线程,都,占,一定,的,内存,线程,多,了,内存,自然,就,不够,了,导致,OOM,所以,根本,问题,是,连接,泄漏,连接,被,占用,了,不,释放,导致,连接,池,耗尽,线程,阻塞,堆积,内存,溢出,服务,崩溃,但是,为什么,会,突然,出现,连接,泄漏,呢,之前,一直,好好,的,为什么,发布,后,就,出,问题,了,呢。
然后,我们,继续,排查,连接,为什么,不,释放,看,了,代码,里,连接,使用,的,地方,发现,我们,用,了,一个,新,的,SDK,这个,SDK,是,用来,做,服务,监控,和,链路,追踪,的,这次,发布,新,版本,的,时候,我们,升级,了,这个,SDK,的,版本,从,1.x,升级,到,2.x,当时,看,升级,文档,说,2.x,版本,性能,更,好,功能,更,强,而且,兼容,1.x,的,API,所以,我们,就,直接,升级,了,没有,太,仔细,看,变更,细节,现在,怀疑,是,这个,SDK,升级,导致,的,问题,我们,看,了,这个,SDK,2.x,版本,的,源码,和,变更,日志,发现,2.x,版本,为了,提升,性能,改了,连接,管理,的,机制,引入,了,一个,新,的,连接,池,实现,但是,这个,新,的,连接,池,实现,有,一个,bug,在,某些,异常,场景,下,连接,不会,被,释放,会,泄漏,而且,这个,bug,是,偶现,的,在,低,并发,下,不容易,触发,但是,在,高,并发,下,很,容易,触发,我们,测试,环境,和,预发布,环境,并发,都,不,高,所以,没有,触发,这个,bug,但是,生产,环境,高,并发,全量,发布,后,很快,就,触发,了,连接,泄漏,连接,池,耗尽,然后,连锁反应,导致,整个,系统,雪崩,终于,找到,根本原因,了,当时,整个,团队,都,松,了,一口气,但是,故障,还,没,恢复,还,需要,紧急,处理。
四、恢复措施
找到,根本原因,后,我们,立刻,采取,了,恢复,措施,首先,是,紧急,降级,这个,SDK,的,功能,因为,这个,SDK,是,做,监控,和,链路,追踪,的,不是,核心,业务,功能,降级,了,不,影响,核心,业务,我们,通过,配置,中心,把,这个,SDK,的,采集,功能,关闭,了,让,它,不再,创建,和,使用,连接,这样,就,不会,再,泄漏,连接,了,配置,生效,后,很快,就,看到,效果,了,新,的,连接,不再,泄漏,线程,数,开始,下降,内存,使用率,也,开始,下降,服务,的,错误率,开始,降低,响应,时间,开始,变短,但是,因为,之前,堆积,了,很多,Kafka,消息,还有,很多,用户,请求,在,重试,系统,还是,有,一定,的,压力,我们,又,做,了,一些,限流,和,降级,措施,把,一些,非核心,的,功能,暂时,关闭,了,减轻,系统,压力,让,核心,功能,先,恢复,然后,慢慢,处理,堆积,的,消息,和,请求。
然后,我们,把,这个,SDK,的,版本,回退,到,1.x,的,稳定,版本,确认,1.x,版本,没有,这个,连接,泄漏,的,bug,然后,重新,发布,了,服务,把,所有,服务,的,SDK,都,回退,到,1.x,版本,确保,不会,再,触发,这个,bug,回退,完成,后,我们,又,观察,了,一段时间,确认,系统,稳定,了,连接,数,正常,线程,数,正常,内存,正常,错误率,正常,响应,时间,正常,Kafka,消息,堆积,也,慢慢,消费,完,了,整个,系统,恢复,正常,用户,也,不再,反馈,问题,了,故障,终于,恢复,了,从,故障,发生,到,完全,恢复,大概,持续,了,两个,多,小时,这,两个,小时,对,我们,来说,真的,是,惊心动魄,压力,非常,大,但是,最终,还是,成功,恢复,了,也,算是,不幸,中,的,万幸。
五、根本原因分析
故障,恢复,后,我们,做,了,详细,的,根本原因,分析,这次,故障,的,直接,原因,是,我们,升级,的,监控,SDK,2.x,版本,有,连接,泄漏,的,bug,在,高,并发,场景,下,触发,连接,泄漏,导致,连接,池,耗尽,线程,阻塞,堆积,内存,溢出,服务,崩溃,然后,连锁反应,导致,整个,系统,雪崩,但是,除了,这个,直接,原因,我们,还,分析,了,更深层,的,原因,为什么,这个,bug,能,流到,生产,环境,为什么,我们,没有,提前,发现,为什么,故障,发生,后,排查,了,这么,久,才,定位,到,原因,这些,深层,原因,更,值得,我们,反思,和,改进。
第一个,深层,原因,是,版本,升级,评审,不,严格,我们,升级,SDK,版本,的,时候,没有,严格,评审,变更,内容,只是,看,了,官方,说,兼容,性能,更,好,就,直接,升级,了,没有,仔细,看,变更,日志,和,源码,变更,也,没有,做,充分,的,测试,和,验证,尤其是,高,并发,场景,下,的,测试,没有,做,导致,这个,偶现,的,bug,没有,被,提前,发现,流到,了,生产,环境,这,是,我们,流程,上,的,漏洞,版本,升级,不管,大小,都,应该,严格,评审,充分,测试,不能,因为,是,小版本,升级,或者,官方,说,兼容,就,掉以轻心。
第二个,深层,原因,是,测试,环境,和,生产,环境,差距,大,我们,的,测试,环境,和,预发布,环境,并发,量,都,很,低,和,生产,环境,的,高,并发,差距,很,大,很多,高,并发,下,才,会,触发,的,bug,在,测试,环境,根本,触发,不,了,所以,测试,通过,了,不,代表,生产,就,没问题,我们,需要,有,更,接近,生产,环境,的,压测,环境,做,全链路,压测,在,高,并发,场景,下,验证,系统,的,稳定性,和,性能,提前,发现,这类,问题。
第三个,深层,原因,是,监控,和,告警,不够,完善,故障,最,开始,发生,的,时候,我们,的,监控,只,告警,了,错误率,和,响应,时间,但是,没有,更,细,粒度,的,监控,比如,连接,池,使用,情况,线程,数,内存,使用,分布,等等,如果,我们,有,连接,池,使用,情况,的,监控,能,看到,连接,数,持续,增长,不,释放,就能,更早,发现,问题,更快,定位,原因,不用,排查,这么,久,所以,我们,需要,完善,监控,体系,更,细,粒度,地,监控,系统,的,各项,指标,做到,早,发现,早,预警。
第四个,深层,原因,是,故障,应急,响应,机制,不够,完善,故障,发生,后,我们,最,开始,有点,慌,排查,思路,不,够,清晰,走,了,一些,弯路,比如,最,开始,直接,回滚,版本,但是,回滚,解决,不,了,问题,浪费,了,一些,时间,而且,团队,分工,也,不,够,明确,有些,事情,重复,做,了,有些,事情,没有,人,做,所以,我们,需要,完善,故障,应急,响应,机制,制定,清晰,的,故障,排查,流程,和,团队,分工,定期,做,故障,演练,提升,团队,的,故障,应急,响应,能力,做到,故障,发生,后,能,快速,有序,地,排查,和,恢复。
六、经验教训和改进措施
通过,这次,故障,我们,总结,了,很多,经验,教训,也,制定,了,一系列,改进,措施,避免,再,犯,类似,的,错误,下面,分享,给,大家。
第一,严格,版本,变更,评审,流程,不管,是,应用,代码,变更,还是,依赖,SDK,版本,升级,还是,配置,变更,都,要,严格,评审,评审,变更,内容,影响,范围,风险,点,回滚,方案,等等,不能,因为,是,小变更,或者,官方,说,兼容,就,掉以轻心,所有,变更,都,要,有,记录,有,评审,有,验证,才能,上线,而且,升级,第三方,依赖,的,时候,要,仔细,看,变更,日志,和,源码,变更,了解,清楚,改了,什么,有,什么,风险,不能,盲目,升级。
第二,完善,测试,和,压测,体系,建立,更,接近,生产,环境,的,预发布,环境,和,压测,环境,做,全链路,压测,在,高,并发,场景,下,验证,系统,的,稳定性,和,性能,提前,发现,高,并发,下,才,会,触发,的,bug,和,性能,问题,而且,每次,重大,变更,上线,前,都,要,做,充分,的,测试,和,压测,确保,系统,稳定,才能,上线,不能,只,做,功能,测试,不,做,性能,测试,和,高,并发,测试。
第三,完善,监控,和,告警,体系,增加,更,细,粒度,的,监控,指标,比如,连接,池,使用,情况,线程,数,线程,状态,分布,内存,使用,分布,GC,情况,等等,做到,系统,的,各项,指标,都,能,监控,到,而且,设置,合理,的,告警,阈值,做到,异常,早,发现,早,预警,不要,等,故障,已经,很,严重,了,才,告警,另外,建立,统一,的,监控,大盘,能,一目了然,地,看到,整个,系统,的,运行,状态,方便,故障,排查,和,定位。
第四,完善,故障,应急,响应,机制,制定,清晰,的,故障,分级,标准,和,应急,响应,流程,明确,不同,级别,故障,的,响应,人,处理,流程,升级,机制,等等,而且,明确,团队,分工,谁,负责,排查,谁,负责,恢复,谁,负责,沟通,谁,负责,记录,等等,避免,故障,发生,后,混乱,无序,另外,定期,做,故障,演练,模拟,各种,故障,场景,提升,团队,的,故障,应急,响应,能力,和,排查,经验,做到,真正,故障,发生,的,时候,能,快速,有序,地,处理。
第五,建立,完善,的,降级,和,限流,机制,对,非核心,功能,都,要,有,降级,开关,故障,发生,的,时候,能,快速,降级,非核心,功能,减轻,系统,压力,保证,核心,功能,可用,而且,对,核心,接口,要,有,限流,机制,防止,流量,突增,把,系统,打垮,另外,做好,容量,规划,和,弹性,伸缩,机制,系统,能,根据,流量,自动,扩容,和,缩容,应对,流量,波动,保证,系统,稳定性。
第六,重视,第三方,依赖,的,质量,和,安全,第三方,SDK,和,依赖,是,我们,系统,的,一部分,它们,的,质量,和,安全,直接,影响,我们,系统,的,稳定性,所以,选择,第三方,依赖,的,时候,要,慎重,选择,活跃,维护,口碑,好,的,开源,项目,而且,升级,版本,的,时候,要,慎重,充分,测试,不要,盲目,追新,另外,对,核心,依赖,要,有,备选,方案,和,快速,替换,的,能力,万一,出,问题,能,快速,切换,到,备选,方案,减少,故障,影响。
七、写在最后
这次,云原生,故障,对,我们,团队,来说,是,一次,非常,深刻,的,教训,也是,一次,非常,宝贵,的,经历,整个,过程,惊心动魄,压力,非常,大,但是,通过,这次,故障,我们,发现,了,系统,和,流程,中,的,很多,问题,也,做,了,很多,改进,整个,团队,的,技术,能力,和,运维,能力,都,有,了,很大,提升,系统,的,稳定性,也,更,高,了,从,这个,角度,来说,这次,故障,也,不是,完全,是,坏事,塞翁失马,焉知非福,只要,能,从,故障,中,学习,和,成长,避免,再,犯,类似,的,错误,故障,就,有,价值。
做,互联网,系统,尤其是,云原生,架构,的,系统,复杂度,很,高,涉及,的,技术,栈,很,广,出,故障,是,难免,的,没有,人,能,保证,系统,永远,不,出,故障,重要,的,是,出,了,故障,之后,怎么,快速,恢复,怎么,从,故障,中,学习,和,成长,怎么,避免,再,犯,类似,的,错误,这,才,是,更,重要,的,所以,我们,要,重视,故障,复盘,每次,故障,后,都,要,认真,复盘,总结,经验,教训,制定,改进,措施,并且,落实,到位,这样,才能,不断,提升,系统,的,稳定性,和,团队,的,能力。
希望,这篇,故障,复盘,文章,能,给,做,云原生,和,运维,的,朋友,一些,参考,和,启发,也,希望,大家,的,系统,都,能,稳定,运行,少,出,故障,当然,如果,出,了,故障,也,不要,怕,认真,复盘,总结,教训,持续,改进,就,能,越,做,越,好,也,欢迎,大家,在,评论,区,分享,你们,遇到,过,的,云原生,故障,和,排查,经验,一起,交流,一起,进步,谢谢,大家,的,阅读。
评论(0)
暂无评论,快来抢沙发~
评论功能仅对会员开放,请先登录
登录