hadoop運維筆記


一. 故障處理部分

1.1. spark提交任務報錯java.lang.NoClassDefFoundError: com/alibaba/fastjson/JSON

報錯原因: 在運行環境沒有找到fastjson的依賴庫
解決方法: 在SPARK_HOME/jars/ 添加fastjson-VERSION.jar包。 例如我的環境下SPARK_HOME是/usr/local/service/spark/。

[hadoop@10 ~]$ ls $SPARK_HOME/jars/fast*
/usr/local/service/spark/jars/fastjson-1.2.12.jar

1.2.  跨HDFS集群、HDFS屬主用戶不同,傳輸文件沒有權限的問題

這個問題衍生出兩件事,把這兩件事處理完問題即可解決。

  • 不同集群間解析
  • 不同集群屬主

先看一下不同集群間解析。要想跨集群傳輸文件,首先得確定集群相互"認識",即集群間確定通過ip或者hostname可達。在ip可達的前提下,我們判斷集群間是否"認識",則需要檢查hdfs-site.xml中dfs.namenode.datanode.registration.ip-hostname-check這項配置。它表示是否將ip反向解析成主機名,默認為true。如果未設置這一項,則需要對/etc/hosts添加主機解析,對於HDFS這種規模性集群來說,這很顯然是比較繁瑣的。

對於不同集群屬主來說,可以通過修改被傳文件權限或通過添加用戶、附加組使用戶獲得文件的讀取權限。

1.3 HDFS中hdfshosts直接使用ip遇到的問題

故障描述:

  1. 在hdfs web頁面顯示dn全部dead
  2. strace 追蹤dn進程,發現連接nn超時
  3. 查看dn日志報錯如下:
18/11/27 22:53:00 ERROR datanode.DataNode: Initialization failed for Block pool BP-958982478-10.0.220.44-1543329751956 (Datanode Uuid null) service to /10.0.220.44:9100 Datanode denied communication with namenode because hostname cannot be resolved (ip=10.0.220.48, hostname=10.0.220.48): DatanodeRegistration(0.0.0.0:50010, datanodeUuid=1e26933b-35a3-4d3f-8c5f-3ab03f10ca62, infoPort=50075, infoSecurePort=0, ipcPort=50020, storageInfo=lv=-56;cid=CID-1f213b85-b28c-4824-a44c-813c95ce7ecc;nsid=1612667934;c=0)
        at org.apache.hadoop.hdfs.server.blockmanagement.DatanodeManager.registerDatanode(DatanodeManager.java:852)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.registerDatanode(FSNamesystem.java:4486)
        at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.registerDatanode(NameNodeRpcServer.java:1286)
        at org.apache.hadoop.hdfs.protocolPB.DatanodeProtocolServerSideTranslatorPB.registerDatanode(DatanodeProtocolServerSideTranslatorPB.java:96)
        at org.apache.hadoop.hdfs.protocol.proto.DatanodeProtocolProtos$DatanodeProtocolService$2.callBlockingMethod(DatanodeProtocolProtos.java:28752)
        at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:616)
        at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:982)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2217)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2213)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:422)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1758)
        at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2213)

問題分析:
首先想到的就是NN與DN通信出現了問題。但是如題所述"直接使用ip",也就是說不在/etc/hosts做任何配置的前提下能正常工作。這時就需要考慮怎樣在hdfs的配置里面能夠使DN直接通過ip來訪問NN,即禁用對DN的ip做反向域名解析。
解決方法:
在NameNode節點 的 hdfs-site.xml添加如下內容

<property>
      <name>dfs.namenode.datanode.registration.ip-hostname-check</name>
      <value>false</value>
</property>

1.4 ambari hive server2啟動失敗。

報錯日志如下

Caused by: java.sql.SQLException: Access denied for user 'hive'@'xx.xx.xx.xx'(using password: YES)
        at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1078)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4187)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:4119)
        at com.mysql.jdbc.MysqlIO.checkErrorPacket(MysqlIO.java:927)
        at com.mysql.jdbc.MysqlIO.proceedHandshakeWithPluggableAuthentication(MysqlIO.java:1709)
        at com.mysql.jdbc.MysqlIO.doHandshake(MysqlIO.java:1252)
        at com.mysql.jdbc.ConnectionImpl.coreConnect(ConnectionImpl.java:2488)
        at com.mysql.jdbc.ConnectionImpl.connectOneTryOnly(ConnectionImpl.java:2521)
        at com.mysql.jdbc.ConnectionImpl.createNewIO(ConnectionImpl.java:2306)
        at com.mysql.jdbc.ConnectionImpl.<init>(ConnectionImpl.java:839)
        at com.mysql.jdbc.JDBC4Connection.<init>(JDBC4Connection.java:49)
        at sun.reflect.GeneratedConstructorAccessor17.newInstance(Unknown Source)
        at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
        at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
        at com.mysql.jdbc.Util.handleNewInstance(Util.java:411)
        at com.mysql.jdbc.ConnectionImpl.getInstance(ConnectionImpl.java:421)
        at com.mysql.jdbc.NonRegisteringDriver.connect(NonRegisteringDriver.java:350)
        at java.sql.DriverManager.getConnection(DriverManager.java:664)
        at java.sql.DriverManager.getConnection(DriverManager.java:208)
        at com.jolbox.bonecp.BoneCP.obtainRawInternalConnection(BoneCP.java:361)
        at com.jolbox.bonecp.BoneCP.<init>(BoneCP.java:416)
        ... 71 more

手動連接mysql依然連接不上,檢查發現連接權限不夠,重新授權后,啟動成功。

1.5 通過flume HDFSSink 寫HDFS丟數據

flume 日志報錯如下

30 Jul 2018 21:33:01,573 WARN  [SinkRunner-PollingRunner-DefaultSinkProcessor] (org.apache.flume.sink.hdfs.BucketWriter.append:545)  - Caught IOException writing to HDFSWriter (No lease on /tmp/20180730/2018073021.1564493581533.json.tmp (inode 33774359): File does not exist. [Lease.  Holder: DFSClient_NONMAPREDUCE_-2075237917_36, pendingcreates: 1]
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.checkLease(FSNamesystem.java:3432)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.analyzeFileState(FSNamesystem.java:3233)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getNewBlockTargets(FSNamesystem.java:3071)
        at org.apache.hadoop.hdfs.server.namenode.FSNamesystem.getAdditionalBlock(FSNamesystem.java:3031)
        at org.apache.hadoop.hdfs.server.namenode.NameNodeRpcServer.addBlock(NameNodeRpcServer.java:725)
        at org.apache.hadoop.hdfs.protocolPB.ClientNamenodeProtocolServerSideTranslatorPB.addBlock(ClientNamenodeProtocolServerSideTranslatorPB.java:492)
        at org.apache.hadoop.hdfs.protocol.proto.ClientNamenodeProtocolProtos$ClientNamenodeProtocol$2.callBlockingMethod(ClientNamenodeProtocolProtos.java)
        at org.apache.hadoop.ipc.ProtobufRpcEngine$Server$ProtoBufRpcInvoker.call(ProtobufRpcEngine.java:616)
        at org.apache.hadoop.ipc.RPC$Server.call(RPC.java:982)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2049)
        at org.apache.hadoop.ipc.Server$Handler$1.run(Server.java:2045)
        at java.security.AccessController.doPrivileged(Native Method)
        at javax.security.auth.Subject.doAs(Subject.java:422)
        at org.apache.hadoop.security.UserGroupInformation.doAs(UserGroupInformation.java:1698)
        at org.apache.hadoop.ipc.Server$Handler.run(Server.java:2045)
). Closing file (hdfs://xx.xx.xx.xx:xx/tmp/20180730//2018073021.1564493581533.json.tmp) and rethrowing exception.

問題分析:
從報錯情況來看,flume 使用HDFSWriter.appened方法寫事件時,發現臨時文件已經沒有租約,並未找到該文件,然后嘗試close文件,發現文件早已經close,再次拋出異常。
為什么出現這種情況呢?通過查看配置文件sink部分,發現hdfs.idleTimeout 的值設置過小。

agent.sinks.k1.type = hdfs
agent.sinks.k1.hdfs.path = "hdfs地址"
agent.sinks.k1.hdfs.filePrefix = %Y%m%d%H
agent.sinks.k1.hdfs.fileSuffix = .json 
agent.sinks.k1.hdfs.useLocalTimeStamp=true
agent.sinks.k1.hdfs.writeFormat = Text
agent.sinks.k1.hdfs.fileType = DataStream
agent.sinks.k1.hdfs.rollInterval = 300
agent.sinks.k1.hdfs.rollSize = 5073741824
agent.sinks.k1.hdfs.batchSize = 10000
agent.sinks.k1.hdfs.rollCount = 0
agent.sinks.k1.hdfs.callTimeout = 100000
agent.sinks.k1.hdfs.idleTimeout = 30
agent.sinks.k1.hdfs.round = true
agent.sinks.k1.hdfs.roundValue =60 
agent.sinks.k1.hdfs.roundUnit = minute

由於這個值設置的太小,然后每隔30s 就會判斷正在 bucketWriter 的文件是否更新,如果沒有更新 ,他就會flush, 然后關閉bucketWriter 。而實際上我們的source類型采用的是spooldir,每60s才會產生新文件。在沒有延遲的情況下,每60s bucketWriter才會更新,最后就導致一部分正常的HDFS寫請求失敗。
解決方法
修改hdfs.idleTimeout 的值為 hdfs.rollInterval 的2倍。

agent.sinks.k1.hdfs.idleTimeout = 600

hdfs.rollInterval 為hdfs文件的回滾周期,剛好達到rollInterval 需要回滾時,若出現HDFS或者網絡錯誤,導致回滾失敗。那么就經常在hdfs上出現很多.tmp文件。這時如果設置了hdfs.idleTimeout ,就可以很好的解決這個問題。但是切記,不可以設置的太短。建議稍微大於 hdfs.rollInterval 值。

二. hadoop集群平滑退役/上線節點(DataName/tasktracker or NodeManager)

在生產環境中可能會遇到退役(下線)服務器需求,對於計算節點來說強制下線節點影響的只是task作業,但是對於HDFS來說,就會出現數據丟失的風險。當然hadoop也提供了平滑下線的機制。

2.1 退役DataNode

2.1.1 在namenode節點hdfs-site.xml中增加配置,PATH路徑根據自己實際情況進行修改

<property>
       <name>dfs.hosts.exclude</name>
       <value>/usr/local/service/hadoop/etc/hadoop/hdfsexcludedhosts</value>
</property>

2.1.2 在相關文件中添加需要退役的主機

[hadoop@10 ~]$ cat  /usr/local/service/hadoop/etc/hadoop/hdfsexcludedhosts
10.0.0.1
10.0.0.2

2.1.3 在NameNode 運行以下命令,將經過審核的DataNode更新至NameNode

[hadoop@10 ~]$ hdfs dfsadmin -refreshNodes

2.1.4 查看下線情況

hdfs dfsadmin -report 

Decomissioning標記的即為正在下線的DataNode,hadoop集群會將下線的DataNode數據塊復制到其他節點。
復制完成之后會變成Decommission Status : Decommissioned。
2.1.5 下線完成后,清空/usr/local/service/hadoop/etc/hadoop/hdfsexcludedhosts 文件

[hadoop@10 ~]$ > /usr/local/service/hadoop/etc/hadoop/hdfsexcludedhosts

注意: 如果hadoop集群為HA,則需要在2個主控節點做相同操作

2.2 退役NodeManager 節點

2.2.1 在RM(ResourceManager)節點yarn-site.xml中增加配置,PATH路徑根據自己實際情況進行修改

<property>
        <name>yarn.resourcemanager.nodes.exclude-path</name>
       <value>/usr/local/service/hadoop/etc/hadoop/yarnexcludedhosts</value>
</property>

2.2.2 在相關文件中添加需要退役的主機

[hadoop@10 ~]$ cat  /usr/local/service/hadoop/etc/hadoop/yarnexcludedhosts
10.0.0.1
10.0.0.2

2.2.3 在RM節點 運行以下命令,將經過審核的NodeManager更新至RM

[hadoop@10 ~]$ yarn rmadmin -refreshNodes

2.2.4 下線完成后,在nodes include文件中去掉下線的機器,並清空exclude 文件

#yarn-site.xml 中nodes include 配置路徑,路徑根據自己實際情況
<property>
        <name>yarn.resourcemanager.nodes.include-path</name>
        <value>/usr/local/service/hadoop/etc/hadoop/yarnhosts</value>
</property>
[hadoop@10 hadoop]$ > /usr/local/service/hadoop/etc/hadoop/yarnexcludedhosts

注意: 如果hadoop集群為HA,則需要在2個主控節點做相同操作

2.3 上線DataNode節點

2.3.1 修改dfs.hosts對應配置文件,添加需要上線的機器

[hadoop@10 ~]$ cat /usr/local/service/hadoop/etc/hadoop/hdfshosts
10.0.100.53
10.0.100.52

2.3.2 在NameNode節點運行以下命令,將經過審核的datanode更新至namenode

[hadoop@10 ~]$ hdfs dfsadmin -refreshNodes

2.3.3 檢查是否上線成功

hdfs dfsadmin -report 

注意: 如果hadoop集群為HA,則需要在2個主控節點做相同操作

2.4 上線NodeManager節點

2.4.1 在nodes include文件中添加需要上線的機器

#yarn-site.xml 中nodes include 配置路徑,路徑根據自己實際情況
<property>
        <name>yarn.resourcemanager.nodes.include-path</name>
        <value>/usr/local/service/hadoop/etc/hadoop/yarnhosts</value>
</property>
[hadoop@10 ~]$ cat /usr/local/service/hadoop/etc/hadoop/yarnhosts 
10.0.100.53 
10.0.100.52

2.4.2 在RM節點 運行以下命令,將經過審核的NodeManager更新至RM

[hadoop@10 ~]$ yarn rmadmin -refreshNodes

注意: 如果hadoop集群為HA,則需要在2個主控節點做相同操作

三. hadoop集群標簽加入與退出

在生產環境中除了會遇到退役(下線)服務器需求,也可能會對集群標簽做一些相關操作,下面主要說一下在集群中如何從標簽中添加或退出節點

標簽相關操作

列出當前集群中存在的節點標簽

yarn cluster --list-node-labels

刪除當前集群中已存在的節點標簽

yarn rmadmin -removeFromClusterNodeLabels "<label1>,<label2>,..."

添加節點標簽到節點上

yarn rmadmin -replaceLabelsOnNode "node1.example.com=X"

通過如下命令可以批量從節點標簽中添加節點

$ cat addNodeList.txt 
node1.example.com
node2.example.com
node3.example.com
node4.example.com
node5.example.com

$ cat addNodeList.txt | xargs -t -i yarn rmadmin -replaceLabelsOnNode "{}=X"

從節點標簽中移除節點

yarn rmadmin -replaceLabelsOnNode "node1.example.com"

通過如下命令可以批量從節點標簽中移除節點

cat addNodeList.txt 
node1.example.com
node2.example.com
node3.example.com
node4.example.com
node5.example.com

$ cat addNodeList.txt | xargs -t -i yarn rmadmin -replaceLabelsOnNode "{}"

致謝:Hadoop 委任和解除節點
Flume-ng HDFS Sink “丟數據”


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM