事故背景交代
涤生大数据花费重金购得几台较高配置的阿里云服务器机器,构建了一整套以cdh为核心的大数据课程教学、学员实操练习环境、但是,就是这个但是,以为集群规模目前相对较小。不会有什么幺蛾子发生,于是运维中最核心的监控没并有完善到集群。
事故发生
2023年4月18日的清晨,在企业微信沟通群中,我们的spark课程大佬健哥反馈说我们内部使用的wiki服务出现编辑内容后保存报错的问题,这里做个说明,为了让小白学员有真实的企业操作环境体验,我们在管理学员上使用的现在大多数公司使用的wiki服务。
问题排查一:
基于以上wiki服务的报错,一开始怀疑是网络的问题,首先查看了阿里云的网络监控,再次查看了我们的vpn服务监控(因为我们在集群安全防护上,是将所有的主机服务都隐藏在阿里云内网的,学员的对教学环境资源的访问都是需要通过VPN认证登录)还有其他内部服务的访问也都是没有问题的,这足以说明网络上是健康的。
于是打算登录通过jumpserver服务登录主机(这里做一个说明:我们提供给学员的练习平台是完全cp中小型企业的实际操作环境的,有基于web的【涤生数据开发平台】,也会有基于centos7系统的终端下shell 指令的练习操作,这一步就需要通过跳板机的认证授权,登录到特定的主机),通过检查wiki的服务日志来定位问题,此时发现jumpserver服务登录也出现的问题,无法正常登录,此时想起来,jumpserver服务和wiki服务是在一台主机上部署的,多年运维的直觉告诉我,有可能是主机层面出现问题了。才会有两个服务同时故障。于是立马通过cm的控制台查看主机资源的指标状态,一看吓一大跳,此刻文字表达不出(我草),各位看官请看下图:
于是只能通过后门(登录主机,基于管理员用户留有后门,以备在jumpserver出现异常情况下登录主机排查问题)登录其中一台主机(这里当然是jumpserver和wiki服务所在主机)通过df -h指令一看,果然所有的磁盘都被写满,庆幸的是主机还没有完全卡死,常规的运维指定还可以正常操作。于是发现磁盘写满是因为datanode的数据目录存储很大导致,由此判断是有异常的大文件被写入hdfs存储系统,将整个hdfs的存储容量打满了。
处理问题:
既然问题已经找到,此时只需要确认hdfs写入的大文件,然后删除大文件就可以解决问题,于是执行了最常规的操作指令
hdfs dfs -count -s hdfs:///
报错,尴尬了,因为所有的磁盘写满了,所有整个hadoop集群的服务也受到影响,导致整个集群都挂了,于是眼下之急只能是扩充磁盘容量或者从主机层面直接释放磁盘容量。
说干就干,扩充磁盘容量是不可能了,因为老板没钱啊(多推荐点学员,看官老爷们),具体查看磁盘的存储文件,发现其他的日志文件也占据不小的存储空间,(简直就是看到了救命稻草),删除此部分文件,应该可以恢复磁盘的正常读写,进而将整体服务拉起来,后面也就迎刃而解了。
果然,和我们预料的一样,磁盘在释放出来一定量的存储空间后,wiki服务,jumpserver服务都可以正常运作,唯独(此处眼中已经泛起了泪花)在拉起hdfs集群时namenode不能正常拉起。
问题排查二:
既然namenode不愿意正常运行,坑定是哪里出现了毛病,那不怕,咱干的就是这个,哪里有问题,就修哪里。
最常规的排查思路,看日志,只要日志看的好,80%的问题基本都能解决了。果不其然,日志中显示,namenode一开始是可以正常拉起的,但是在拉起一段时间后其中一个节点就挂掉了,而且从日志中可以发现,问题出现在HDFS启动时无法拉取JournalNode对应的数据,应该是JournalNode服务出现异常,于是通过查看JournalNode的服务日志继续深扒问题,于是乎,有了下面一段重要日志的出现:
从上面的日志文件中可知,因为是磁盘写满导致的JournalNode宕机,所以导致了JournalNode维护的edits文件损坏。
重点提示:HDFS启动如果报错是拉取JournalNode对应的数据异常,此类错误的原因大概率为JournalNode异常。
我们可以基于以下三点来排查处理问题:
观察JournalNode的启动状态和日志。
如果JournalNode的日志无明显异常,可考虑NameNode节点到JournalNode节点的网络联通性。
如果JournalNode出现上述异常日志,可以在集群中找到一个健康的JournalNode节点并通过将此节点上数据全部复制到其他节点来修复其他异常的JournalNode节点。
如果JournalNode出现上述异常日志,且所有的节点都出现异常,此时需要删除其中一个节点以edits_inprogress开头的文件,然后同步所有的文件到其他JournalNode节点。
最终解决:
本次集群的故障就是所有的JournalNode节点的数据文件发生损坏,处理手段也是删除其中一个节点的edits_inprogress开头的文件,然后同步到其他所有JournalNode节点,重启整个集群后,集群正常运行。
然后定位到hdfs的异常文件,删除此文件,磁盘恢复正常存储水平。所有服务恢复正常运行。
问题复盘:
复盘本次事故的原因,触发点很简单,就是没有及时监控主机磁盘,导致磁盘写满,进而引发一连串的问题发生,所以基于此,我们眼下需要做的就是完善告警机制。于是就安排起来了。
这里我们选用的也是当下比较火的三个搭档promethues+grafana+altermanager(小广告打一波:涤生大数据的运维课程体系中有关于这三个组件的详细使用教程以及详细的企业实战案例,有需要的老铁可以私聊)
结尾:
手撸webhook python小代码分享一波。
import json
import requests
from flask import Flask, request
app = Flask(__name__)
@app.route('/webhook', methods=['POST'])
def webhook():
data = request.get_json()
# 获取告警信息
alerts = data.get('alerts', [])
# 解析告警信息
for alert in alerts:
alertname = alert.get('labels', {}).get('alertname', 'Unknown')
status = alert.get('status', 'Unknown')
summary = alert.get('annotations', {}).get('summary', 'Unknown')
# print(alertname)
# print(status)
# print(summary)
# 构建机器人消息体
payload = {
"msgtype": "text",
"text": {
"content": f"*{alertname} {status}*\n{summary}"
}
}
# 发送消息到机器人
url = 'https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=a4df7f84-fe6e-47f9-xxx'
headers = {'Content-Type': 'application/json'}
response = requests.post(url, headers=headers, data=json.dumps(payload))
if response.status_code != 200:
return f"Failed to send notification: {response.text}", 500
return "Notification sent successfully", 200
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8080)