一次基于docker的遗留系统线上异常排故经验分享

背景

最近遇到了一个遗留系统的排故问题,觉得比较有意思,反正每人看,在这里唠叨一下。

基本情况

最近有一个很长时间没有维护的系统的客户打电话过来说反馈系统有异常,让给看看怎么回事。
经过初步询问是机房异常掉电后系统访问不了,心想八成是某个服务没起来,问题应该不大。于是安慰客户后,把这个项目的基本情况捡起来看了看,这个项目上次维护已经可以追溯到近两年前,而且该系统是我方负责后端,前端由外包单位负责开发和运维的,到现在为止外包单位已经换了两拨,最近的那波人都找不到了。更要命的是客户的系统是部署在内部网络的,是无法通过外网访问到的。基本情况捋到这就差不多了,我感觉不太妙,估计是个深坑。
不管怎么说,客户都反馈到我这了,还是看看吧。于是下面故事开始。

排故的故事

基本情况摸底

跟客户对接人联系,反馈系统界面无法访问,但服务器可以ping的通,telnet也可以通。ok,基本工具都会用,还是挺靠谱的。

初次交锋

页面都打不开,初步判断应该是前端有问题,由于系统部署到客户内网的,我这也看不到情况,不过好在前端是单独部署在一个服务器上的,而且是docker化运行的,经过部署脚本使用了–restart=always,应该能自动起来。本着尝试的精神,让客户来一次重启大法。经过3分钟漫长的等待,客户反馈启动好了,赶紧让客户打开浏览器看一下,嗯果然不出所料,页面可以访问了,正在暗自高兴。
但坏消息接踵而至:

  • 页面刷出来的时间特别长,10多秒还在转圈。
  • 无法登录到系统内部。

WTF!什么情况?反应慢还好说,怎么还无法登录了,无法登录一般是后端服务出问题了啊,赶紧跟客户视频聊天开起来,一个动作一个动作,检查后端服务是不是都还健在。
WTF!一切正常。
又让客户打开浏览器的控制台,查看networrk情况,登录接口确实是长时间没有响应,但仔细一看,这个接口却不是发给后台的而是发给前端自己的,嗯?这就很可疑了,转念一想,估计是自己做了个node或是nginx代理来解决跨域问题。
于是让客户直接通过工具将登陆请求直接发给后台,果然访问正常。问题还是在前台,不自觉的松了一口气,毕竟不是自家做的,除了问题甩锅很方便。- -!
这是客户又反馈现在页面都打不开了。WTF!什么情况。
这时三个小时已经过去了。考虑到客户该吃饭了,先表示休息一下吧,我在整理整理思路。同时侧面问了问为啥这次没有叫我们跑过去,原来客户单位现在不让外部单位的人进,要不然早就让我们跑过去解决了(同一个城市)。

二次上阵

中午吃着盒饭,同时整理手头上的信息。

  • 服务器ping的通
  • 后端服务正常
  • 请求经过代理访问后端服务超时
  • 页面本来打不开
  • 重启后页面能够访问,但加载特别慢
  • 过了大概10分钟,页面也无法访问了,显示超时
    目前看大概率前端服务器有异常。中毒?网络丢包?都不像。
    吃过盒饭,联系客户再战问题。第一件事就是检查网络情况,简单一点直接ping一个大包,没有丢包。然后就只能远程到服务器上来检查了,前端服务器操作系统是没有GUI的centos,这对于客户是一个挑战,他们自带的运维系统还登录不了这个系统不知道什么原因,只能让他先用putty了。
    半小时后putty终于连接到前端服务器了,赶紧ps -x 一下看看,结果吓了一大跳,有N个node进程,而且每个CPU占用都超过100%,加一块大概800%,跟核数一致,这下基本可以判定是CPU打满造成的问题。结合这台机器上的服务都是docker运行的,再利用docker stats看看各个容器的资源占用情况,果然都超过100%。
    这下清楚问题了,但也是个坏消息,暂时没有简单直接的解决方案。于是再次询问有没有其他途径能访问他们的系统。客户提供了一个激动人心的消息,刚刚想起,那就是我们单位应该还有一个网卡可以访问,并提供了网卡联系人。
    终于找到了救星,赶紧联系人,半小时后拿到专网卡。这下终于能够正面刚了。

三度决战

喝口水稳稳心神,插上网卡,输入登录信息,连接上网络。
在打开终端,连接商前端服务器,决战正式开始。
不亲眼看到这个情况真的是很难相信,一个前端服务器竟然整整齐齐运行着近10个页面应用,但都是不同的端口。估计是我们这边的业务人员不断的提需求,以及临时充数的页面,外包的同学们改改就直接都甩到了这个服务器上。时间真是一把杀猪刀,对人如此,对系统更是如此。
赶紧联系业务人员和客户确定哪些有用,把不用的服务都停下来,ok,这下服务就剩下四个了。现在CPU没有被打满了,前端页面也可以访问了。服务器操作也顺畅起来了,接下来再继续定位问题。
这四个服务也没有人访问,CPU占用还是特别高,这显然不正常。于是找一个服务使用docker logs XXX看一下日志,看到日志显示它正在疯狂的重连websocket。
退出来查看另一个服务,同样的问题。终于看到了希望,这也许是一个因素。检查代码,看他连的那个websocket到底是干什么的,发现是一个中间件。
又检查这个中间件,这个中间件服务虽然在运行但无法访问,应该是掉电后状态异常造成的。更要命的是关闭不了这个服务,于是只能重启机器,再强制关闭这个服务。ok,在尝试重启中间件,WTF!还是不行。检查日志也没有看出什么异常,我去,这麻烦了。正当心烦气躁时,不经意间看了看docker的容器中也有一个消息中间件的容器,但是没有运行起来。检查指令发现这个容器确实运行过。
一种可能性出现了,可能是之前外包运维团队开始是直接部署的,但发现有兼容性问题,于是又更换为docker部署,成功后,但没有删除直接部署的服务。在这次掉电后直接的部署的服务在docker之前就自动启动了,正常的中间件无法运行,也就出现了node服务疯狂重连的问题。

于是赶紧把docker中的中间件启动起来,发现一切终于安静了,那堆100%的服务都迅速回归到正常。正当我以为世界终于恢复到正常的时候,删除了直接部署的中间件,邀请客户确认系统时,发现系统不太对劲,跟原来的系统相比很多地方都不一样,而且有的功能还用不了。
WTF!这是怎么回事,这是典型的版本问题啊。赶紧检查代码版本,没有问题。又去查docker的镜像版本,也没有问题。再去看看容器信息,启动的镜像竟然不是最新的,而是近两年前的版本。仔细检查,容器启动命令发现使用了–restart=always,再用docker container ls -a检查全部镜像,发现有大量的过去的容器没有销毁,而且都是使用了 同一端口。事情到这里明确了,很多容器都是用自动重启,但都是一个端口,于是之后又一个容器能够成功启动,这个容器使用的镜像又不是最新的。于是赶紧停下错误的容器,启动最新的镜像的容器。同时删除那些早已过期的容器和镜像。

再次检查系统页面,终于一切都恢复正常。

服务恢复时间距离客户联系时间已经过了6个小时。

后续处理

虽然解决了问题,但CPU打满的根本原因并没有找到,难道一直尝试连接websocket真的能够造成这种问题么。我在本机上试图模拟复现生产系统的问题,虽然CPU确实会升高但远没有打满,一般4~5%最高时达到20%。没有复现出生产事故。
考虑到开发机器的docker和操作系统版本与生产系统的不一致,所以这个结论也没有办法排除这个原因。后续由于专网卡又被其他人借走,访问不到系统只能等网络连接恢复后再做定位了。高度怀疑是docker和操作系统版本过低的原因,毕竟是4年之前的版本了,而且使用pm2-docker来做守护,有可能有兼容性问题。

回顾

  • 表面原因
    掉电以及生产环境设置不合理造成的
  • 技术原因
    配置不合理,没有充分考虑到无人运维的情况下断电重启的问题
  • 管理原因
    交接不彻底,对于个人依赖性过强
    由于各种原因,生产环境处理失控状态

总结

  • 一个问题的出现往往不是一个问题产生的,注意排除全部问题和恢复性校验
  • docker是个好东西,但运维需要规范化管理
  • 不要依赖某个人或某几个人,要有对应的文档
  • 盲目应用理解不深的技术都可能对比造成极大的负面影响
原创文章 155 获赞 81 访问量 22万+

猜你喜欢

转载自blog.csdn.net/zhaoenweiex/article/details/105189656