對於初學者來說,Hadoop的搭建與配置有兩個核心:
- HDFS(hadoop distribute file system ,hadoop 分佈式文件系統)
hdfs是整個hadoop生態的基礎,它具有很多優點和特性,不再多提,我們的目的是讓hdfs在我們的集羣上跑起來。 - Yarn(Yet Another Resource Negotiator,另一種資源協調者)
反正是一次大改版出現的事物,從那以後不再有jobTracker這樣的東西了。簡而言之yarn把jobTracker的工作分解了,爲的就是不讓老版本的namenode壓力過大而進行的重新設計優化。
讀者應該自行了解過上面兩項內容,這裏不再贅述,我們直接進行集羣的配置與搭建。
Hadoop集羣的搭建
1. 準備工作
我使用的是三臺物理設備,包括一臺我常用的筆記本電腦和一個老舊筆記本電腦和樹莓派3b+組成的三節點集羣,我現在經常用的電腦作爲主節點(namenode),舊筆記本和樹莓派作爲slave(datanode)。
linux發行版本的選擇: 我在兩臺筆記本上選擇的是xubuntu,我覺得這個界面挺清爽的,centOS也是推薦使用的發行版本,樹莓派就是安裝官方的操作系統Raspbian就好了,不過有點不爽的就是官方發佈的只有32位,樹莓派3b+是arm64啊喂。(只好湊合用)
說明: 我會用namenode來代表主節點,如無明確說明,datanode將代表兩個從節點,datanode2代表從節點2(樹莓派),並且如無說明我們都默認在主節點上執行命令。雖然習慣不好,但是我都是默認用root來操作。XD
於是就有了下圖。
系統安裝不是本文的重點,最好能在安裝系統時直接設定好主機名省的在修改。然後配置IP,這點我也不是很懂,反正IPv4手動配置就完了。
使用 ifconfig和env來檢查自己的ip和主機名是否正確
不重啓修改linux主機名的方法:
vim /etc/sysconfig/network
#修改
HOSTNAME=主機名
#然後執行命令
hostname -b 主機名
緊接着我們配置一下hosts這個文件,這個文件的作用是在本地將主機名解析成ip地址我的hosts內容是這樣的,使用如下vim編輯文件 /etc/hosts
vim /etc/hosts
...
127.0.0.1 localhost
192.168.1.103 lijiale-namenode
192.168.1.104 lijiale-datanode
192.168.1.105 lijiale-datanode2
具體作用就是當你想要ssh連接一臺節點時,ssh 192.168.1.103
與ssh lijiale-namenode
的效果是一樣的。
接下來我們會發現在使用命令ssh時會出現一些問題,比如connection refused,或者是你明明輸入的正確密碼卻就是不給你通過。但是這些都可以百度解決,不是本文的主要內容。
解決了ssh的問題後,我們是可以直接用ssh 主機名
來遠程訪問一個節點的,這時候就介紹一個非常方便的命令scp
,具體事宜大家可以man一下看看,它就是基於ssh協議實現的,所以你必須要先搞定ssh服務。
你可以將它理解爲命令cp
的加強版,它允許我們將文件遠程複製到其他節點上,我們就用這個命令來將剛剛我們編輯好的hosts文件直接發送給兩個datanode
我們在namenode上執行命令(如無說明我們都默認在主節點上操作)
scp /etc/hosts lijiale-datanode:/etc/hosts
scp /etc/hosts lijiale-datanode:/etc/hosts
你會發現每次執行上述命令時都會要求你輸入目標節點的密碼,這是因爲我們集羣之間還沒有實現免密碼登錄,這肯定是不行的,接下來我們就實現集羣搭建的第一個難題,集羣間的ssh免密登陸。
2.集羣間ssh免密登陸(關鍵)
到目前爲止好像都還沒hadoop什麼事,一直在搗鼓linux,別急啦準備工作是必須的,你當然可以跳過這一步。但是相信我,如果你跳過這步直接進行後面的內容,以後你輸密碼會輸到你崩潰的。
我突然覺得有必要寫一篇關於ssh的學習總結。(我也有些迷。)
大概描述一下接下來的操作在幹什麼:
所謂免密登陸,靠的就是密鑰驗證, 公鑰和私鑰都是成對出現的。 當我拿着私鑰去訪問擁有私鑰對應公鑰的計算機時,我就可以直接登陸而無需密碼驗證。
所以我們做的事情就是在每臺機器上生成這樣一對密鑰,再把每臺機器上的公鑰都集中在一個文件中,最後再分發到每臺機器上。這樣每臺機器在互相訪問時,都能找到自己私鑰對應的公鑰,所以就都可以免密碼登錄了。
接下來這樣就等於實現了免密登陸。
由上圖可以很清楚的明白免密登陸的原理。
如果理解了上面所說的,接下來的動作也就很容易明白了。
-
生成密鑰
每個節點都要執行如下命令ssh-keygen -t rsa -P '' -f /root/.ssh/id_rsa
執行後你會看到一個奇怪的矩形,反正我也不懂,你只需要知道這是獨一無二的就行。
這時
/root/.ssh
目錄下會有兩個文件id_rsa.pub
和id_rsa
,這顯然就是我們要的公鑰(.pub)和私鑰了。 -
生成含有本地公鑰的authorized_keys文件
這一步就是關鍵了,這是我們上圖中綠色標註的文件,系統中本身是有這樣一個文件 的。遠程主機將請求登錄的用戶的公鑰保存在登陸後的用戶主目錄下的$HOME/.ssh/
下,而我們一直用root操作,所以操作目錄理所應當爲/root/.ssh/
執行如下命令:cd /root/.ssh/ cat id_rsa.pub >>authorized_keys chmod 600 authorized_keys
如果你理解了上面說的,你就應該知道,這一步我們將自己的公鑰保存在了authorized_keys文件中,這樣一來我們就能免密登陸我自己。
ssh localhost #正常情況下此時是不需要輸入密碼的
同樣的操作,我們需要在另外兩個機器上進行,並且驗證它們都可以免密碼登錄自己。
-
生成含有所有節點公鑰的authorized_keys文件
到這一步我們已經成功了大半,如題所說,我們需要將各個節點的公鑰集中在一起, 好在有現成的命令可以用。我們先將所有節點的公鑰集中在主節點的authorized_keys上。 需要分別在兩臺從節點上執行命令:
#在lijiale-datanode節點執行命令 ssh-copy-id -i /root/.ssh/id_rsa.pub lijiale-namenode #在lijiale-datanode2節點執行命令 ssh-copy-id -i /root/.ssh/id_rsa.pub lijiale-namenode
大功告成,你會發現現在任何一個節點訪問主節點時都不需要密碼,因爲主節點的authorized_keys中,已經保存了三個公鑰了。
-
分發authorized_keys
現在的主節點上的authorized_keys文件就像一個萬能牌,它放在哪,去哪就不需要密碼。
繼續在主節點使用scp覆蓋剩餘兩個從節點的authorized_keys。scp /root/.ssh/authorized_keys lijiale-datanode:/root/.ssh/authorized_keys scp /root/.ssh/authorized_keys lijiale-datanode2:/root/.ssh/authorized_keys
至此,節點的ssh免密碼通信配置完成。
3.Hadoop的安裝
Linux下軟件的安裝向來比較簡單,解壓就完了。
我們需要的安裝包如下:
- hadoop-2.2.0-x64.tar.gz
- JDK1.8(有的操作系統安裝時自帶jdk)
這裏附上hadoop-2.2.0-x64.tar.gz的資源鏈接
鏈接:https://pan.baidu.com/s/1MOStB3zHaXb69gH9B-alTw
提取碼:y8ps
我的安裝路徑如下:
Hadoop2.2解壓在/home/hadoop/hadoop2.2
jdk解壓在/usr/local/jdk1.8
小提示:解壓出來的文件名很長,這裏可以改的短一點方便後面的配置少打點字。
hadoop-2.2.0-x64.tar.gz在解壓出來後並不完美,除了我們要將它改名爲hadoop2.2以圖方便外,還要在它下面手動創建以下文件夾(新版本可能不再需要這麼幹,畢竟我這是2.2版本)爲了更清晰的展示它的目錄結構,這裏我就用命令行創建
mkdir /home/hadoop/hadoop2.2/hdfs
mkdir /home/hadoop/hadoop2.2/hdfs/name
mkdir /home/hadoop/hadoop2.2/hdfs/data
mkdir /home/hadoop/hadoop2.2/logs
mkdir /home/hadoop/hadoop2.2/tmp
接下來就需要將hadoop命令寫入環境變量,如果你係統中沒有安裝Java,那你還需要配置以下jdk的環境變量。
使用vim打開profile文件
vim /etc/profile
在profile後追加如下內容
export JAVA_HOME=/usr/local/jdk1.8
export ClASSPATH=.:$JAVA_HOME/lib/tools.jar:$JAVA_HOME/lib/dt.jar
export HADOOP_HOME=/home/hadoop/hadoop2.2
export PATH=.:$HADOOP_HOME/sbin:$HADOOP_HOME/bin:$JAVA_HOME/bin:$PATH
export HADOOP_LOG_DIR=/home/hadoop/hadoop2.2/logs
export YARN_LOG_DIR=$HADOOP_LOG_DIR
注意 :
.
都不能少,一字不落的寫在文件最後。
profile文件很關鍵,要是不小心改壞了系統也會癱瘓,所以必須謹慎操作。
4.Hadoop的配置文件
我們需要修改的配置文件有8個,它們都在/home/hadoop/hadoop2.2/etc/hadoop
下,我將它們分爲三類
- 環境變量導入
- 關鍵配置文件
- core-site.xml
- hdfs-site.xml
- mapred-site.xml
- yarn-site.xml
- slave標識文件
- slaves
其中環境變量導入下面的三個文件,其實內容不需要變化太多,你會發現裏面的JAVA_HOME都是被註釋的,你只需要取消註釋(刪去#)將你的JAVA_HOME寫到後面即可(“=”後不要加空格)。這裏就不在給出修改後的配置文件
關鍵配置文件中很多都是空的,那是Hadoop要求用戶必須做出的配置選項,下面依次列出我的配置文件(內含註釋)。
core-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
略
-->
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://lijiale-namenode:9000/</value>
<description>設定 主結點的主機名以及端口</description>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/home/hadoop/hadoop2.2/tmp</value>
<description>存儲臨時文件的目錄</description>
</property>
<property>
<name>hadoop.proxyuser.hadoop.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.hadoop.groups</name>
<value>*</value>
</property>
</configuration>
hdfs-site.xml
<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
略
-->
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>dfs.namenode.http-address</name>
<value>lijiale-namenode:50070</value>
<description>NameNode地址和端口</description>
</property>
<property>
<name>dfs.namenode.secondary.http-address</name>
<value>lijiale-datanode:50090</value>
<description>SecondNameNode 地址和端口</description>
</property>
<property>
<name>dfs.replication</name>
<value>3</value>
<description>設定HDFS存儲文件的副本數,默認爲3</description>
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///home/hadoop/hadoop2.2/hdfs/name</value>
<description>namenode用來持續存儲命名空間和交換日誌的本地文件系統路徑</description>
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file:///home/hadoop/hadoop2.2/hdfs/data</value>
<description>DataNode在本地存儲塊文件目錄的列表</description>
</property>
<property>
<name>dfs.namenode.checkpoint.dir</name>
<value>file:///home/hadoop/hadoop2.2/hdfs/namesecondary</value>
<description>設置secondarynamenode存儲臨時鏡像的本地文件系統路徑,如果這是一個用逗號分隔的文件列表,則鏡像將會冗餘複製到所有目錄</description>
</property>
<property>
<name>dfs.webhdfs.enabled</name>
<value>true</value>
<description>是否允許網頁瀏覽HDFS文件</description>
</property>
<property>
<name>dfs.stream-buffer-size</name>
<value>131072</value>
<description>默認是4KB,作爲Hadoop緩衝區,用於Hadoop讀HDFS的文件和寫HDFS的文件,還有map的輸出都用到這個緩衝區容量,對於現在的硬件,可以設置128KB(131072),甚至是1MB(太大了map和readuce任務可能會內存溢出)</description>
</property>
</configuration>
mapred-site.xml(這個文件原名爲mapred-sire.xml.template,需要刪掉.template後綴)
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="configuration.xsl"?>
<!--
略
-->
<!-- Put site-specific property overrides in this file. -->
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>lijiale-namenode:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>lijiale-namenode:19888</value>
</property>
</configuration>
yarn-site.xml
<?xml version="1.0"?>
<!--
略
-->
<configuration>
<property>
<name>yarn.resourcemanager.hostname</name>
<value>lijiale-namenode</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
<value>org.apache.hadoop.mapred.ShuffleHandler</value>
</property>
<property>
<name>yarn.resourcemanager,address</name>
<value>lijiale-namenode:8032</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>lijiale-namenode:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>lijiale-namenode:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>lijiale-namenode:8033</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>lijiale-namenode:8088</value>
</property>
</configuration>
slaves這個文件,只寫主機名,被寫入的主機名將作爲從節點,對於我的集羣,我的slaves文件內容爲
lijiale-datanode
lijiale-datanode2
分別爲我的老筆記本和樹莓派主機名。
回顧一下,第3步hadoop的安裝和第4步hadoop的配置,目前還都是在主節點上進行的操作,同樣的操作我們需要在另外兩個從節點上再來一次。所有的環境變量,目錄結構,配置文件內容,對於我這三臺機器來講都是相同的。
小提示:你可以把第4步中提到的8個配置文件都提取出來,然後一起扔到/home/hadoop/hadoop2.2/etc/hadoop
下全部替換即可完成第4步。
也就是說第3步,第4步分別在三臺機器上完整再做一遍。 都完成後,我們終於可以進入最後一步了。
5.格式化並啓動hadoop
在主節點執行命令:
hadoop namenode –format
如果看到有返回 Exiting with status: 0
就證明格式化成功。
接着啓動hdfs和yarn
主節點依次執行命令:
start-dfs.sh
start-yarn.sh
執行完畢後在各個節點執行命令 jps
如能分別看到如下結果則證明hdfs和yarn已經在你的集羣上跑起來了。
之所以沒用實際操作截圖是因爲,我覺的這樣畫圖的方式更加直觀,也加深了我的理解。
接下來我們就能跑一個hadoop自帶的詞頻統計程序了
Wordcount 運行(英文)
它是Hadoop自帶的一個集羣驗證程序,可以對英文進行詞頻統計。
HDFS是一套獨立於操作系統的文件系統,在被格式化後其實就是一個空的/
,
因爲hadoop生態下的所有軟件幾乎都是基於HDFS運作的,WordCount案例也不例外,我們需要先將一份文件提交到HDFS上中,在這之前創建文件夾等操作其實都無太大變化。
#在HDFS上創建文件夾,用於存放待統計的文件
hdfs dfs -mkdir /data
hdfs dfs -mkdir /data/wordcount #這裏應該有參數可以遞歸創建,我沒有仔細查過
#output文件夾用於存放輸出結構
hdfs dfs -mkdir /output
#向HDFS上傳待統計文件
hdfs dfs -put /home/hadoop/hadoop2.2/etc/hadoop/core_site.xml
#運行wordcount案例 執行如下命令
hadoop jar /home/hadoop/hadoop2.2/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.2.0.jar wordcount /data/wordcount /output/wordcount
我親測成功執行了。
可以在瀏覽器中輸入lijiale-namenode:8080找到作業成功運行的記錄。
如果覺得太快了感受不到程序在跑的快樂,那就可以放多個文件,重新執行上述命令,但是要記得手動刪除目錄/output/wordcount
否則會報錯。