這幾天因爲學習需要搭建了一個由3個節點組成的hadoop和spark分佈式集羣,做記錄如下(已生成目錄,可按需查看)。
集羣搭建環境及安裝軟件版本
- centos6
- jdk1.8.0_161
- hadoop2.7.5
- Spark2.3.0
- Scala-2.11.8
- Anaconda2-5.1.0
- IDEA-2018.1
搭建分佈式集羣的幾個主要步驟:
- 下載好搭建分佈式集羣的軟件
- 修改集羣各個虛機名稱
- 網絡配置:修改集羣各個虛機hosts文件
- 配置SSH:使得節點間可以互相免密登錄
- 安裝jdk:在集羣的各個虛機上安裝jdk並配置相應jdk環境變量
- 安裝hadoop:先在主節點上安裝hadoop,修改完配置文件後再將主節點的hadoop文件映射至從節點並配置好各節點相應環境變量
- 安裝spark:先在主節點上安裝spark,修改完配置文件conf後再將主節點的spark文件映射至從節點並配置好各節點相應環境變量
- 安裝scala:在集羣的各個虛機上安裝scala並配置相應scala環境變量
- 安裝Anaconda2:在集羣的各個虛機上安裝Anaconda2並配置相應Anaconda2環境變量
- 安裝IDEA-2018.1.1.tar.gz:在主節點上安裝IDEA
- 因爲是初次安裝,所以採取了在各個節點安裝jdk、hadoop、spark、scala、Anaconda2和配置相應環境變量的較繁瑣安裝方式,但實際上步驟5-9完全可以只在主機上進行然後再將安裝好的jdk、hadoop、spark、scala、Anaconda2打包映射到各個從節點,並用主節點的環境變量文件profile.txt替換其他節點的方式安裝。
一、修改集羣各個虛機的名稱
因爲拿到手的虛機虛機名不符合自己的開發需求需要更改,加之虛擬機名會影響分佈式集羣環境變量的配置,所以把修改集羣虛機名放在搭建分佈式平臺的第一步。期望修改後的虛機名爲:主節點:Master,從節點1:slave1, 從節點2:slave2。修改的步驟如下(以主節點爲例):
- 打開在虛機根路徑下的/etc/sysconfig的network 文件,打開方式可爲在指令行輸入
文件打開後將第二行文件修改爲HOSTNAME=Master,修後侯如下所示:vim /etc/sysconfig/network - 其他節點的虛機名按照步驟1修改。
- 將個節點的虛機的network文件修改後,用指令重啓集羣,重啓指令爲 shutdown -r now ,重啓後新的虛機名開始起效。(這一步的重啓也可以等到第二步的網絡配置完成後)
注:如果你的虛機集羣是遠程登錄的也可以直接用指令重啓,不需要集羣物理機管理者授權,重啓後過一段時間便可以重新連接到集羣。 - 重啓虛機後登陸centos系統,打開終端進入shell命令提示符狀態,顯示如下內容表示修改成功:
注:我的集羣centos版本和配置相互一致,且都是以root賬戶登錄。[root@Master ~]#
二、網絡配置
修改集羣中個節點的hosts文件,使得節點間可以相互ping通,爲配置SSH做準備。修改步驟和內容如下:
- 打開Master節點的hosts文件,指令如下:
[root@Master ~]# vim /etc/hosts - 在Master節點的hosts文件中增加slave1、slave2的IP和主機映射關係,修改後如下所示:
- 參照Master節將slave1、slave2的hosts文件修改成Master節點的hosts文件一樣。
- 重啓虛擬機羣
- 在Master節點測試是否能ping 通slave1、slave2,測試指令如下:
ping通slave1後如下示:ping slave1 -c 3
ping slave2 -c 3
ping通slave2後如下示: - 其他節點的ping測試參考Master節點
三、配置SSH
使得集羣間可以實現免密登錄,從而使得集羣中的Hadoop名稱節點(Namenode)可以啓動集羣中所有機器的Hadoop守護進程。
3.3 SSH的免密配置:
- centos默認安裝了SSH的服務端,在進行SSH的免密配置之前先需要在集羣的各個虛機上先安裝好SSH的客戶端。SSH客戶端的安裝指令爲:
# yum install openssh-server - 生成私鑰和公鑰:在三個節點中使用如下命令生成私鑰和公鑰
執行後輸出如下圖示:# ssh-keygen -t ras #執行該命令後,遇到提示信息,一直按Enter鍵就可以
命令執行完畢後,可以在~/.ssh路徑下看到兩個文件:id-rsa和id_rsa.pub,其中,以.pub結尾的是公鑰。把公鑰命名爲authorized_keys_master.pub,使用的命令如下:
同樣地將他其他兩個節點的公鑰名命名爲authorized_keys_slave1.pub、authorized_keys_slave2.pub。# cd ~/.ssh # mv id_rsa.pub authorized_keys_master.pub - 合併公鑰信息:把兩個節點(slave1和slave2)的公鑰使用scp指令映射Master節點的~/.ssh目錄。
使用cat指令把3個節點的公鑰信息保存到authorized_keys文件,指令如下:
# scp authorized_keys_slave1.pub root@Master:~./ssh #在節點slave1上執行# scp authorized_keys_slave2.pub root@Master:~/.ssh #在節點slave2上執行
合併完成後,查看文件的內容下所示:$ cat authorized_keys_master.pub >>authorized_keys $ cat authorized_keys_slave1.pub >>authorized_keys $ cat authorized_keys_slave2.pub >>authorized_keys
完成合並後再使用scp命令把authorized_keys 密碼文件發送到slave1和slave2節點,命令如下:
# scp authorized_keys root@slave1:~./ssh # scp authorized_keys root@slave2:~/.ssh
傳輸完畢後,需要在3臺節點使用如下設置authorized_keys 的讀寫權限:
# cd ~/.ssh # chmod 400 authorized_keys 4. 驗證免密登錄:在各節點中使用ssh命名,驗證他們之間是否可以免密登錄:
$ssh Master $ssh slave1 $ssh slave2 配置成功免密登錄效果如下:
四、安裝jdk
hadoop和scala都是基於jvm虛擬機運行,因此我們需要給各個節點的虛機安裝上jdk併爲其配置好相應環境變量,此處以主節點安裝爲例,其他節點與主節點安裝及配置方式一致。
- 在/opt路徑下新建一個文件夾app並將集羣軟件(包括hadoop、spark等)全部在/opt/app路徑下,指令如下:
# mkdir /opt/app - 將jdk解壓到app路徑
# cd /opt/app tar -zxvf ./jdk-8u161-linux-x64.tar.gz 打開profile文件,添加jdk環境變量
在文件中添加環境變量如下:# vim /etc/profile export JAVA_HOME=/opt/app/jdk1.8.0_161 export PATH=$JAVA_HOME/bin:$PATH 用指令使得jdk的環境變量生效
# suorce /etc/proflle
五、安裝hadoop
- 在主節點中的/opt/app路徑下將hadoop安裝包解壓,並將解壓後的文件夾重命名爲hadoop
# cd /opt/app
# tar -zxvf ./hadoop-2.7.5.tar.gz
# mv hadoop2.7.5 hadoop - 修改hadoop路徑下的/etc/hadoop下的core-site.xml、hdfs-site.xml、mapreduce-site.xml、yarn-site.xml、slaves五個文件
1)修改core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://Master:9000</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/opt/app/hadoop/tmp</value> #臨時文件路徑
</property>
<property>
<name>hadoop.proxyuser.root.hosts</name>
<value>*</value>
</property>
<property>
<name>hadoop.proxyuser.root.groups</name>
<value>*</value>
</property>
</configuration>
2)修改hdfs-site.xml<configuration>
<property>
<name>dfs.replication</name>
<value>2</value> #備份數爲2
</property>
<property>
<name>dfs.namenode.name.dir</name>
<value>file:///opt/app/hadoop/tmp/dfs/namenode</value> #名稱節點路徑
</property>
<property>
<name>dfs.datanode.data.dir</name>
<value>file://opt/app/hadoop/tmp/dfs/datanode</value> #數字節點路徑
</property>
<property>
<name>dfs.http.address</name>
<value>Master:50070</value> #設爲主節點主機名:Master
</property>
</configuration>
3)修改mapreduce-site.xml<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<name>mapreduce.jobhistory.address</name>
<value>Master:10020</value>
</property>
<property>
<name>mapreduce.jobhistory.webapp.address</name>
<value>Master:19888</value>
</property>
</configuration>
4)yarn-site.xml<configuration>
<!-- Site specific YARN configuration properties -->
<property>
<name>yarn.resourcemanager.hostname</name>
<value>Master</value>
</property>
<property>
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<name>yarn.log-aggregation.retain-seconds</name>
<value>86400</value>
</property>
<property>
<name>yarn.nodemanager.resource.memory-mb</name>
<value>6144</value>
</property>
<property>
<name>yarn.nodemanager.local-dirs</name>
<value>/opt/app/hadoop/tmp/localdir</value>
</property>
<property>
<name>yarn.nodemanager.log-dirs</name>
<value>/opt/app/hadoop/tmp/logdir</value>
</property>
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<name>yarn.nodemanager.vmem-pmem-ratio</name>
<value>10</value>
</property>
<property>
<name>yarn.log.server.url</name>
<value>http://Master:19888/jobhistory/logs</value>
</property>
</configuration>
5)修改slavesMaster
slave1
slave2
- 配置環境變量
export HADOOP_HOME=/opt/app/hadoop export PATH=$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH - 用指令使得環境變量生效
# source /etc/profile - 將主節點上的/opt/app/hadoop文件夾映射到各個節點上。
# cd /opt/app # tar -zcf ./hadoop.master.tar.gz ./hadoop 將/opt/app/hadoop 文件夾壓縮並命名爲hadoop.master.tar.gz # scp ./hadoop.master.tar.gz slave1:/opt/app # scp ./hadoop.master.tar.gz slave2:/opt/app - 在各個節點上的/opt/app路徑的hadoop.master.tar.gz 解壓所在路徑(以slave1爲例)
各節點的環境變量配置參照主節點# cd /opt/app # tar -zxvf ./hadoop/master.tar.gz # chown -R root /opt/app/hadoop #給解壓後的hadoop文件夾以可讀寫權限 - hadoop成功安裝測試
在各節點上輸入下面的指令若出現hadoop版本信息則安裝hadoop成功# hadoop version - 啓動hadoop集羣
在主節點上執行下列指令
成功啓動時下示:# hdfs dfs namenode -format #首次啓動需要格式化主節點上的名稱節點 # start-dfs.sh # start-yarn.sh
Master節點:
slave1節點:
slave2節點: - hadoop集羣安裝後啓動遇到的異常
異常1:啓動hadoop集羣失敗,如下圖示
異常原因:主節點的hosts文件裏的從節點2 IP地址輸入錯誤
因爲當時顯示是slave2節點異常,結果一直在slave2節點上查找錯誤,找了許久沒有找到,近乎絕望之際才發現是主節點上的hosts文件配置錯誤。在這裏謹記,集羣配置牽一髮而動全身,出現錯誤時記得把各個節點的上的可能相關異常源都審查一遍。異常2:訪問hdfs失敗,異常如下所示
異常原因:未關閉集羣防火牆(不知爲何看師兄的集羣未關閉集羣也能正常訪問hdfs,這裏表示困惑)
解決方案:修改/集羣etc/selinux/config文件如下
重啓集羣后,在各節點指令終端輸入如下指令,如果顯示"iptables: Firewall is not running"則表示關閉防火牆成功
service iptables status |
六、安裝scala
scala是spark的底層語言,用scala開發spark應用是最爲高效的。雖然spark自帶scala,但是卻不便於我們在IDA工具上進行開發應用,所以這裏爲spark集羣需要安裝好scala。- 將scala解壓到app路徑
# cd /opt/app
# tar -zxvf ./scala-2.11.8.tgz
打開profile文件,添加scala環境變量
# vim /etc/profile
- 在文件中添加環境變量如下:
export SCALA_HOME=/opt/app/scala-2.11.8 export PATH=$SCALA_HOME/bin:$PATH 用指令使得scala的環境變量生效
# suorce /etc/proflle
- 其他節點scala安裝參照主節點
七、安裝Spark
- 在主節點中的/opt/app路徑下將spark安裝包解壓,並將解壓文件夾重命名爲spark,解壓及重命名指令如下
# cd /opt/app # tar -zxvf ./spark-2.3.0-bin-hadoop2.7.tgz # mv spark-2.3.0-bin-hadoop2.7.tgz spark |
- 修改解壓後spark/conf路徑下的slaves、spark-env.sh及spark-deflauts.conf文件
- 配置conf/slaves
該配置文件用於設置集羣中運行Worker節點信息,需要注意的是Master節點不僅運行master進程,也運行worker進程。slaves文件配置如下:Master #主節點名 slave1 #從節點1名 slave2 #從節點2名
- 配置conf/spark-env.sh
該配置文件用於設置spark運行環境,默認的spark/conf目錄中沒有spark-env.sh文件,需要通過複製或者修改spark-env.sh.template進行創建。使用的命令如下:
然後在打開的spark-env.sh文件中加入如下內容,設置Master爲主節點,# cd /app/opt/spark/conf # cp spark-env.sh.template spark-env.sh # vim spark-env.sh
export JAVA_HOME=/opt/app/jdk1.8.0_161 export SCALA_HOME=/opt/app/scala-2.11.8 export SPARK_MASTER_IP=Master export HADOOP_CONF_DIR=/opt/app/hadoop/etc/hadoop
- 配置conf/spark-deflauts.conf文件
spark.yarn.historyServer.address=Master:18080 spark.history.ui.port=18080 #HistoryServer的web端口 spark.eventLog.enabled=true #是否記錄Spark事件,用於應用程序在完成後重構webUI spark.eventLog.dir=hdfs://Master:9000/tmp/spark/events #保存日誌相關信息的路徑,可以是hdfs://開頭的HDFS路徑, #也可以是file://開頭的本地路徑,都需要提前創建 spark.history.fs.logDirectory=hdfs://Master:9000/tmp/spark/event
- 配置/etv/profile
打開環境變量配置文件
加入spark環境變量配置如下# vim /etv/profile
export SPARK_HOME=/opt/app/spark export PATH=$SPARK_HOME/bin:SPARK_HOME/sbin:PATH
執行環境變量生效指令
# source /etc/profile
分發Spark目錄至分節點上
# cd /opt/app # scp ./spark root@slave1:/opt/app/spark # scp ./spark root@slave2:/opt/app/spark
- 啓動Spark
在主節點輸入如下指令:
啓動成功後jps後可看到# start-master.sh # start-slaves.sh
Master節點:
slave1節點:
slave1節點: - 使用spark-shell運行一個spark程序實例
首先啓動spark-shell,在任意路徑輸入如下指令
在spark-shell上運行一個簡單的wordcount程序# spark-shell
結果如下:scals-> val rdd=sc.textFile("file:///opt/app/spark/README.md") scala-> val wordcount = rdd.flatMap(_.split("\\s+")).map(x=>(x,1)).reduceByKey(_+_) scala-> val wordsort = wordcount.map{x=>(x._2,x._1)}.sortByKey(false).map(x=>(x._2,x._1)) scala-> wordsort.take(10)
啓動異常
啓動spark-shell出現"ERROR SparkContext :Error initializing SparkContext."
報出:"java.io.FileNotFoundExceptio:File does not exist :hdfs:Master:9000/tmp/spark/events"異常說明沒有在hdfs上創建tmp/spark/events路徑,創建後重新啓動spark-shell再運行上面程序時則可正常運行。
異常警示如下:
八、安裝Anaconda
在每個節點進行下列操作- 執行安裝指令,指令如下:
安裝時,第一個詢問回覆yes,第二個詢問爲Anaconda路徑,這裏我們不選擇默認路徑改爲[root/anaconda2]>>/opt/app/anaconda,第三個詢問爲是否將Anaconda路徑配置在本地環境變量./root/.bashrc,由於我們是把環境變量統一配置在/etc/profile中,所有也選擇nocd /opt/app bash ./Anaconda2-5.1.0-Linux-x86-64.sh
具體安裝流程如下:
- 配置環境變量
打開環境變量文件
添加如下語句vim /etc/profile
export ANACONDA2_HOME=/opt/app/anaconda2 export PATH=$ANACONDA2_HOME/bin:$PATH
執行環境變量生效指令
source /etc/profile
九、安裝IDEA
- 代碼調試基本在主節點進行,故只需在主節點安裝IDEA即可,安裝指令如下
cd /opt/app
basd ./IDEA-2018.1.1.tar.gz
- 配置環境變量
打開環境變量文件
在環境變量文件中加入如下語句:# vim /etc/profile
export IDEA_HOME=/opt/app/IDEA export PATH=$IDEA_HOME/bin:$PATH
- 打開idea指令
任意環境輸入:# idea.sh
至此,一個可應用於實際開發的hadoop,spark分佈式平臺搭建成功。