第一章 HA 概述
(1)所謂 HA(High Availablity),即高可用(7*24 小時不中斷服務)。
(2)實現高可用最關鍵的策略是消除單點故障。HA 嚴格來說應該分成各個組件的 HA機制:HDFS 的 HA 和 YARN 的 HA。
(3)NameNode 主要在以下兩個方面影響 HDFS 集羣
- NameNode 機器發生意外,如宕機,集羣將無法使用,直到管理員重啓
- NameNode 機器需要升級,包括軟件、硬件升級,此時集羣也將無法使用
HDFS HA 功能通過配置多個 NameNodes(Active/Standby)實現在集羣中對 NameNode 的熱備來解決上述問題。如果出現故障,如機器崩潰或機器需要升級維護,這時可通過此種方式將 NameNode 很快的切換到另外一臺機器。
第二章 HDFS-HA 集羣搭建
當前 HDFS 集羣的規劃
hadoop102 | hadoop103 | hadoop104 |
NameNode | Secondarynamenode | |
DataNode | DataNode | DataNode |
HA 的主要目的是消除 namenode 的單點故障,需要將 hdfs 集羣規劃成以下模樣
hadoop102 | hadoop103 | hadoop104 |
NameNode | NameNode | NameNode |
DataNode | DataNode | DataNode |
2.1 HDFS-HA 核心問題
1)怎麼保證三臺 namenode 的數據一致
- a.Fsimage:讓一臺 nn 生成數據,讓其他機器 nn 同步
- b.Edits:需要引進新的模塊 JournalNode 來保證 edtis 的文件的數據一致性
https://www.cnblogs.com/wkfvawl/p/15475122.html#scroller-28
2)怎麼讓同時只有一臺 nn 是 active,其他所有是 standby 的
- a.手動分配
- b.自動分配
3)2nn 在 ha 架構中並不存在,定期合併 fsimage 和 edtis 的活誰來幹
由 standby 的 nn 來幹
4)如果 nn 真的發生了問題,怎麼讓其他的 nn 上位幹活
- a.手動故障轉移
- b.自動故障轉移
第三章 HDFS-HA 手動模式
3.1 環境準備
(1)修改 IP
(2)修改主機名及主機名和 IP 地址的映射
(3)關閉防火牆
(4)ssh 免密登錄
(5)安裝 JDK,配置環境變量等
3.2 規劃集羣
hadoop102 | hadoop103 | hadoop104 |
NameNode | NameNode | NameNode |
JournalNode | JournalNode | JournalNode |
DataNode | DataNode | DataNode |
3.3 配置 HDFS-HA 集羣
1)官方地址:http://hadoop.apache.org/
2)在 opt 目錄下創建一個 ha 文件夾
[atguigu@hadoop102 ~]$ cd /opt [atguigu@hadoop102 opt]$ sudo mkdir ha [atguigu@hadoop102 opt]$ sudo chown atguigu:atguigu /opt/ha
3)將/opt/module/下的 hadoop-3.1.3 拷貝到/opt/ha 目錄下(記得刪除 data 和 log 目錄)
[atguigu@hadoop102 opt]$ cp -r /opt/module/hadoop-3.1.3 /opt/ha/
4)配置 core-site.xml
<configuration> <!-- 把多個 NameNode 的地址組裝成一個集羣 mycluster --> <property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <!-- 指定 hadoop 運行時產生文件的存儲目錄 --> <property> <name>hadoop.tmp.dir</name> <value>/opt/ha/hadoop-3.1.3/data</value> </property> </configuration>
5)配置 hdfs-site.xml
<configuration> <!-- NameNode 數據存儲目錄 --> <property> <name>dfs.namenode.name.dir</name> <value>file://${hadoop.tmp.dir}/name</value> </property> <!-- DataNode 數據存儲目錄 --> <property> <name>dfs.datanode.data.dir</name> <value>file://${hadoop.tmp.dir}/data</value> </property> <!-- JournalNode 數據存儲目錄 --> <property> <name>dfs.journalnode.edits.dir</name> <value>${hadoop.tmp.dir}/jn</value> </property> <!-- 完全分佈式集羣名稱 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!-- 集羣中 NameNode 節點都有哪些 --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2,nn3</value> </property> <!-- NameNode 的 RPC 通信地址 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>hadoop102:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>hadoop103:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn3</name> <value>hadoop104:8020</value> </property> <!-- NameNode 的 http 通信地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>hadoop102:9870</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>hadoop103:9870</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn3</name> <value>hadoop104:9870</value> </property> <!-- 指定 NameNode 元數據在 JournalNode 上的存放位置 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://hadoop102:8485;hadoop103:8485;hadoop104:8485/myclus ter</value> </property> <!-- 訪問代理類:client 用於確定哪個 NameNode 爲 Active --> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyP rovider</value> </property> <!-- 配置隔離機制,即同一時刻只能有一臺服務器對外響應 --> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <!-- 使用隔離機制時需要 ssh 祕鑰登錄--> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/atguigu/.ssh/id_rsa</value> </property> </configuration>
6)分發配置好的 hadoop 環境到其他節點
3.4 啓動 HDFS-HA 集羣
1)將 HADOOP_HOME 環境變量更改到 HA 目錄(三臺機器)
[atguigu@hadoop102 ~]$ sudo vim /etc/profile.d/my_env.sh
將 HADOOP_HOME 部分改爲如下
#HADOOP_HOME export HADOOP_HOME=/opt/ha/hadoop-3.1.3 export PATH=$PATH:$HADOOP_HOME/bin export PATH=$PATH:$HADOOP_HOME/sbin
去三臺機器上 source 環境變量
[atguigu@hadoop102 ~]$source /etc/profile
2)在各個 JournalNode 節點上,輸入以下命令啓動 journalnode 服務
[atguigu@hadoop102 ~]$ hdfs --daemon start journalnode [atguigu@hadoop103 ~]$ hdfs --daemon start journalnode [atguigu@hadoop104 ~]$ hdfs --daemon start journalnode
3)在[nn1]上,對其進行格式化,並啓動
[atguigu@hadoop102 ~]$ hdfs namenode -format
[atguigu@hadoop102 ~]$ hdfs --daemon start namenode
4)在[nn2]和[nn3]上,同步 nn1 的元數據信息
[atguigu@hadoop103 ~]$ hdfs namenode -bootstrapStandby
[atguigu@hadoop104 ~]$ hdfs namenode -bootstrapStandby
5)啓動[nn2]和[nn3]
[atguigu@hadoop103 ~]$ hdfs --daemon start namenode
[atguigu@hadoop104 ~]$ hdfs --daemon start namenode
6)查看 web 頁面顯示
圖 hadoop102(standby)
圖 hadoop103(standby)
圖 hadoop104(standby)
7)在所有節點上,啓動 datanode
[atguigu@hadoop102 ~]$ hdfs --daemon start datanode [atguigu@hadoop103 ~]$ hdfs --daemon start datanode [atguigu@hadoop104 ~]$ hdfs --daemon start datanode
8)將[nn1]切換爲 Active
[atguigu@hadoop102 ~]$ hdfs haadmin -transitionToActive nn1
9)查看是否 Active
[atguigu@hadoop102 ~]$ hdfs haadmin -getServiceState nn1
第四章 HDFS-HA 自動模式
4.1 HDFS-HA 自動故障轉移工作機制
自動故障轉移爲 HDFS 部署增加了兩個新組件:ZooKeeper 和 ZKFailoverController(ZKFC)進程,如圖所示。ZooKeeper 是維護少量協調數據,通知客戶端這些數據的改變和監視客戶端故障的高可用服務。
4.2 HDFS-HA 自動故障轉移的集羣規劃
hadoop102 | hadoop103 | hadoop104 |
NameNode | NameNode | NameNode |
JournalNode | JournalNode | JournalNode |
DataNode | DataNode | DataNode |
Zookeeper | Zookeeper | Zookeeper |
ZKFC | ZKFC | ZKFC |
4.3 配置 HDFS-HA 自動故障轉移
1)具體配置
(1)在 hdfs-site.xml 中增加
<!-- 啓用 nn 故障自動轉移 --> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
(2)在 core-site.xml 文件中增加
<!-- 指定 zkfc 要連接的 zkServer 地址 --> <property> <name>ha.zookeeper.quorum</name> <value>hadoop102:2181,hadoop103:2181,hadoop104:2181</value> </property>
2181:zookeeper對Client端提供服務的端口。
(3)修改後分發配置文件
[atguigu@hadoop102 etc]$ pwd
/opt/ha/hadoop-3.1.3/etc
[atguigu@hadoop102 etc]$ xsync hadoop/
2)啓動
(1)關閉所有 HDFS 服務:
[atguigu@hadoop102 ~]$ stop-dfs.sh
(2)啓動 Zookeeper 集羣:
[atguigu@hadoop102 ~]$ zkServer.sh start [atguigu@hadoop103 ~]$ zkServer.sh start [atguigu@hadoop104 ~]$ zkServer.sh start
(3)啓動 Zookeeper 以後,然後再初始化 HA 在 Zookeeper 中狀態:
[atguigu@hadoop102 ~]$ hdfs zkfc -formatZK
(4)啓動 HDFS 服務:
[atguigu@hadoop102 ~]$ start-dfs.sh
(5)可以去 zkCli.sh 客戶端查看 Namenode 選舉鎖節點內容:
[zk: localhost:2181(CONNECTED) 7] get -s /hadoop-ha/mycluster/ActiveStandbyElectorLock myclusternn2 hadoop103 �>(�> cZxid = 0x10000000b ctime = Tue Jul 14 17:00:13 CST 2020 mZxid = 0x10000000b mtime = Tue Jul 14 17:00:13 CST 2020 pZxid = 0x10000000b cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x40000da2eb70000 dataLength = 33 numChildren = 0
3)驗證
(1)將 Active NameNode 進程 kill,查看網頁端三臺 Namenode 的狀態變化
[atguigu@hadoop102 ~]$ kill -9 namenode 的進程 id
4.3 解決 NN 連接不上 JN 的問題
自動故障轉移配置好以後,然後使用 start-dfs.sh 羣起腳本啓動 hdfs 集羣,有可能會遇到 NameNode 起來一會後,進程自動關閉的問題。查看 NameNode 日誌,報錯信
息如下:
2020-08-17 10:11:40,658 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop104/192.168.6.104:8485. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS) 2020-08-17 10:11:40,659 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop102/192.168.6.102:8485. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS) 2020-08-17 10:11:40,659 INFO org.apache.hadoop.ipc.Client: Retrying connect to server: hadoop103/192.168.6.103:8485. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=10, sleepTime=1000 MILLISECONDS) 2020-08-17 10:11:49,678 WARN org.apache.hadoop.hdfs.server.namenode.FSEditLog: Unable to determine input streams from QJM to [192.168.6.102:8485, 192.168.6.103:8485, 192.168.6.104:8485]. Skipping.org.apache.hadoop.hdfs.qjournal.client.QuorumException: Got too many exceptions to achieve quorum size 2/3. 3 exceptions thrown:192.168.6.103:8485: Call From hadoop102/192.168.6.102 to hadoop103:8485 failed on connection exception: java.net.ConnectException: 拒絕連接; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused
查看報錯日誌,可分析出報錯原因是因爲 NameNode 連接不上 JournalNode,而利用 jps 命令查看到三臺 JN 都已經正常啓動,爲什麼 NN 還是無法正常連接到 JN 呢?這是因爲 start-dfs.sh 羣起腳本默認的啓動順序是先啓動 NN,再啓動 DN,然後再啓動 JN,並且默認的 rpc 連接參數是重試次數爲 10,每次重試的間隔是 1s,也就是說啓動完 NN以後的 10s 中內,JN 還啓動不起來,NN 就會報錯了。
core-default.xml 裏面有兩個參數如下:
<!-- NN 連接 JN 重試次數,默認是 10 次 --> <property> <name>ipc.client.connect.max.retries</name> <value>10</value> </property> <!-- 重試時間間隔,默認 1s --> <property> <name>ipc.client.connect.retry.interval</name> <value>1000</value> </property>
解決方案:遇到上述問題後,可以稍等片刻,等 JN 成功啓動後,手動啓動下三臺NN:
[atguigu@hadoop102 ~]$ hdfs --daemon start namenode [atguigu@hadoop103 ~]$ hdfs --daemon start namenode [atguigu@hadoop104 ~]$ hdfs --daemon start namenode
也可以在 core-site.xml 裏面適當調大上面的兩個參數:
<!-- NN 連接 JN 重試次數,默認是 10 次 --> <property> <name>ipc.client.connect.max.retries</name> <value>20</value> </property> <!-- 重試時間間隔,默認 1s --> <property> <name>ipc.client.connect.retry.interval</name> <value>5000</value> </property>
第五章 YARN-HA 配置
5.1 YARN-HA 工作機制
1)官方文檔:
http://hadoop.apache.org/docs/r3.1.3/hadoop-yarn/hadoop-yarn-site/ResourceManagerHA.htm
2)YARN-HA 工作機制
5.2 配置 YARN-HA 集羣
1)環境準備
(1)修改 IP
(2)修改主機名及主機名和 IP 地址的映射
(3)關閉防火牆
(4)ssh 免密登錄
(5)安裝 JDK,配置環境變量等
(6)配置 Zookeeper 集羣
2)規劃集羣
hadoop102 | hadoop103 | hadoop104 |
ResourceManager | ResourceManager | ResourceManager |
NodeManager | NodeManager | NodeManager |
Zookeeper | Zookeeper | Zookeeper |
3)核心問題
a .如果當前 active rm 掛了,其他 rm 怎麼將其他 standby rm 上位?
核心原理跟 hdfs 一樣,利用了 zk 的臨時節點
b. 當前 rm 上有很多的計算程序在等待運行,其他的 rm 怎麼將這些程序接手過來接着跑?
rm 會將當前的所有計算程序的狀態存儲在 zk 中,其他 rm 上位後會去讀取,然後接着跑
4)具體配置
(1)yarn-site.xml
<configuration> <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 的地址 --> <property> <name>yarn.resourcemanager.cluster-id</name> <value>cluster-yarn1</value> </property> <!--指定 resourcemanager 的邏輯列表--> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2,rm3</value> </property> <!-- ========== rm1 的配置 ========== --> <!-- 指定 rm1 的主機名 --> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>hadoop102</value> </property> <!-- 指定 rm1 的 web 端地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm1</name> <value>hadoop102:8088</value> </property> <!-- 指定 rm1 的內部通信地址 --> <property> <name>yarn.resourcemanager.address.rm1</name> <value>hadoop102:8032</value> </property> <!-- 指定 AM 向 rm1 申請資源的地址 --> <property> <name>yarn.resourcemanager.scheduler.address.rm1</name> <value>hadoop102:8030</value> </property> <!-- 指定供 NM 連接的地址 --> <property> <name>yarn.resourcemanager.resource-tracker.address.rm1</name> <value>hadoop102:8031</value> </property> <!-- ========== rm2 的配置 ========== --> <!-- 指定 rm2 的主機名 --> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>hadoop103</value> </property> <property> <name>yarn.resourcemanager.webapp.address.rm2</name> <value>hadoop103:8088</value> </property> <property> <name>yarn.resourcemanager.address.rm2</name> <value>hadoop103:8032</value> </property> <property> <name>yarn.resourcemanager.scheduler.address.rm2</name> <value>hadoop103:8030</value> </property> <property> <name>yarn.resourcemanager.resource-tracker.address.rm2</name> <value>hadoop103:8031</value> </property> <!-- ========== rm3 的配置 ========== --> <!-- 指定 rm1 的主機名 --> <property> <name>yarn.resourcemanager.hostname.rm3</name> <value>hadoop104</value> </property> <!-- 指定 rm1 的 web 端地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm3</name> <value>hadoop104:8088</value> </property> <!-- 指定 rm1 的內部通信地址 --> <property> <name>yarn.resourcemanager.address.rm3</name> <value>hadoop104:8032</value> </property> <!-- 指定 AM 向 rm1 申請資源的地址 --> <property> <name>yarn.resourcemanager.scheduler.address.rm3</name> <value>hadoop104:8030</value> </property> <!-- 指定供 NM 連接的地址 --> <property> <name>yarn.resourcemanager.resource-tracker.address.rm3</name> <value>hadoop104:8031</value> </property> <!-- 指定 zookeeper 集羣的地址 --> <property> <name>yarn.resourcemanager.zk-address</name> <value>hadoop102:2181,hadoop103:2181,hadoop104: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.ZKRMStateSt ore</value> </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_MAPRED_HOME</value> </property> </configuration>
(2)同步更新其他節點的配置信息,分發配置文件
[atguigu@hadoop102 etc]$ xsync hadoop/
4)啓動 YARN
(1)在 hadoop102 或者 hadoop103 中執行:
[atguigu@hadoop102 ~]$ start-yarn.sh
(2)查看服務狀態
[atguigu@hadoop102 ~]$ yarn rmadmin -getServiceState rm1
(3)可以去 zkCli.sh 客戶端查看 ResourceManager 選舉鎖節點內容:
[atguigu@hadoop102 ~]$ zkCli.sh [zk: localhost:2181(CONNECTED) 16] get -s /yarn-leader-election/cluster-yarn1/ActiveStandbyElectorLock cluster-yarn1rm1 cZxid = 0x100000022 ctime = Tue Jul 14 17:06:44 CST 2020 mZxid = 0x100000022 mtime = Tue Jul 14 17:06:44 CST 2020 pZxid = 0x100000022 cversion = 0 dataVersion = 0 aclVersion = 0 ephemeralOwner = 0x30000da33080005 dataLength = 20 numChildren = 0
(4)web 端查看 hadoop102:8088 和 hadoop103:8088 的 YARN 的狀態
5.3 HADOOP HA 的最終規劃
將整個 ha 搭建完成後,集羣將形成以下模樣
hadoop102 | hadoop103 | hadoop104 |
NameNode | NameNode | NameNode |
JournalNode | JournalNode | JournalNode |
DataNode | DataNode | DataNode |
Zookeeper | Zookeeper | Zookeeper |
ZKFC | ZKFC | ZKFC |
ResourceManager | ResourceManager | ResourceManager |
NodeManager | NodeManager | NodeManager |