问题:
在hadoop的1.2.0中由于单个磁盘故障导致datanode节点失效,生产环境中datanode节点大多都有多块磁盘,我们现在需要一种方法,让datanode不会被单块磁盘的故障导致整个节点失效。
解决方法及适用场景:
1、修改hadoop源代码(介个在作者能力之外)
2、修改hdfs-site.xml中的dfs.data.dir的值,将故障盘的挂载点删除并重启(推荐在手动部署的hadoop环境中,将此方法做成脚本使用)
3、卸载故障盘,临时将数据写入根目录的挂载点,不修改配置文件(笔者的环境,使用hortonworks部署的hadoop,配置文件由ambari管理,手动修改后一旦使用ambari便会被同步回原来的配置...)
第三种解决方法的部分需求和代码实现
需求:
1、检测到故障盘的挂载点连续三次故障后再进行卸载并停止datanode以免错误判断
2、卸载故障盘后,检测到挂载点正常便启动datanode
3、在datanode启动后,依然能对故障盘进行nagios报警,以提醒管理员
4、管理员修复磁盘后,仅需手动停止datanode,并挂载修复后的磁盘即可,脚本会自动检测磁盘的挂载点并启动datanode
5、假设系统盘有一定可用容量,且一直是好的,因为当系统盘故障后...没有然后了...
代码实现:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
#!/bin/bash
# datanode的挂载点列表
MPT[0]=/storage/disk1/
MPT[1]=/storage/disk2/
# check_readonly 此脚本是用来检测datanode的挂载点是否可以,错误则必须输出有:ERROR DIRECTORY 关键字
CRD=/opt/nagios-bin/check_readonly
# chk_rw.sh是nagios被动监控脚本,用来向nagios发送本地磁盘信息
RWS=/opt/nagios-bin/chk_rw.sh
DPID=`cat /var/run/hadoop/hdfs/hadoop-hdfs-datanode.pid`
KD=`ps aux|grep -v grep|grep $DPID`
HOSTNAME=`uname -n`
LIP=`grep $HOSTNAME /etc/hosts|awk '{print $1}'`
CTF=/tmp/count.log
[ ! -f "$CTF" ] && echo 0 > "$CTF"
for i in ${MPT[@]};do
CTE=`$CRD $i|grep "ERROR DIRECTORY"`
NMP=`df $i|/usr/bin/tail -1|awk '{print $NF}'`
# 判断datanode是否需要启动,并启动
if [[ -z "$CTE" && -z "$KD" ]];then
chmod 777 $i &>/dev/null
rm -rf "$i"/* &>/dev/null
su - hdfs -c "/usr/lib/hadoop/bin/hadoop-daemon.sh --config /etc/hadoop/conf start datanode" &>/dev/null
fi
# 如果挂载点正常,判断是否需要将发送给nagios服务端的脚本信息修改为正常
if [[ -z "$CTE" && "$NMP" != "/" ]];then
if grep "chkrw_state=2" $RWS &>/dev/null ;then
sed -i '/chkrw_state=2/d' $RWS
fi
continue
fi
# 当挂载点故障或挂载到根目录时,进入如下判断
if [[ -n "$CTE" || "$NMP" == "/" ]];then
DNP=`ps aux|grep -v grep|grep datanode|/usr/bin/wc -l`
# 当挂载点正常,datanode进程正常,且挂载点为根时,跳出循环
[[ -z "$CTE" && "$NMP" == "/" && -n $DNP ]] && continue
# 计数器,走到此步骤则+1,满足三次之后便进入如下判断
/usr/bin/expr `cat $CTF` + 1 > $CTF
if [ `cat $CTF` -ge 3 ];then
echo 0 > "$CTF"
# 清零计数器,并修改想nagios发送信息的脚本
if ! grep "chkrw_state=2" $RWS &>/dev/null ;then
sed -i '/chkrw_state=$?/achkrw_state=2' $RWS
fi
# 停止可能占用故障挂载点的进程并停止datanode以及卸载
PIDL=(`/usr/sbin/lsof $i|awk '{print $2}'|grep -v PID`)
for p in ${PIDL[@]};do
[ -z "$p" ] && continue
kill -9 $p
done
/bin/umount $i &> /dev/null
chmod -R 777 $i
if [[ "$NMP" == "/" ]];then
su - hdfs -c "/usr/lib/hadoop/bin/hadoop-daemon.sh --config /etc/hadoop/conf stop datanode" &>/dev/null
[ -n "$KD" ] && kill -9 $DPID &> /dev/null
else
echo "`/bin/date +%k:%M:%S/%Y-%m-%d` $i umount fail." >> /tmp/check_mp.log
fi
fi
fi
done
# 向nagios服务器发送本地磁盘信息
$RWS $LIP ${MPT[@]}
注:
其中nagios方面的内容非本文重点,因此不再提供文中出现的对应脚本,如果需要,请联系笔者。
另需考虑使用根目录的情况一段时间后,故障盘修复或更换后,重新挂载后数据迁移量问题,笔者考虑此问题时曾尝试将此时的系统盘挂载点的数据同步到新磁盘上(点击此处查看此版本),如果此操作在很短的时间内完成时可行的,但是当数据量很多时(譬如需同步500G甚至1T时),短时间必然无法完成,而同步后启动datanode,通过日志发现datanode报错数据节点的注册位置不一致(详细见下图),但是datanode进程并不会因此挂掉(事实上,不做任何操作,仅停止datanode一会,再启动就会显示此错误),考虑对此方法产生的问题暂时无法确定其后果,因此笔者本文中和生产环境中在使用挂载点时先清空里面的内容,因此启动后通过日志可看到hdfs在进行大量的数据同步操作。
将此脚本按需要的频率,写入计划任务即可。
阅读(2379) | 评论(0) | 转发(0) |