Author : Ali0th
Date : 2019-4-22
經過上一篇部署單機 hadoop 之後,開始嘗試部署 hadoop 叢集。hadoop叢集最少需要三臺機,因為hdfs副本數最少為3。這裡我們使用四臺機子進行搭建。
本文盡求詳盡,包括所有步驟與問題的解決。可見目錄,有對遇到的bug的一些解決方法。可以看到我是如何踩坑過來的。
0.1. 目錄
[TOC]
0.2. 環境
CentOS release 6.4
openjdk version "1.8.0_201"
複製程式碼
0.3. 叢集裝置
準備四臺虛擬機器,一臺 master,三臺 slaver。master 作為NameNode、DataNode、ResourceManager、NodeManager,slave 均作為DataNode、NodeManager。
master : 192.168.192.164
slave1 : 192.168.192.165
slave2 : 192.168.192.167
slave3 : 192.168.192.166
複製程式碼
0.4. hostname 配置
由於 Hadoop 叢集內部有時需要通過主機名來進行相互通訊,因此我們需要保證每一臺機器的主機名都不相同。
vim /etc/hosts # 四臺機器都需要操作
192.168.192.164 master
192.168.192.165 slave1
192.168.192.167 slave2
192.168.192.166 slave3
reboot # 重啟
hostname # 檢視主機名
複製程式碼
/etc/hosts
與 /etc/sysconfig/network
的區別
0.5. 環境變數配置
vim /etc/profile
#java
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el6_10.x86_64
export CLASSPATH=.:$JAVA_HOME/jre/lib/rt.jar:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
export PATH=$PATH:$JAVA_HOME/bin
#hadoop
export HADOOP_HOME=/usr/local/hadoop
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
複製程式碼
0.6. ssh 免密登入
四臺機器均執行下面操作
ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
chmod 0600 ~/.ssh/authorized_keys
複製程式碼
每個機子上都操作一下,把公鑰拷貝到其他機器上
ssh-copy-id -i ~/.ssh/id_rsa.pub master
ssh-copy-id -i ~/.ssh/id_rsa.pub slave1
ssh-copy-id -i ~/.ssh/id_rsa.pub slave2
ssh-copy-id -i ~/.ssh/id_rsa.pub slave3
複製程式碼
測試配置成功
[mt@slave3 ~]$ ssh master
Last login: Tue Apr 16 17:51:47 2019 from slave2
[mt@master ~]$ ssh slave3
Last login: Tue Apr 16 17:32:12 2019 from 192.168.192.1
[mt@slave3 ~]$ ssh slave2
Last login: Tue Apr 16 17:51:42 2019 from master
[mt@slave2 ~]$ ssh slave3
Last login: Tue Apr 16 17:53:08 2019 from master
[mt@slave3 ~]$
複製程式碼
0.7. 配置時間當步
詳細配置見 :hadoop叢集時間同步
這裡試驗使用阿里雲時間
ntpdate ntp1.aliyun.com
複製程式碼
0.8. hadoop 配置檔案
共需要配置/opt/hadoop/hadoop-3.1.0/etc/hadoop/下的六個個檔案,分別是
hadoop-env.sh、core-site.xml、hdfs-site.xml、yarn-site.xml、mapred-site.xml、workers
cd $HADOOP_HOME cd etc/hadoop
0.8.1. 建立資料儲存目錄
- NameNode 資料存放目錄: /usr/local/data/hadoop/name
- SecondaryNameNode 資料存放目錄: /usr/local/data/hadoop/secondary
- DataNode 資料存放目錄: /usr/local/data/hadoop/data
- 臨時資料存放目錄: /usr/local/data/hadoop/tmp
- HADOOP_MAPRED_HOME :
sudo mkdir -p /usr/local/data/hadoop/name
sudo mkdir -p /usr/local/data/hadoop/secondary
sudo mkdir -p /usr/local/data/hadoop/data
sudo mkdir -p /usr/local/data/hadoop/tmp
複製程式碼
0.8.2. 配置 hadoop-env.sh
export JAVA_HOME=/usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el6_10.x86_64
export HDFS_NAMENODE_USER="root"
export HDFS_DATANODE_USER="root"
export HDFS_SECONDARYNAMENODE_USER="root"
export YARN_RESOURCEMANAGER_USER="root"
export YARN_NODEMANAGER_USER="root"
複製程式碼
0.8.3. core-site.xml hdfs-site.xml
接著分別編輯core-site.xml以及hdfs-site.xml配置檔案
vim core-site.xml # 增加如下內容
複製程式碼
hadoop配置檔案詳解系列(一)-core-site.xml篇
需要配置的是 name,tmp.dir
<configuration>
<property>
<name>fs.default.name</name>
<value>hdfs://master:8020</value>
<description>指定預設的訪問地址以及埠號</description>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/hadoop/data/</value>
<description>其它臨時目錄的父目錄,會被其它臨時目錄用到</description>
</property>
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
<description>在序列中使用的緩衝區大小</description>
</property>
</configuration>
複製程式碼
vim hdfs-site.xml # 增加如下內容
需要配置的是 replication、namenode 、datanode 、 web.
<configuration>
<property>
<name>dfs.replication</name>
<value>4</value>
<description>副本數,HDFS儲存時的備份數量</description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>/usr/local/data/hadoop/name</value>
<description>namenode臨時檔案所存放的目錄</description>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>/usr/local/data/hadoop/data</value>
<description>datanode臨時檔案所存放的目錄</description>
</property>
<property>
<name>dfs.namenode.http-address</name>
<value>master:50070</value>
<description>hdfs web 地址</description>
</property>
</configuration>
複製程式碼
0.8.4. 編輯 yarn-site.xml 配置檔案
vim yarn-site.xml # 增加如下內容
需要配置的是資料獲取方式, master 地址,(配置yarn 外部可訪問),關閉記憶體檢測(虛擬機器需要),容器可能會覆蓋的環境變數。
<configuration>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
<description>nomenodeManager獲取資料的方式是shuffle</description>
</property>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>master</value>
<description>指定Yarn的老大(ResourceManager)的地址</description>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>192.168.192.164:8088</value>
<description>配置 yarn 外部可訪問,(外網IP:埠)</description>
</property>
<property>
<name>yarn.nodemanager.env-whitelist</name>
<value> JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_HOME,PATH,LANG,TZ</value>
<description>容器可能會覆蓋的環境變數,而不是使用NodeManager的預設值</description>
</property>
<property>
<name>yarn.nodemanager.vmem-check-enabled</name>
<value>false</value>
<description>關閉記憶體檢測,虛擬機器需要,不配會報錯</description>
</property>
</configuration>
複製程式碼
0.8.5. 拷貝並編輯 MapReduce 的配置檔案
cp mapred-site.xml.template mapred-site.xml vim mapred-site.xml # 增加如下內容
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
<description>告訴hadoop以後MR(Map/Reduce)執行在YARN上</description>
</property>
<property>
<name>mapreduce.admin.user.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>可以設定AM【AppMaster】端的環境變數,如果上面缺少配置,
可能會造成mapreduce失敗</description>
</property>
<property>
<name>yarn.app.mapreduce.am.env</name>
<value>HADOOP_MAPRED_HOME=$HADOOP_HOME</value>
<description>可以設定AM【AppMaster】端的環境變數,如果上面缺少配置,
可能會造成mapreduce失敗</description>
</property>
</configuration>
複製程式碼
0.8.6. 配置從節點主機名
最後是配置從節點的主機名,如果沒有配置主機名的情況下就使用IP:
vim workers # hadoop3.0以後slaves更名為workers
slave1
slave2
slave3
複製程式碼
0.8.7. 配置分發
分發 hadoop 及其配置:
rsync -av /usr/local/hadoop slave1:/usr/local/hadoop
rsync -av /usr/local/hadoop slave2:/usr/local/hadoop
rsync -av /usr/local/hadoop slave3:/usr/local/hadoop
rsync -av ~/.bash_profile slave1:~/.bash_profile
rsync -av ~/.bash_profile slave2:~/.bash_profile
rsync -av ~/.bash_profile slave3:~/.bash_profile
複製程式碼
這裡我每個機子都裝了相同的 hadoop ,所以只要分發配置檔案即可:
rsync -av /usr/local/hadoop/etc/hadoop/* slave1:/usr/local/hadoop/etc/hadoop
rsync -av /usr/local/hadoop/etc/hadoop/* slave2:/usr/local/hadoop/etc/hadoop
rsync -av /usr/local/hadoop/etc/hadoop/* slave3:/usr/local/hadoop/etc/hadoop
rsync -av ~/.bash_profile slave1:~/.bash_profile
rsync -av ~/.bash_profile slave2:~/.bash_profile
rsync -av ~/.bash_profile slave3:~/.bash_profile
複製程式碼
在從節點執行:
source ~/.bash_profile
複製程式碼
0.9. 對NameNode做格式化
只需要在 master 執行即可。
hdfs namenode -format
複製程式碼
0.10. 啟動叢集
# 一次性啟動
start-all.sh
# 逐個元件啟動
start-dfs.sh
start-yarn.sh
複製程式碼
嘗試上傳檔案,成功。
0.11. 檢視程式與埠
檢視程式
[hadoop@master hadoop]$ jps
13794 NodeManager
13667 ResourceManager
14100 Jps
13143 NameNode
複製程式碼
[hadoop@master hadoop]$ ps -ef|grep java
hadoop 13143 1 7 02:10 ? 00:00:03 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el6_10.x86_64/bin/java -Dproc_namenode -Djava.library.path=/lib -Dhdfs.audit.logger=INFO,NullAppender -Dhadoop.security.logger=INFO,RFAS -Dyarn.log.dir=/usr/local/hadoop/logs -Dyarn.log.file=hadoop-hadoop-namenode-master.log -Dyarn.home.dir=/usr/local/hadoop -Dyarn.root.logger=INFO,console -Dhadoop.log.dir=/usr/local/hadoop/logs -Dhadoop.log.file=hadoop-hadoop-namenode-master.log -Dhadoop.home.dir=/usr/local/hadoop -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,RFA -Dhadoop.policy.file=hadoop-policy.xml org.apache.hadoop.hdfs.server.namenode.NameNode
hadoop 13667 1 18 02:10 pts/0 00:00:05 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el6_10.x86_64/bin/java -Dproc_resourcemanager -Djava.library.path=/usr/local/hadoop/lib -Dservice.libdir=/usr/local/hadoop/share/hadoop/yarn,/usr/local/hadoop/share/hadoop/yarn/lib,/usr/local/hadoop/share/hadoop/hdfs,/usr/local/hadoop/share/hadoop/hdfs/lib,/usr/local/hadoop/share/hadoop/common,/usr/local/hadoop/share/hadoop/common/lib -Dyarn.log.dir=/usr/local/hadoop/logs -Dyarn.log.file=hadoop-hadoop-resourcemanager-master.log -Dyarn.home.dir=/usr/local/hadoop -Dyarn.root.logger=INFO,console -Dhadoop.log.dir=/usr/local/hadoop/logs -Dhadoop.log.file=hadoop-hadoop-resourcemanager-master.log -Dhadoop.home.dir=/usr/local/hadoop -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,RFA -Dhadoop.policy.file=hadoop-policy.xml -Dhadoop.security.logger=INFO,NullAppender org.apache.hadoop.yarn.server.resourcemanager.ResourceManager
hadoop 13794 1 17 02:10 ? 00:00:04 /usr/lib/jvm/java-1.8.0-openjdk-1.8.0.201.b09-2.el6_10.x86_64/bin/java -Dproc_nodemanager -Djava.library.path=/lib -Dyarn.log.dir=/usr/local/hadoop/logs -Dyarn.log.file=hadoop-hadoop-nodemanager-master.log -Dyarn.home.dir=/usr/local/hadoop -Dyarn.root.logger=INFO,console -Dhadoop.log.dir=/usr/local/hadoop/logs -Dhadoop.log.file=hadoop-hadoop-nodemanager-master.log -Dhadoop.home.dir=/usr/local/hadoop -Dhadoop.id.str=hadoop -Dhadoop.root.logger=INFO,RFA -Dhadoop.policy.file=hadoop-policy.xml -Dhadoop.security.logger=INFO,NullAppender org.apache.hadoop.yarn.server.nodemanager.NodeManager
hadoop 14116 12870 0 02:11 pts/0 00:00:00 grep java
複製程式碼
檢視埠
netstat -tnlp
複製程式碼
0.12. 附錄
0.12.1. /etc/hosts
與 /etc/sysconfig/network
的區別
Linux系統在向DNS伺服器發出域名解析請求之前會查詢/etc/hosts檔案,如果裡面有相應的記錄,就會使用hosts裡面的記錄。/etc/hosts檔案通常裡面包含這一條記錄
network檔案,路徑:/etc/sysconfig/network,此檔案是針對本計算機的,是給計算機起的一個名字,是計算機的一個標識。
設定了 /etc/hosts
後重啟,/etc/rc.d/rc.sysinit
啟動指令碼會根據 eth0 的 ip 和 /etc/hosts
中的對應關係,把系統的 hostname
改成相應的名稱。
# In theory there should be no more than one network interface active
# this early in the boot process -- the one we're booting from.
# Use the network address to set the hostname of the client. This
# must be done even if we have local storage.
ipaddr=
if [ "$HOSTNAME" = "localhost" -o "$HOSTNAME" = "localhost.localdomain" ]; then
ipaddr=$(ip addr show to 0.0.0.0/0 scope global | awk '/[[:space:]]inet / { print gensub("/.*","","g",$2) }')
for ip in $ipaddr ; do
HOSTNAME=
eval $(ipcalc -h $ip 2>/dev/null)
[ -n "$HOSTNAME" ] && { hostname ${HOSTNAME} ; break; }
done
fi
# code ...
# Reread in network configuration data.
if [ -f /etc/sysconfig/network ]; then
. /etc/sysconfig/network
# Reset the hostname.
action $"Resetting hostname ${HOSTNAME}: " hostname ${HOSTNAME}
fi
複製程式碼
0.12.2. hadoop 3.0 與 2.0 的異同
官方介紹:hadoop.apache.org/docs/r3.0.0…
1 埠變化
Namenode ports: 50470 –> 9871, 50070 –> 9870, 8020 –> 9820
Secondary NN ports: 50091 –> 9869, 50090 –> 9868
Datanode ports: 50020 –> 9867, 50010 –> 9866, 50475 –> 9865, 50075 –> 9864
複製程式碼
2 節點配置檔案由slaves改為了workers
3 Hadoop3.0最低支援Java8
0.13. 問題與解決
問題:
雖然 hadoop 啟動了,但 Jps 不顯示 hadoop 程式資訊。
解決:
使用hdfs namenode -format格式化namenode時,會在namenode資料資料夾中儲存一個current/VERSION檔案,記錄clusterID,而datanode中儲存的current/VERSION檔案中的clustreID的值是第一次格式化儲存的clusterID,再次進行格式化時,就會生成新的clusterID,並儲存在namenode的current/VERSION檔案中,從而datanode和namenode之間的ID不一致。導致上述結果!
修改NameNode的VERSION檔案的clusterID的值。 namenode節點的路徑:/解壓路徑/hadoop/tmp/dfs/name/current datanode節點的路徑:/解壓路徑/hadoop/tmp/dfs/data/current/ more VERSION,可發現,datanode的clustreID與其他3臺datanode的clustreID不同。 vim VERSION修改clusterID的值與DataNode相同即可,並啟動。
問題:
Couldn't find datanode to write file. Forbidden
解決:
由於多次格式化hdfs,導致格式化hdfs的時候失敗(提示Reformat Y or N,輸入了Y也不能格式化成功),可能會導致namenode無法啟動,所以如果要重新格式化。清空 hadoop.tmp.dir配置項路徑下的tmp和logs 即可。
rm -rf (資料夾路徑)/*
rm -rf /usr/local/hadoop/data/*
rm -rf /usr/local/data/hadoop/name/*
rm -rf /usr/local/data/hadoop/data/*
複製程式碼
重新啟動後,發現問題依舊存在。
使用 hdfs dfsadmin -report
檢查。
[root@master hadoop]# hdfs dfsadmin -report
Configured Capacity: 0 (0 B)
Present Capacity: 0 (0 B)
DFS Remaining: 0 (0 B)
DFS Used: 0 (0 B)
DFS Used%: 0.00%
Replicated Blocks:
Under replicated blocks: 0
Blocks with corrupt replicas: 0
Missing blocks: 0
Missing blocks (with replication factor 1): 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
Erasure Coded Block Groups:
Low redundancy block groups: 0
Block groups with corrupt internal blocks: 0
Missing block groups: 0
Low redundancy blocks with highest priority to recover: 0
Pending deletion blocks: 0
複製程式碼
使用 tail -n 10 logs/hadoop-hadoop-datanode-slave1.log
檢視 slave1 的日誌。
[root@slave1 hadoop]# tail -n 10 logs/hadoop-hadoop-datanode-slave1.log
2019-04-18 02:18:15,895 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: localhost.localdomain/127.0.0.1:9000. Already tried 4 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2019-04-18 02:18:16,896 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: localhost.localdomain/127.0.0.1:9000. Already tried 5 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2019-04-18 02:18:17,900 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: localhost.localdomain/127.0.0.1:9000. Already tried 6 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2019-04-18 02:18:18,904 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: localhost.localdomain/127.0.0.1:9000. Already tried 7 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2019-04-18 02:18:19,906 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: localhost.localdomain/127.0.0.1:9000. Already tried 8 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS)
2019-04-18 02:18:20,788 ERROR org.apache.hadoop.hdfs.server.datanode.DataNode: RECEIVED SIGNAL 15: SIGTERM
2019-04-18 02:18:20,792 INFO org.apache.hadoop.hdfs.server.datanode.DataNode: SHUTDOWN_MSG:
/************************************************************
SHUTDOWN_MSG: Shutting down DataNode at slave1/192.168.192.165
************************************************************/
複製程式碼
發現 slave1 連線不上 master,發現是因為 slave1 以為 localhost.localdomain 才是 master,發現 slave1 的配置檔案中,core-site.xml
如下,配置是 hdfs://localhost.localdomain:9000
。
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://localhost.localdomain:9000</value>
<description>hdfs內部通訊訪問地址</description>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/usr/local/data/hadoop/tmp</value>
</property>
</configuration>
複製程式碼
原來是配置沒有分發成功,重新進行分發即可。
問題:
Permission denied: user=dr.who, access=WRITE, inode="/":root:supergroup:drwxr-xr-x
解決:
hadoop fs -chmod 777 /
複製程式碼
問題:
Couldn't upload the file 從人工智慧到TensorFlow.pdf.
解決:
應該是在別的機子訪問時,沒有配置host地址解析造成的。