虛擬機器CentOS 7.5.1804下無外網Hadoop HA叢集安裝
網上有很多Hadoop HA叢集安裝的資料,我當時安裝也是參考了官方文件和這些資料才安裝成功的。由於使用的環境和軟體版本可能有所不同,且因工作環境網路所限無法連線外網,加之記錄一下自己的安裝過程,不枉花費時間來研究Hadoop環境的搭建,故作此文章。
一、叢集架構表
IP地址 |
主機名 |
角色 |
埠 |
192.168.52.2 |
namenode |
NameNode,JournalNode,ZKFC, ResourceManager,MapReduce歷史伺服器 |
hdfs-site(http://namenode:50070) yarn-site(http://namenode:8088) |
192.168.52.3 |
datanode1 |
NameNode,JournalNode,ZKFC,DataNode,ZooKepper |
hdfs-site(http://datanode1:50070) |
192.168.52.4 |
datanode2 |
ResourceManager,JournalNode,DataNode,ZooKepper |
yarn-site(http://namenode:8088) |
192.168.52.5 |
datanode3 |
DataNode,ZooKepper |
注:ZKFC並不依賴ZooKeeper,所以無須在namenode上安裝ZooKeeper。
二、作業系統環境及軟體版本(都是當時的最新版本)
我安裝的是1臺虛擬機器,克隆了3個,具體安裝過程在此不加贅述。
1、CentOS 7.5.1804 ,最小化安裝
2、Hadoop 2.9.2
3、JDK8(最開始裝的JDK11,屢試不行,去官網查版本支援,發現不支援JAVA 11,於是下的JDK8)
4、ZooKeeper-3.4.13
5、ntpdate或者CentOS 7預設的chrony時間同步,二選一
6、psmisc(很重要,fuser指令所需的包,後面會詳細說明)
cat /etc/redhat-release
hadoop -version
java -version
alternatives --config java (配置java多版本環境)
yum install psmisc
三、安裝過程
1、配置主機名
1.1 分別在4臺伺服器上用root賬戶執行:
hostnamectl set-hostname namenode
hostnamectl set-hostname datanode1
hostnamectl set-hostname datanode2
hostnamectl set-hostname datanode3
1.2 在4臺伺服器上用root使用者執行(亦可在namenode上修改,然後scp複製到其他主機上):
vi /etc/hosts
然後在文字末尾插入如下4行資訊
192.168.52.2 namenode
192.168.52.3 datanode1
192.168.52.4 datanode2
192.168.52.5 datanode3
192.168.52.1 win #這行最好也加上,方便本機windows與4臺虛擬機器的相互訪問
2、關閉SELINUX
因為CentOS的所有訪問許可權都是有SELinux來管理的,為了簡化安裝過程避免許可權導致的問題,先將其關閉,以後根據需要再進行重新管理。
執行如下指令關閉:
setenforce 0 #臨時設定SELINUX狀態
vi /etc/selinux/config # 編輯 config 檔案將 SELINUX=enforcing 修改為 SELINUX=disabled(重啟生效)
檢視執行結果:
getenforce #檢視當前SELINUX狀態,permissive或disabled代表SELINUX處於關閉狀態
3、關閉防火牆
同樣是為了簡化安裝,避免防火牆策略帶來的影響。
先檢視防火牆狀態:
[[email protected] hadoop]$ systemctl status firewalld
● firewalld.service - firewalld - dynamic firewall daemon Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled) #disabled表示非開機啟動
Active: inactive (dead) #inactive表示當前未啟用,active表示已啟用
Docs: man:firewalld(1)
4、新建hadoop賬戶
由於Hadoop 叢集中的各節點預設會使用當前的賬號SSH免密碼登入其它節點,所以需要在每個節點中建立一個相同的供 Hadoop 叢集專用的賬戶,本例中使用的賬戶為 hadoop 。
useradd hadoop #建立賬戶 passwd hadoop #設定密碼
5、配置ssh互信(root、hadoop)
5.1 開啟 sshd 祕鑰認證
編輯每一臺伺服器的 /etc/ssh/sshd_config 檔案,去掉下面這3行前的 “#” 註釋。
執行:
vi /etc/ssh/sshd_config
刪除行首"#",取消註釋:
# RSAAuthentication yes
# PubkeyAuthentication yes
# AuthorizedKeysFile .ssh/authorized_keys
然後重啟sshd服務:
systemctl restart sshd
5.2 配置root賬戶的ssh互信
5.2.1 生成公鑰和私鑰
在4臺伺服器上執行,一直按回車預設即可:
ssh-keygen -t rsa
執行完後會在hadoop使用者的家目錄(/home/hadoop)中生成一個.ssh資料夾,裡面有兩個檔案,其中id_rsa是私鑰,id_rsa.pub是公鑰。
在namenode伺服器上以下執行:
5.2.2 將4臺伺服器公鑰檔案的內容追加輸入到authorized_keys檔案
(1) 先將namenode的公鑰內容插入到authorized_keys檔案
cat /home/root/.ssh/id_rsa.pub >> /home/root/.ssh/authorized_keys
(2) 通過ssh輸入密碼再將三臺datanode的公鑰內容插入到authorized_keys檔案
ssh [email protected] cat /home/root/.ssh/id_rsa.pub >> /home/root/.ssh/authorized_keys
ssh [email protected] cat /home/root/.ssh/id_rsa.pub >> /home/root/.ssh/authorized_keys
ssh [email protected] cat /home/root/.ssh/id_rsa.pub >> /home/root/.ssh/authorized_keys
5.2.3 ssh連線namenode自己,以在/home/root/.ssh/known_hosts生成自己的那條記錄
ssh hadoop cat /home/root/.ssh/id_rsa.pub >> /home/root/.ssh/authorized_keys
5.2.4 將authorized_keys和known_hosts通過scp複製到三臺datanode伺服器上
scp /home/root/.ssh/authorized_keys datanode1:/home/root/.ssh/
scp /home/root/.ssh/authorized_keys datanode2:/home/root/.ssh/
scp /home/root/.ssh/authorized_keys datanode3:/home/root/.ssh/
scp /home/root/.ssh/known_hosts datanode1:/home/root/.ssh/
scp /home/root/.ssh/known_hosts datanode2:/home/root/.ssh/
scp /home/root/.ssh/known_hosts datanode3:/home/root/.ssh/
5.2.5 修改ssh目錄和authorized_keys的許可權
chmod -R 700 /home/root/.ssh chmod 600 /home/root/.ssh/authorized_keys
5.2.6 測試一下,不需要輸入密碼就能登入則成功,注意下命令列中的主機名哦
ssh [email protected] ssh [email protected] ssh [email protected]
5.3 同理,配置hadoop賬戶的ssh互信
用hadoopz賬戶登入,生成公、私鑰:
ssh-keygen -t rsa
其他步驟按照5.2的順序來,只要把root替換成hadoop就可以了。
6、 用root使用者給hadoop使用者授予sudo許可權
執行如下指令:
visudo
在文末新增如下內容,目的是為了授予hadoop使用者組所有許可權,可使用sudo指令執行一些只有root使用者才能執行的指令。
%hadoop ALL=(ALL) ALL
7、安裝JDK
從下面網站下載Oracle JDK8的tar.gz包,第一個網站可以下載8u202版本,第二個可以下載8u192版本,Oracle官方說了2019年1月以後將不支援Java 8的公開版更新。
https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
ftp、rz或通過虛擬機器共享資料夾上傳到伺服器,找到安裝包所在目錄,解壓安裝即可,
tar -zxf java8.tar.gz -C 要解壓到的檔案路徑 #想要看安裝過程輸出資訊的可以加個v引數,即-zxvf
8、配置時間同步,避免伺服器間時間不一致帶來的影響
注意:ntp配置後,要延遲一陣才開始時間同步,所以用ntpstat -p指令檢視是否配置成功時,不要以為輸出的結果不對就是沒配置正確,最好等一段時間再看。
9、安裝ZooKeeper
這個也沒什麼說的,下載,解壓,配置。在ZooKeeper伺服器比如datanode1上安裝配置好後,然後scp整個ZooKeeper目錄即可。
下載地址:
https://www.apache.org/dyn/closer.cgi/zookeeper/
到ZooKeeper伺服器上,解壓指令:
tar -zxf zookeeper.tar.gz -C 要解壓到的檔案路徑
配置:
到ZooKeeper的安裝目錄下的conf子目錄下新建zoo.cfg:
cp zoo_sample.cfg zoo.cfg
配置zoo.cfg:
vi zoo.cfg
把原來的dataDir那行註釋掉,新加如下兩行:
dataDir=/hadoop/software/zookeeper-3.4.13/data
dataLogDir=/hadoop/software/zookeeper-3.4.13/logs
server.1=datanode1:2888:3888
server.2=datanode2:2888:3888
server.3=datanode3:2888:3888
新建兩個目錄——data目錄和logs目錄,對應zoo.cfg中的配置,並在data目錄下新建myid檔案,內容對應zoo.cfg中的server單詞後的數字,如果是複製的檔案別忘了改哦!
至此ZooKeeper就配好了,是不是很簡單?
10、安裝、配置Hadoop
安裝hadoop難點無非就是配置問題,在遇到問題時確保配置正確,結合log檔案查詢原因。
注意:下面所有指令都是以hadoop使用者登入執行的:
10.1 安裝Hadoop
下載地址:
下載好tar.gz包,解壓(建議不要下source原始碼版本的,需要各種包和docker包,很煩),注意四臺伺服器上都要安裝哦!
tar -zxf hadoop.tar.gz -C hadoop的安裝目錄
10.2 配置hadoop的環境變數和全域性環境變數
可以分別配置/etc/profile和/home/hadoop/.bash_profile,這樣許可權方面更安全一點,但我嫌麻煩,索性都配到/etc/profile裡了。
vi /etc/profile
在文末加入如下內容:
# Configure JAVA
export JAVA_HOME=/software/jdk1.8.0_202
export JAVA_BIN=$JAVA_HOME/bin
export JAVA_LIB=$JAVA_HOME/lib
export CLASSPATH=.:$JAVA_LIB/tools.jar:$JAVA_LIB/dt.jar
# Configure Hadoop
export HADOOP_HOME=/hadoop/hadoop-2.9.2
export HADOOP_CONF_DIR=${HADOOP_HOME}/etc/hadoop
# Configure Zookeeper
export ZOOKEEPER_HOME=/hadoop/software/zookeeper-3.4.13
# Configure PATH export PATH=$PATH:$HOME/.local/bin:$HOME/bin:$JAVA_BIN:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$ZOOKEEPER_HOME/bin
進入到配置檔案所在目錄:
cd /hadoop/hadoop-2.9.2/etc/hadoop
10.3 在配置hdfs時用到的配置檔案是hadoop-env.sh、core-site.xml和hdfs-site.xml,具體配置如下:
10.3.1 配置hadoop-env.sh
將其中的export JAVA_HOME行替換為JAVA_HOME的絕對路徑:
export JAVA_HOME=/software/jdk1.8.0_202
根據自己的實際環境配置。注意,我開始覺得沒必要修改,因為JAVA_HOME全域性變數已經在/etc/profile中聲明瞭,且測試shell指令碼echo出的變數值也對,執行Hadoop卻報錯,看樣必須要設定成絕對路徑。
10.3.2 配置core-site.xml,在<configuration>標籤內加入(如果裡面有內容,則替換)如下內容:
<property>
<!-- hdfs預設檔案系統名 -->
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<!-- 序列檔案的緩衝區大小 -->
<property>
<name>io.file.buffer.size</name>
<value>131072</value>
</property>
<!-- 臨時檔案目錄-->
<property>
<name>hadoop.tmp.dir</name>
<value>file:/hadoop/hadoop-2.9.2/tmp_ha</value>
</property>
<!-- 指定ZKFC故障自動切換轉移 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>namenode:2181,datanode1:2181</value>
</property>
10.3.3 配置hdfs-site.xml
<!-- reducer獲取資料的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!--啟用ResourceManager ha-->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!--啟用ResourceManager ha自動切換-->
<property>
<name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!--宣告兩臺ResourceManager的地址-->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>rmCluster</value>
</property>
<!--定義兩臺ResourceManager的rm-id-->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!--定義rm-id為rm1的ResourceManager的主機名-->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>namenode</value>
</property>
<!--定義rm-id為rm2的ResourceManager的主機名-->
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>datanode2</value>
</property>
<!--指定zookeeper叢集的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>datanode1:2181,datanode2:2181,datanode3:2181</value>
</property>
<!--啟用自動恢復-->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!--指定ResourceManager的狀態資訊儲存在zookeeper叢集-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
至此,hdfs HA就配置完了。
10.4 在配置yarn ResourceManager時用到的配置檔案是yarn-env.sh、yarn-site.xml
10.4.1 配置yarn-env.sh
將其中的export JAVA_HOME行替換為JAVA_HOME的絕對路徑:
export JAVA_HOME=/software/jdk1.8.0_202
10.4.2 配置yarn-site.xml
<!-- reducer獲取資料的方式 -->
<property>
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<!--啟用ResourceManager ha-->
<property>
<name>yarn.resourcemanager.ha.enabled</name>
<value>true</value>
</property>
<!--啟用ResourceManager ha自動切換-->
<property>
<name>yarn.resourcemanager.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
<!--宣告兩臺ResourceManager的地址-->
<property>
<name>yarn.resourcemanager.cluster-id</name>
<value>rmCluster</value>
</property>
<!--定義兩臺ResourceManager的rm-id-->
<property>
<name>yarn.resourcemanager.ha.rm-ids</name>
<value>rm1,rm2</value>
</property>
<!--定義rm-id為rm1的ResourceManager的主機名-->
<property>
<name>yarn.resourcemanager.hostname.rm1</name>
<value>namenode</value>
</property>
<!--定義rm-id為rm2的ResourceManager的主機名-->
<property>
<name>yarn.resourcemanager.hostname.rm2</name>
<value>datanode2</value>
</property>
<!--指定zookeeper叢集的地址-->
<property>
<name>yarn.resourcemanager.zk-address</name>
<value>datanode1:2181,datanode2:2181,datanode3:2181</value>
</property>
<!--啟用自動恢復-->
<property>
<name>yarn.resourcemanager.recovery.enabled</name>
<value>true</value>
</property>
<!--指定ResourceManager的狀態資訊儲存在zookeeper叢集-->
<property>
<name>yarn.resourcemanager.store.class</name>
<value>org.apache.hadoop.yarn.server.resourcemanager.recovery.ZKRMStateStore</value>
</property>
至此,yarn HA就配置完了。
10.5 複製配置到其他3臺伺服器
10.5.1 為了省事,可以先配好一臺伺服器,比如namenode,然後再用scp指令複製hadoop配置檔案到其他機器上。
在其餘三臺伺服器上分別用hadoop使用者執行:
scp -r namenode:/hadoop/hadoop-2.9.2/etc/hadoop /hadoop/hadoop-2.9.2/etc/hadoop
也可以反過來,只在namenode伺服器上執行:
scp -r /hadoop/hadoop-2.9.2/etc/hadoop datanode1:/hadoop/hadoop-2.9.2/etc/hadoop
scp -r /hadoop/hadoop-2.9.2/etc/hadoop datanode1:/hadoop/hadoop-2.9.2/etc/hadoop
scp -r /hadoop/hadoop-2.9.2/etc/hadoop datanode1:/hadoop/hadoop-2.9.2/etc/hadoop
10.5.2 建議依據伺服器在叢集中的角色做個性化配置
如果只是安裝個Hadoop HA叢集玩玩,可以按10.5.1那麼做;可如果想深入瞭解Hadoop的配置引數,建議結合官方文件,對不同角色的伺服器做個性化配置,少配一些不必要的引數。
11、啟動Hadoop HA叢集
(1)在任意ZooKeeper節點上執行:
hdfs zkfc -formatZK
(2)啟動ZKFC (ZookeeperFailoverController是用來監控NameNode狀態,協助實現主備NameNode切換的,所以僅僅在主備NameNode節點上啟動就行)
在namenode、datanode1上分別執行:
hadoop-daemon.sh start zkfc
用jps指令檢視執行結果:
(3)啟動用於主備NameNode之間同步元資料資訊的共享儲存系統JournalNode。在叢集中各個節點上執行。
兩個NameNode為了資料同步,會通過一組稱作JournalNodes的獨立程序進行相互通訊。當active狀態的NameNode的名稱空間有任何修改時,會告知大部分的JournalNodes程序。standby狀態的NameNode有能力讀取JournalNodes中的變更資訊,並且一直監控Edit log的變化,把變化應用於自己的名稱空間。standby可以確保在叢集出錯時,名稱空間狀態已經完全同步了。
按如上所說,只在NameNode上啟動JournalNode即可,可是JournalNode機制有額外的限制,需要N-1/2個節點且至少有3個節點,因此必須要在其他伺服器上加一個JournalNode節點。
分別在namenode、datanode1、datanode2三臺JournalNode伺服器上執行:
hadoop-daemon.sh start journalnode
用jps指令檢視執行結果:
(4)格式化並啟動主NameNode
在namenode上執行:
hdfs namenode -format
用jps指令檢視執行結果:
(5)在備NameNode上同步主NameNode的元資料資訊
在datanode1上執行:
hdfs namenode -bootstrapStandby
如果安裝過程中出現問題,多次執行會有報錯,需要關掉服務或殺死程序,清空報錯提示的目錄。
(6)啟動備NameNode
在datanode1上執行:
hadoop-daemon.sh start namenode
用jps指令檢視執行結果:
(7)主NameNode上啟動DataNode
在namenode上,啟動所有datanode
hadoop-daemons.sh start datanode
所有節點啟動完成後,驗證主備切換。
在瀏覽器中開啟
http://namenode:50070/dfshealth.html#tab-overview
http://datanode1:50070/dfshealth.html#tab-overview
檢視狀態
然後,在主NameNode(主機名namenode)上執行:
ps -ef|grep namenode-namenode #正常只要ps -ef|grep namenode即可,因為我的主機名也叫namenode,所以需要改動一下
找到程序號後,
kill -9 剛剛找到的程序號
然後檢視
http://datanode1:50070/dfshealth.html#tab-overview
無需檢視namenode的網頁,想也知道程序被殺了根本打不開。
發現datanode1的狀態由standby變為active,則驗證成功。
最後,不放心的話可以在namenode上啟動NameNode。可以看到,狀態由active變為standby。
至此,hdfs HA就驗證完了。
注:
1)這裡也可以用hdfs haadmin指令檢視NameNode狀態
hdfs haadmin -getServiceState nn2 #nn1、nn2為上面定義的NameNode節點名
hdfs haadmin -getServiceState nn1 #報錯正常,因為程序被kill了,還沒啟動
2)在驗證時也可以通過hdfs haadmin指令來進行主備切換,但這樣並不能驗證HA主備切換真的配置成功了。我最開始配置錯誤,這樣操作仍然可以驗證成功,可kill程序就無法驗證成功了,證明配置存在問題。
hdfs haadmin -failover nn1 nn2
(8)在主ResourceManager(namenode)、備(datanode2)上啟動Yarn
yarn-daemon.sh start resourcemanager
開啟
http://namenode:8088/cluster/cluster
http://datanode2:8088/cluster/cluster
關掉resourcemanager服務,或者kill掉該程序後,驗證主備切換。
yarn-daemon.sh stop resourcemanager
此時,主ResourceManager網頁無法訪問。再次在namenode上啟動ResourceManager服務:
yarn-daemon.sh start resourcemanager
可以看到
至此,Yarn HA就驗證完了。
12、遇到的問題
(1)好多年沒關注Linux版本變更了,只是偶爾用到一些常用指令,在安裝CentOS 7時,發現好多指令都不能用了,比如SysV服務變成了systemd服務,導致chkconfig、service指令某些功能不能用了,系統建議用原生的systemctl指令。不禁感慨現在知識迭代太快了。
(2)因為工作地點網路環境所限,需要做額外工作。剛開始想配reposever連到阿里雲或者教育網作為yum源,屢試不行,應該是防毒軟體和網路策略限制了,網路不通。我記得以前直接用iso檔案作為yum源就行,我4臺伺服器,只需要一臺做yum源,其他3臺用它當yum源,於是就按這個思路配置yum源。這樣,整個叢集就是純內網Hadoop叢集了。
(3)在配置ntp同步時,我打算用namenode作為叢集ntp伺服器,其他三臺datanode同步其時間,而namenode的時間由本機windows同步過去。其實可以用VMware Workstation自帶的時間同步。可我就是想試試windows ntp服務,於是又研究了一下,安裝了個njinx和ntp,最終實現同步。
但在驗證時驗證過早,總以為配置有問題,因為幾年前裝過ntp服務,大致知道怎麼配,可怎麼也找不到哪兒配置錯了。最後偶然發現ntpstat -p居然同步了,證明配置沒問題,搜了下資料才發現ntp第一次同步會有一定的延遲。
(4)在配置hdfs HA時,將ssh驗證那塊的私鑰當成公鑰了,以為是ssh互信呢,給改成authorized_keys了,後來看log才找到原因。
(5)改完ssh後,發現kill程序主備切換還是失敗,檢視log和hadoop java原始碼才發現呼叫的是fuser指令,而CentOS 7最小化安裝預設是不安裝fuser對應的軟體包的。於是:
yum install psmisc
安裝好後,再次驗證,果然成功了!你說這有多坑吧,所以建議想省心的還是完整安裝作業系統吧,省著少這包那包的。
總結,架構整體挺簡單,但因涉及到的方面比較多,再加上環境原因,導致在配yum源、ntp時間同步和驗證hdfs HA時多花了些時間。在hadoop配置方面,多看看官方文件,挺簡單的,但也不能盡信之,因為這個文件好像很久沒更新了,連支援的jdk都是7,聽說java是3個版本一個大版本,所以jdk 6、7、8應該差異不大。