天天看點

基于zookeeper的hadoop HA實作

非HA弊端

HDFS叢集的分布式存儲是靠namenode節點(namenode負責響應用戶端請求)來實作。在非HA叢集中一旦namenode當機,雖然中繼資料不會丢失,但整個叢集将無法對外提供服務,導緻HDFS服務的可靠性不高,這在實際應用場景中顯然是不可行的。

HA機制

已知導緻服務可靠性不高的原因是namenode節點當機,那麼怎麼才能避免這個namenode節點當機呢?一個容易想到的解決方案是部署兩台namenode節點,形成主備模式(active/standby模式),這樣一旦active節點當機,standby節點立即切換到active模式。事實上HA機制就是采取的這種方案。要想實作該機制,需要解決以下問題:

1.為什麼選擇主備模式,而不是主主模式(active/active模式),也即讓兩個namenode節點都響應用戶端的請求

        一個顯然的前提是,兩台namenode節點需要儲存一緻的中繼資料。

        我們知道namenode節點是用來管理這些中繼資料的,響應用戶端請求時(上傳)需要增加中繼資料資訊,如果使用主主模式,那麼兩個節點都将對中繼資料進行寫操作,怎麼同步是個很困難的問題。是以,隻能有一台機器響應請求,也即處在active狀态的節點(可稱為主節點),而另一台namenode在主節點正常工作情況下僅用來同步active節點的中繼資料資訊,這個namenode稱為備用節點(處在standby狀态),可見,要解決的問題主要是怎麼同步active節點的中繼資料資訊。

2.怎麼同步兩個namenode節點的中繼資料

      響應用戶端請求的是active節點,是以隻有active節點儲存了最新的中繼資料。中繼資料分為兩部分,一部分是剛寫入新的中繼資料(edits),另一部分是合并後的較舊的(fsimage)。HA機制解決同步問題的方法是将active節點新寫入的edits中繼資料放在zookeeper叢集上(zookeeper叢集主要功能是實作少量資料的分布式同步管理),standby節點在active節點正常情況下隻需要将zookeeper叢集上edits檔案同步到自己的fsimage中就可以。

       ​​ Hadoop​​架構為這個叢集專門寫了個分布式應用qjournal(依賴zookeeper實作),實作qjournal的節點稱為journalnode。

3.怎麼感覺active節點是否當機,并将standby節點快速切換到active狀态?

        解決方案是專門在namenode節點上啟動一個監控程序,時刻監控namenode的狀态。對于處在active狀态的namenode,如果發現不正常就向zookeeper叢集中寫入一些資料。對于處在standby狀态的namenode,監控程序從zookeeper叢集中讀資料,進而感覺到active節點是否正常。如果發現異常,監控程序負責将standby狀态切換到active狀态。這個監控程序在hadoop中叫做zkfc(依賴zookeeper實作)。

4.如何在狀态切換時避免brain split(腦裂)?

        腦裂:active namenode工作不正常後,zkfc在zookeeper中寫入一些資料,表明異常,這時standby namenode中的zkfc讀到異常資訊,并将standby節點置為active。但是,如果之前的active namenode并沒有真的死掉,出現了假死(死了一會兒後又正常了,哈哈,是不是很搞笑),這樣,就有兩台namenode同時工作了。這種現象稱為腦裂。

        解決方案:standby namenode感覺到主用節點出現異常後并不會立即切換狀态,zkfc會首先通過ssh遠端殺死active節點的 namenode程序(kill -9 程序号)。但是(這樣還不行,驚訝),如果kill指令沒有執行成功咋辦??如果在一段時間内沒有收到執行成功的回執,standby節點會執行一個自定義腳本,盡量保證不會出現腦裂問題!這個機制在hadoop中稱為fencing(包括ssh發送kill指令,執行自定義腳本兩道保障)

解決上訴問題以後,基本上就實作了hadoop HA 。

HA實作

1.HA叢集規劃

機名  軟體  程序
hadoop01  jdk,hadoop,zookeeper  QuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
hadoop02  jdk,hadoop,zookeeper  QuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
hadoop03  jdk,hadoop,zookeeper  QuorumPeerMain(zookeeper),journalnode,datanode,nodemanager
hadoop04  jdk,hadoop  namenode,zkfc(active)
hadoop05  jdk,hadoop  namenode,zkfc
hadoop06  jdk,hadoop  resourcemanager
hadoop07  jdk,hadoop  resourcemanager      

(注:datanode,nodemanager一般放到一起。journalnode依賴zookeeper來實作,是以QuorumPeerMain(zookeeper),journalnode必須放一起!)

2.叢集安裝前的環境檢查

時間同步:

在指令行中做如下操作,來安裝ntpdate
yum install -y ntp
繼續在指令行中操作,進行同步時間
ntpdate 210.72.145.44 #中國國家授時中心      

關閉防火牆:

systemctl stop firewalld.service #停止firewall

systemctl disable firewalld.service #禁止firewall開機啟動

設定主機名映射(root使用者)

機器之間的主機名和IP建立映射關系

192.168.169.129 hadoop01
192.168.169.130 hadoop02
192.168.169.131 hadoop03
192.168.169.132 hadoop04
192.168.169.133 hadoop05
192.168.169.134 hadoop06
192.168.169.135 hadoop07      

建立專有的使用者(root使用者)

一般是建專有的hadoop使用者,不在root使用者上面搭建

建立組和使用者

這裡每台虛拟主機都應該有hadoop使用者

#先建立組cloud
groupadd cloud
#建立使用者并加入組cloud
useradd -g cloud hadoop
#修改使用者hadoop的密碼
passwd hadoop      

将hadoop使用者加到sodu清單

1、檢視/etc/sudoers的權限

ls -l /etc/sudoers      
基于zookeeper的hadoop HA實作

可以看的是隻讀權限,如果我們要修改就必須先改變該檔案的權限

2、修改權限

chmod 777 /etc/sudoers      
基于zookeeper的hadoop HA實作

3、将hadoop添加root權限

vim /etc/sudoers      
基于zookeeper的hadoop HA實作

在root下加入下面hadoop使用者

4、還原權限

chmod 440 /etc/sudoers

拷貝/etc/sudoers到其它主機

scp /etc/sudoers hadoop02:/etc/

scp /etc/sudoers hadoop03:/etc/

scp /etc/sudoers hadoop04:/etc/

scp /etc/sudoers hadoop05:/etc/

scp /etc/sudoers hadoop06:/etc/

scp /etc/sudoers hadoop07:/etc/

配置免密碼登入(hadoop使用者)

切換hadoop使用者

su hadoop      

進入到目前使用者的根目錄

cd ~      

檢視所有檔案

ls –la      

進入.ssh目錄

cd .ssh      

生産公鑰和私鑰(四個回車)

ssh-keygen -t rsa      

執行完這個指令後,會生成兩個檔案id_rsa(私鑰)、id_rsa.pub(公鑰)

基于zookeeper的hadoop HA實作

将公鑰拷貝到要免登陸的機器上

ssh-copy-id hadoop01
ssh-copy-id hadoop02
ssh-copy-id hadoop03
ssh-copy-id hadoop04
ssh-copy-id hadoop05
ssh-copy-id hadoop06
ssh-copy-id hadoop07      

這時會在hadoop02

主機的.ssh/下産生一個名為authorized_keys的檔案,這時通過 ssh hadoop02時可以直接免登陸進入主機 

如下:

基于zookeeper的hadoop HA實作

同理可以給其他機器也設定免密碼登入。

準備軟體

在/home/hadoop/下建立cloud檔案夾,用來安裝相關軟體,同時所用安裝包放在cloud下的soft-install檔案夾下,如:

cd /home/hadoop
mkdir cloud
mkdir soft-install      

上傳我們所需要的軟體到這個目錄

安裝jdk

解壓

tar -zxvf jdk-8u91-linux-x64.tar.gz -C /home/hadoop/cloud/      

配置環境變量

# 修改配置檔案
sudo vi /etc/profile
# 在最後下添加

export JAVA_HOME=/home/hadoop/cloud/jdk1.8.0_91
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar

# 重新整理配置檔案
source /etc/profile      

将jdk和環境變量分别拷貝到其他主機上

可以直接将cloud檔案夾複制過去

scp -r cloud/ hadoop02:/home/hadoop/
scp -r cloud/ hadoop03:/home/hadoop/
scp -r cloud/ hadoop04:/home/hadoop/
scp -r cloud/ hadoop05:/home/hadoop/
scp -r cloud/ hadoop06:/home/hadoop/
scp -r cloud/ hadoop07:/home/hadoop/      

将環境變量拷貝到其他主機下

sudo scp /etc/profile hadoop02:/etc/
sudo scp /etc/profile hadoop03:/etc/
sudo scp /etc/profile hadoop04:/etc/
sudo scp /etc/profile hadoop05:/etc/
sudo scp /etc/profile hadoop06:/etc/
sudo scp /etc/profile hadoop07:/etc/      

重新整理環境變量

source /etc/profile      

安裝zookeeper

如果不懂Zookeeper請參考:https://www.ibm.com/developerworks/cn/opensource/os-cn-zookeeper/

下載下傳位址:http://mirrors.hust.edu.cn/apache/zookeeper/

安裝

前面我們已經安裝的jdk,現在我們在hadoop01、hadoop02、hadoop03上安裝Zookeeper

1、解壓

tar -zxvf zookeeper-3.4.9.tar.gz -C /home/hadoop/cloud/      

2、修改Zookeeper的預設配置 conf/zoo_sample.cfg

mv zoo_sample.cfg zoo.cfg
vi zoo.cfg      

配置如下:

#修改dataDir指向我們資料
dataDir=/home/hadoop/cloud/zookeeper-3.4.9/data
#并在最後添加
server.1=hadoop01:2888:3888
server.2=hadoop02:2888:3888
server.3=hadoop03:2888:3888      

3、在/home/hadoop/cloud/zookeeper-3.4.9/目錄下建立data檔案夾

mkdir data      

4、在data檔案夾下建立myid檔案指明本機id

vi myid      

id 分别對應為hadoop01為1,hadoop02為2,hadoop03為3 後面我們再統一拷貝

5、複制zookeeper-3.4.8到hadoop02、hadoop03機器上并修改相應的myid

scp -r zookeeper-3.4.9/ hadoop02:/home/hadoop/cloud/zookeeper-3.4.9/
scp -r zookeeper-3.4.9/ hadoop03:/home/hadoop/cloud/zookeeper-3.4.9/      

啟動Zookeeper

分别在hadoop01、hadoop02、hadoop03上啟動Zookeeper

#執行/home/hadoop/cloud/zookeeper-3.4.9/bin目錄下的腳本啟動
./zkServer.sh start      

檢視zookeeper的狀态

./zkServer.sh status      

在bin/目錄下運作,運作結果如下說明成功(此時至少運作2台)

基于zookeeper的hadoop HA實作

其實我們可以找到leader 然後stop,會發現Zookeeper會立即切換Leader

安裝hadoop

安裝(現在hadoop01安裝,然後複制其他機器)

解壓

tar -zxvf hadoop-2.7.3.tar.gz -C /home/hadoop/cloud/      

配置環境變量

# 修改配置檔案
sudo vi /etc/profile
# 在最後下添加

export HADOOP_HOME=/home/hadoop/cloud/hadoop-2.7.3
export PATH=$PATH:$HADOOP_HOME/bin

# 重新整理配置檔案
source /etc/profile      

測試:

which hadoop      
基于zookeeper的hadoop HA實作

修改配置檔案(6個)

#hadoop2.x的配置檔案全部在$HADOOP_HOME/etc/hadoop下

cd /home/hadoop/cloud/hadoop-2.7.3/etc/hadoop

hadoop-env.sh

# The java implementation to use.
export JAVA_HOME=/home/hadoop/cloud/jdk1.8.0_91      

core-site.xml

<configuration>

    <!-- 指定hadoop運作時産生檔案的存儲路徑 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/home/hadoop/cloud/hadoop-2.7.3/tmp</value>
    </property>

    <!-- 指定hdfs的nameservice為ns1 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://ns1</value>
    </property>

    <!-- 指定zookeeper位址,多個用,分割 -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
    </property>

</configuration>      

hdfs-site.xml

<configuration>
    <!-- dfs.nameservices 命名空間的邏輯名稱,多個用,分割 -->
    <property>
      <name>dfs.nameservices</name>
      <value>ns1</value>
    </property>

    <!-- 指定ns1下有兩個namenode,分别是nn1,nn2 -->
    <property>
      <name>dfs.ha.namenodes.ns1</name>
      <value>nn1,nn2</value>
    </property>

    <!-- 指定nn1的RPC通信位址 -->
    <property>
      <name>dfs.namenode.rpc-address.ns1.nn1</name>
      <value>hadoop04:8020</value>
    </property>

    <!-- 指定nn1的HTTP通信位址 -->
    <property>
      <name>dfs.namenode.http-address.ns1.nn1</name>
      <value>hadoop04:50070</value>
    </property>

    <!-- 指定nn2的RPC通信位址 -->
    <property>
      <name>dfs.namenode.rpc-address.ns1.nn2</name>
      <value>hadoop05:8020</value>
    </property>

    <!-- 指定nn2的HTTP通信位址 -->
    <property>
      <name>dfs.namenode.http-address.ns1.nn2</name>
      <value>hadoop05:50070</value>
    </property>

    <!-- 指定namenode的中繼資料存放的Journal Node的位址,必須基數,至少三個 -->
    <property>
      <name>dfs.namenode.shared.edits.dir</name>
      <value>qjournal://hadoop01:8485;hadoop02:8485;hadoop03:8485/ns1</value>
    </property>

    <!--這是JournalNode程序保持邏輯狀态的路徑。這是在linux伺服器檔案的絕對路徑-->
    <property>
      <name>dfs.journalnode.edits.dir</name>
      <value>/home/hadoop/cloud/hadoop-2.7.3/journal/</value>
    </property>

    <!-- 開啟namenode失敗後自動切換 -->
    <property>
      <name>dfs.ha.automatic-failover.enabled</name>
      <value>true</value>
    </property>

    <!-- 配置失敗自動切換實作方式 -->
    <property>
      <name>dfs.client.failover.proxy.provider.ns1</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>

    <!-- 配置sshfence隔離機制逾時時間30秒 -->
    <property>
       <name>dfs.ha.fencing.ssh.connect-timeout</name>
       <value>30000</value>
    </property>
</configuration>      

mapred-site.xml.template

需要重命名: mv mapred-site.xml.template mapred-site.xml

<configuration>
    <!-- 通知架構MR使用YARN -->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
</configuration>      

yarn-site.xml

<configuration>
    <!-- 開啟RM高可用 -->
    <property>
       <name>yarn.resourcemanager.ha.enabled</name>
       <value>true</value>
    </property>
    <!-- 指定RM的cluster id -->
    <property>
       <name>yarn.resourcemanager.cluster-id</name>
       <value>yrc</value>
    </property>
    <!-- 指定RM的名字 -->
    <property>
       <name>yarn.resourcemanager.ha.rm-ids</name>
       <value>rm1,rm2</value>
    </property>
    <!-- 分别指定RM的位址 -->
    <property>
       <name>yarn.resourcemanager.hostname.rm1</name>
       <value>hadoop06</value>
    </property>
    <property>
       <name>yarn.resourcemanager.hostname.rm2</name>
       <value>hadoop07</value>
    </property>
    <!-- 指定zk叢集位址 -->
    <property>
       <name>yarn.resourcemanager.zk-address</name>
       <value>hadoop01:2181,hadoop02:2181,hadoop03:2181</value>
    </property>
    <property>
       <name>yarn.nodemanager.aux-services</name>
       <value>mapreduce_shuffle</value>
    </property>
  </configuration>      

修改/home/hadoop/cloud/hadoop-2.7.3/etc/hadoop/slaves檔案

slaves檔案是指定子節點的位置

要在hadoop4上啟動hdfs,按照叢集配置,需要指定datanode在hadoop01,hadoop02,hadoop3上

要在hadoop6上啟動yarn,按照叢集配置,需要指定nodemanager在hadoop01,hadoop02,hadoop3上。

vi   slaves

#子節點的位置
hadoop01
hadoop02
hadoop03      

并在 hadoop-2.7.3檔案下 建立tmp檔案:

mkdir tmp      

将配置好的檔案拷貝到其他主機

scp -r hadoop-2.7.3/ hadoop02:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop03:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop04:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop05:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop06:/home/hadoop/cloud/hadoop-2.7.3/
scp -r hadoop-2.7.3/ hadoop07:/home/hadoop/cloud/hadoop-2.7.3/      

将環境變量拷貝到其他主機下

sudo scp /etc/profile hadoop02:/etc/
sudo scp /etc/profile hadoop03:/etc/
sudo scp /etc/profile hadoop04:/etc/
sudo scp /etc/profile hadoop05:/etc/
sudo scp /etc/profile hadoop06:/etc/
sudo scp /etc/profile hadoop07:/etc/      

重新整理環境變量

source /etc/profile      

啟動

啟動的時候注意啟動順序

1、啟動zookeeper(在hadoop01、02、03)

./zkServer.sh start 

  檢視zookeeper狀态:./zkServer.sh status, 正确的狀态是一個leader,兩個follower。

2、啟動journal node(在hadoop01、02、03)

#hadoop-2.7.3/sbin下
./sbin/hadoop-daemon.sh start journalnode      

啟動成功後會多出一個JournalNode程序。

3.格式化HDFS

 在hadoop04上執行格式化指令:./bin/hadoop namenode -format

并把/home/hadoop/cloud/hadoop-2.7.3/tmp 檔案夾拷貝到另一台namenode的目錄下

scp -r /home/hadoop/cloud/hadoop-2.7.3/tmp hadoop05:/home/hadoop/cloud/hadoop-2.7.3/      

4.格式化zkfc

在hadoop4上執行格式化指令:./bin/hdfs zkfc -formatZK

    格式化成功後會在zookeeper叢集建立新的檔案路徑(該路徑下存放zkfc監控namenode節點的資訊)

5、啟動zkfc來監控NN狀态(在hadoop04、05)

./sbin/hadoop-daemon.sh start zkfc      

6、啟動HDFS(namenode)(在hadoop04即可)

#hadoop-2.7.3/sbin下
./sbin/start-dfs.sh      

7、啟動YARN

在hadoop06上執行./sbin/start-yarn.sh

在hadoop07上執行./sbin/yarn-daemon.sh start resourcemanager

通過浏覽器測試如下:

http://192.168.169.132:50070/

http://192.168.169.133:50070/

可以看出hadoop04的namenode是處于一種standby狀态,那麼hadoop05應該是處于active狀态

hdfs haadmin -getServiceState nn1

基于zookeeper的hadoop HA實作

hdfs haadmin -getServiceState nn2

基于zookeeper的hadoop HA實作

把hadoop05(192.168.169.133)的namenode 程序kill掉

基于zookeeper的hadoop HA實作

hdfs haadmin -getServiceState nn1

基于zookeeper的hadoop HA實作

hdfs haadmin -getServiceState nn2

基于zookeeper的hadoop HA實作

可以看出hadoop04的namenode是處于一種active狀态,hadoop05不能通路

重新啟動hadoop05的namenode

./sbin/hadoop-daemon.sh start namenode

hadoop05會變成standby狀态

檢視YARN的狀态

http://192.168.169.134:8088/

輸入:http://192.168.169.135:8088/ 會跳轉到 http://hadoop06:8088/

繼續閱讀