本篇主要從hdfs的namenode和resourcemanager的高可用進行安裝和原理的闡述。
一、HA安裝
1、基本環境准備
1.1.1、centos7虛擬機安裝,詳情見VMware安裝Centos7虛擬機
1.1.2、關閉防火牆
systemctl stop firewalld.service
systemctl disable firewalld.service
1.1.3、修改selinux
vim /etc/selinux/config
將SELINUX=enforcing改為SELINUX=disabled
[hadoop@lgh2 ~]$ cat /etc/selinux/config # This file controls the state of SELinux on the system. # SELINUX= can take one of these three values: # enforcing - SELinux security policy is enforced. # permissive - SELinux prints warnings instead of enforcing. # disabled - No SELinux policy is loaded. SELINUX=disabled # SELINUXTYPE= can take one of three two values: # targeted - Targeted processes are protected, # minimum - Modification of targeted policy. Only selected processes are protected. # mls - Multi Level Security protection. SELINUXTYPE=targeted
1.1.4、安裝java
java 安裝 tar -zxvf jdk-8u201-linux-x64.tar.gz -C /usr/local/ vim /etc/profile export JAVA_HOME=/usr/local/jdk1.8.0_201 export JRE_HOME=/usr/local/jdk1.8.0_201/jre export CLASS_PATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar:$JRE_HOME/lib export PATH=$JAVA_HOME/bin:$JRE_HOME/bin:$PATH
source /etc/profile
1.1.5、添加用戶hadoop
groupadd hadoop useradd -g hadoop -d /home/hadoop echo 'hadoop' | passwd hadoop --stdin
1.1.6、修改/etc/hosts
cat /etc/hosts 192.168.88.131 lgh1 192.168.88.132 lgh2 192.168.88.133 lgh3
如上環境我們准備三台機器,如上1.1.6所見:
1.1.7、配置免密登錄
ssh-keygen -t rsa #這個操作需要連續三次按enter鍵, ssh-copy-id lgh3 ssh-copy-id lgh2 ssh-copy-id lgh1
1.1.8、配置時間同步(這個很重要,在生產環境必定要有,不過自己玩也可以不用配置)
首先我們選定192.168.88.131(lgh1)這台為時間標准的節點,其他兩台機器同這個節點進行同步
設置192.168.88.131這個節點:
yum install -y ntp #如果沒有安裝就安裝 [root@lgh1 ~]# rpm -qa | grep ntp #查看安裝結果 ntp-4.2.6p5-29.el7.centos.x86_64 #用來提供時間同步服務 ntpdate-4.2.6p5-29.el7.centos.x86_64 #和某台服務器進行同步
修改/etc/ntp.conf文件
egrep -v "^$|#" /etc/ntp.conf [root@lgh1 ~]# egrep -v "^$|#" /etc/ntp.conf driftfile /var/lib/ntp/drift restrict default nomodify notrap nopeer noquery restrict 192.168.88.0 mask 255.255.255.0 nomodify notrap restrict 127.0.0.1 restrict ::1 #server 0.centos.pool.ntp.org iburst #server 1.centos.pool.ntp.org iburst #server 2.centos.pool.ntp.org iburst #server 3.centos.pool.ntp.org iburst server 127.127.1.0 fudge 127.127.1.0 stratum 10 includefile /etc/ntp/crypto/pw keys /etc/ntp/keys disable monitor
systemctl enable ntpd #啟動
其他兩個節點:lhg2和lgh3設置如下:
首先要安裝ntpd:yum install -y ntp #如果沒有安裝則要安裝
新增crontab -e
*/5 * * * * /usr/sbin/ntpdate -u 192.168.88.131 #表示每五分鍾和131時間同步一次
測試:(可以通過如下命令修改131的時間,看其他兩個節點是否能同步成功,親測成功)
date "+%Y-%m-%d %H:%M:%S"
date -s '2018-09-20 10:02:02'
2、hadoop高可用安裝
1.2.1、安裝規划--目錄
mkdir -p /opt/hadoop #存放hadoop文件,安裝目錄 chown -R hadoop:hadoop /opt/hadoop mkdir -p /opt/data/hadoop/hdfs #存放namenode和datanode的數據 mkdir -p /opt/data/hadoop/tmp #存放臨時文件 chown -R hadoop:hadoop /opt/data/hadoop/hdfs chown -R hadoop:hadoop /opt/data/hadoop/tmp
1.2.2、角色規划
解壓1.2.3、zookeeper安裝
cd /opt/hadoop tar -zxvf zookeeper-3.4.8.tar.gz ln -s zookeeper-3.4.8 zookeeper
配置環境變量
vim /etc/profile export ZOOKEEPER_HOME=/opt/hadoop/zookeeper export PATH=$ZOOKEEPER_HOME/bin:$ZOOKEEPER_HOME/conf:$PATH source /etc/profile
修改配置zoo.cfg
cd /opt/hadoop/zookeeper/conf cp zoo_sample.cfg zoo.cfg vim zoo.cfg tickTime=2000 #服務器與客戶端之間交互的基本時間單元(ms) initLimit=10 # 此配置表示允許follower連接並同步到leader的初始化時間,它以tickTime的倍數來表示。當超過設置倍數的tickTime時間,則連接失敗 syncLimit=5 # Leader服務器與follower服務器之間信息同步允許的最大時間間隔,如果超過次間隔,默認follower服務器與leader服務器之間斷開鏈接 dataDir=/opt/hadoop/zookeeper/data #保存zookeeper數據路徑 dataLogDir=/opt/hadoop/zookeeper/dataLog #保存zookeeper日志路徑,當此配置不存在時默認路徑與dataDir一致 clientPort=2181 #客戶端訪問zookeeper時經過服務器端時的端口號 server.1=lgh1:2888:3888 #表示了不同的zookeeper服務器的自身標識,作為集群的一部分,每一台服務器應該知道其他服務器的信息 server.2=lgh2:2888:3888 server.3=lgh3:2888:3888 maxClientCnxns=60 #限制連接到zookeeper服務器客戶端的數量
修改myid文件
cd /opt/hadoop/zookeeper mkdir data dataLog cd /opt/hadoop/zookeeper/data touch myid && echo 1 > myid
分發並修改myid文件
scp -r /opt/hadoop/zookeeper hadoop@lgh2:/opt/hadoop/
scp -r /opt/hadoop/zookeeper hadoop@lgh3:/opt/hadoop/
vim /opt/hadoop/zookeeper/data/myid #lgh2 修改為2
vim /opt/hadoop/zookeeper/data/myid #lgh3 修改為3
啟動並查看狀態
zkServer.sh start
zkServer.sh status
一台為leader狀態,其他兩個為follower狀態
1.2.4、解壓hadoop
cd /opt/hadoop tar -zxvf hadoop-2.7.7.tar.gz ln -s hadoop-2.7.7 hadoop
1.2.5、配置環境變量
export HADOOP_HOME="/opt/hadoop/hadoop-2.7.7"
export PATH=$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH
1.2.6、修改hadoop-env.sh、mapred-env.sh、yarn-env.sh
export JAVA_HOME=/usr/local/jdk1.8.0_201
1.2.7、修改hdfs-site.xml文件
<configuration> <property> <!-- 為namenode集群定義一個services name --> <name>dfs.nameservices</name> <value>mycluster</value> </property> <property> <!-- nameservice 包含哪些namenode,為各個namenode起名 --> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <property> <!-- 名為nn1的namenode 的rpc地址和端口號,rpc用來和datanode通訊 --> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>lgh1:8020</value> </property> <property> <!-- 名為nn2的namenode 的rpc地址和端口號,rpc用來和datanode通訊 --> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>lgh2:8020</value> </property> <property> <!--名為nn1的namenode 的http地址和端口號,web客戶端 --> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>lgh1:50070</value> </property> <property> <!--名為nn2的namenode 的http地址和端口號,web客戶端 --> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>lgh2:50070</value> </property> <property> <!-- namenode間用於共享編輯日志的journal節點列表 --> <!-- 指定NameNode的edits元數據的共享存儲位置。也就是JournalNode列表 該url的配置格式:qjournal://host1:port1;host2:port2;host3:port3/journalId journalId推薦使用nameservice,默認端口號是:8485 --> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://lgh1:8485;lgh2:8485;lgh3:8485/mycluster</value> </property> <property> <!-- journalnode 上用於存放edits日志的目錄 --> <name>dfs.journalnode.edits.dir</name> <value>/opt/hadoop/hadoop/tmp/data/dfs/jn</value> </property> <property> <!-- 客戶端連接可用狀態的NameNode所用的代理類 --> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> <property> <!-- 配置隔離機制方法,多個機制用換行分割,即每個機制暫用一行 --> <name>dfs.ha.fencing.methods</name> <value> sshfence shell(/bin/true) </value> </property> <!-- 使用sshfence隔離機制時需要ssh免登陸 --> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/hadoop/.ssh/id_rsa</value> </property> <!-- journalnode集群之間通信的超時時間 --> <property> <name>dfs.qjournal.start-segment.timeout.ms</name> <value>60000</value> </property> <!-- 指定副本數 --> <property> <name>dfs.replication</name> <value>2</value> </property> <!--namenode路徑--> <property> <name>dfs.namenode.name.dir</name> <value>/opt/data/hadoop/hdfs/nn</value> </property> <!--datanode路徑--> <property> <name>dfs.datanode.data.dir</name> <value>/opt/data/hadoop/hdfs/dn</value> </property> <!-- 開啟NameNode失敗自動切換 --> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <!-- 啟用webhdfs --> <property> <name>dfs.webhdfs.enabled</name> <value>true</value> </property> <!-- 配置sshfence隔離機制超時時間 --> <property> <name>dfs.ha.fencing.ssh.connect-timeout</name> <value>30000</value> </property> <property> <name>ha.failover-controller.cli-check.rpc-timeout.ms</name> <value>60000</value> </property> </configuration>
1.2.8、修改core-site.xml
<configuration> <property> <!-- hdfs 地址,ha中是連接到nameservice --> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property> <property> <!-- --> <name>hadoop.tmp.dir</name> <value>/opt/data/hadoop/tmp</value> </property> <!-- 指定zookeeper地址 --> <property> <name>ha.zookeeper.quorum</name> <value>lgh1:2181,lgh2:2181,lgh3:2181</value> </property> <!-- hadoop鏈接zookeeper的超時時長設置 --> <property> <name>ha.zookeeper.session-timeout.ms</name> <value>30000</value> <description>ms</description> </property> <property> <name>fs.trash.interval</name> <value>1440</value> </property> <property> <name>hadoop.proxyuser.hdfs.groups</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.hdfs.hosts</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.hive.groups</name> <value>*</value> </property> <property> <name>hadoop.proxyuser.hive.hosts</name> <value>*</value> </property> </configuration>
1.2.9、修改yarn-site.xml
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.log-aggregation-enable</name> <value>true</value> </property> <property> <name>yarn.log-aggregation.retain-seconds</name> <value>106800</value> </property> <property> <!-- 啟用resourcemanager的ha功能 --> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <property> <!-- 為resourcemanage ha 集群起個id --> <name>yarn.resourcemanager.cluster-id</name> <value>yarn-cluster</value> </property> <property> <!-- 指定resourcemanger ha 有哪些節點名 --> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property> <property> <!-- 指定第一個節點的所在機器 --> <name>yarn.resourcemanager.hostname.rm1</name> <value>lgh2</value> </property> <property> <!-- 指定第二個節點所在機器 --> <name>yarn.resourcemanager.hostname.rm2</name> <value>lgh3</value> </property> <property> <!-- 指定resourcemanger ha 所用的zookeeper 節點 --> <name>yarn.resourcemanager.zk-address</name> <value>lgh1:2181,lgh2:2181,lgh3: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> <property> <name>yarn.log.server.url</name> <value>http://lgh2:19888/jobhistory/logs/</value> </property> </configuration>
1.2.10、修改 slaves
lgh1
lgh2
lgh3
1.2.11、分發到其他兩個節點
scp /opt/hadoop/hadoop-2.7.7 hadoop@lgh2:/opt/hadoop/
scp /opt/hadoop/hadoop-2.7.7 hadoop@lgh3:/opt/hadoop/
1.2.12、格式化nomenode和zookeeper
[hadoop@lgh1 ~]$ hdfs namenode -format
[hadoop@lgh2 ~]$ hdfs namenode -bootstrapStandby
[hadoop@lgh1 ~]$ hdfs zkfc -formatZK #格式化zookeeper
1.2.13、啟動
stop-dfs.sh #關閉所有journalnode start-dfs.sh #啟動namenode,datanode,journalnode等組件 start-yarn.sh #啟動yarn [hadoop@lgh2 ~]$ /opt/hadoop/hadoop/sbin/yarn-daemon.sh start resourcemanager #這里一定要注意是yarn-daemon.sh,啟動resourcemanager [hadoop@lgh3 ~]$ /opt/hadoop/hadoop/sbin/yarn-daemon.sh start resourcemanager
1.2.14、查看進程
jps (圖片不協調。。。)
1.2.15、 訪問頁面(namenode)
192.168.88.131:50070
192.168.88.132:50070
1.2.16、測試namenode故障轉移
在節點192.168.88.132上執行:
[hadoop@lgh2 ~]$ /opt/hadoop/hadoop/sbin/hadoop-daemon.sh stop namenode
然后我們恢復192.168.88.132的namenode
[hadoop@lgh2 ~]$ /opt/hadoop/hadoop/sbin/hadoop-daemon.sh start namenode
該節點變成了standby節點。說明故障轉移成功
1.2.17、查看yarn頁面訪問
resourcemanager的故障測試:
[hadoop@lgh3 ~]$ /opt/hadoop/hadoop/sbin/yarn-daemon.sh stop resourcemanager #停掉lgh3節點上的resourcemanager
這里不截圖了,很成功
到這里hadoop的高可用就安裝完畢了(不過筆者這個中踩了不少坑,遇到一些奇葩問題,但是沒有記錄,總之,刪除掉生成的東西,多格式化幾次試試)
刪除的目錄有:
rm -rf /opt/data/hadoop/hdfs/*
rm -rf /opt/data/hadoop/tmp/*
rm -rf /opt/hadoop/hadoop/logs/*
二、基本原理
1、namenode高可用
我們知道namenode是整個hdfs的核心,如果namenode掛了,那么整個hdfs文件系統也不能提供服務,所以hadoop對hdfs提供了高可用的方案,即Hadoop HA,hdfs的高可用提供了兩種方案,一種是基於QJM(Quorum Journal Manager)的,一種是基於NFS的,我們用的一般都是基於QJM的,所以這里也是講基於QJM的高可用,高可用用來解決NameNode單點故障的問題。解決的方法是在HDFS集群中設置多個NameNode節點。那么提供多個namenode必定存在新的問題:
1、如何保證NameNode內存中元數據數據一致,並保證編輯日志文件的安全性。
2、多個NameNode如何協作
3、客戶端如何能正確地訪問到可用的那個NameNode。
4、怎么保證任意時刻只能有一個NameNode處於對外服務狀態
針對如上問題,hadoop提供了如下解決方案:
對於保證NameNode元數據的一致性和編輯日志的安全性,采用Zookeeper來存儲編輯日志文件。
兩個NameNode一個是Active狀態的,一個是Standby狀態的,一個時間點只能有一個Active狀態的 。
NameNode提供服務,兩個NameNode上存儲的元數據是實時同步的,當Active的NameNode出現問題時,通過Zookeeper實時切換到Standby的NameNode上,並將Standby改為Active狀態。
客戶端通過連接一個Zookeeper的代理來確定當時哪個NameNode處於服務狀態。
我們看一下hdfs高可用的架構圖:如下圖所示:
HDFS HA架構中有兩台NameNode節點,一台是處於活動狀態(Active)為客戶端提供服務,另外一台處於熱備份狀態(Standby)。
DataNode會將心跳信息和Block匯報信息同時發給兩台NameNode,DataNode只接受Active NameNode發來的文件讀寫操作指令。為了使備用節點保持其狀態與Active節點同步,兩個節點都與一組稱為“JournalNodes”(JN)的單獨守護進程通信。當Active節點執行任何名稱空間修改時,它會將修改記錄持久地記錄到大多數這些JN中。待機節點能夠從JN讀取編輯,並且不斷觀察它們對編輯日志的更改。當備用節點看到編輯時,它會將它們應用到自己的命名空間。如果發生故障轉移,Standby將確保在將自身升級為Active狀態之前已從JournalNodes讀取所有編輯內容。這可確保在發生故障轉移之前完全同步命名空間狀態。注意:必須至少有3個JournalNode守護進程,因為編輯日志修改必須寫入大多數JN。這將允許系統容忍單個機器的故障。您也可以運行3個以上的JournalNodes,但為了實際增加系統可以容忍的失敗次數,您應該運行奇數個JN(即3,5,7等)。請注意:當使用N JournalNodes運行時,系統最多可以容忍(N-1)/ 2個故障並繼續正常運行。
Zookeeper來保證在Active NameNode失效時及時將Standby NameNode修改為Active狀態。
故障檢測 - 集群中的每個NameNode計算機都在ZooKeeper中維護一個持久會話。如果計算機崩潰,ZooKeeper會話將過期,通知其他NameNode應該觸發故障轉移。Active NameNode選舉 - ZooKeeper提供了一種簡單的機制,可以將節點專門選為活動節點。如果當前活動的NameNode崩潰,則另一個節點可能在ZooKeeper中采用特殊的獨占鎖,指示它應該成為下一個活動的。
ZKFailoverController(ZKFC)是一個新組件,它是一個ZooKeeper客戶端,它還監視和管理NameNode的狀態。運行NameNode的每台機器也運行ZKFC,ZKFC負責:
1、運行狀況監視 : ZKFC定期使用運行狀況檢查命令對其本地NameNode進行ping操作。只要NameNode及時響應健康狀態,ZKFC就認為該節點是健康的。如果節點已崩潰,凍結或以其他方式進入不健康狀態,則運行狀況監視器會將其標記為運行狀況不佳。
2、ZooKeeper會話管理 :當本地NameNode運行正常時,ZKFC在ZooKeeper中保持會話打開。如果本地NameNode處於活動狀態,它還擁有一個特殊的“鎖定”znode。此鎖使用ZooKeeper對“短暫”節點的支持; 如果會話過期,將自動刪除鎖定節點
3、基於ZooKeeper的選舉 :如果本地NameNode是健康的,並且ZKFC發現沒有其他節點當前持有鎖znode,它將自己嘗試獲取鎖。如果成功,那么它“贏得了選舉”,並負責運行故障轉移以使其本地NameNode處於活動狀態。故障轉移過程類似於上述手動故障轉移:首先,必要時對先前的活動進行隔離,然后本地NameNode轉換為活動狀態。
元數據文件有兩個文件:fsimage和edits,備份元數據就是備份這兩個文件。JournalNode用來實時從Active NameNode上拷貝edits文件,JournalNode有三台也是為了實現高可用。
Standby NameNode不對外提供元數據的訪問,它從Active NameNode上拷貝fsimage文件,從JournalNode上拷貝edits文件,然后負責合並fsimage和edits文件,相當於SecondaryNameNode的作用。最終目的是保證Standby NameNode上的元數據信息和Active NameNode上的元數據信息一致,以實現熱備份。
2、resourcemanager高可用
首先我們來看一下官方提供的架構圖:如圖所示:
ResourceManager HA通過主動/備用架構實現 - 在任何時間點,其中一個RM處於活動狀態,並且一個或多個RM處於待機模式,等待活動RM出現故障或者宕機時機。轉換為活動的觸發器來自管理員(通過CLI)或啟用自動故障轉移時的集成故障轉移控制器。
RM可以選擇嵌入基於Zookeeper的ActiveStandbyElector來決定哪個RM應該是Active。當Active關閉或無響應時,另一個RM自動被選為Active,然后接管。請注意,不需要像HDFS那樣運行單獨的ZKFC守護程序,因為嵌入在RM中的ActiveStandbyElector充當故障檢測器和領導者選擇器而不是單獨的ZKFC守護程序。
當存在多個RM時,客戶端和節點使用的配置(yarn-site.xml)應該列出所有RM。客戶端,應用程序管理器ApplicationMaster(AM)和節點管理器NodeManager(NM)嘗試以循環方式連接到RM,直到它們到達活動RM。如果活動停止,他們將恢復循環輪詢,直到他們連接到新的RM
更多相關文章:hadoop生態系列
參考:
https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-site/ResourceManagerHA.html