問題:
在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、假設系統盤有一定可用容量,且一直是好的,因爲當系統盤故障後...沒有然後了...
代碼實現:
#!/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在進行大量的數據同步操作。
將此腳本按需要的頻率,寫入計劃任務即可。
寫文不易,不正之處,歡迎指正,若覺得還能湊合,給個贊啊親..