1. 程式人生 > >hadoop高可用安裝和原理詳解

hadoop高可用安裝和原理詳解

本篇主要從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-project-dist/hadoop-hdfs/HDFSHighAvailabilityWithQJM.html

https://hadoop.apache.org/docs/stable/hadoop-yarn/hadoop-yarn-site/ResourceManagerHA.html

https://www.cnblogs.com/zsql/p/10736420.html

https://blog.csdn.net/hliq5399/article/details/7819