利用QJM實現HDFS的HA策略部署與驗證工作記錄分享

1、概述 

    Hadoop2.X中的HDFS(Vsersion2.0)相比於Hadoop1.X增加了兩個重要功能,HAFederationHA解決了Hadoop1.X  Namenode中一直存在的單點故障問題,HA策略通過熱備的方式爲主NameNode提供一個備用者,並且這個備用者的狀態一直和主Namenode的元數據保持一致,一旦主NameNode掛了,備用NameNode可以立馬轉換變換爲主NameNode,從而提供不間斷的服務。另外,Federation特性,主要是允許一個 HDFS 集羣中存在多個 NameNode 同時對外提供服務,這些 NameNode 分管一部分目錄(水平切分),彼此之間相互隔離,但共享底層的 DataNode 存儲資源。本文檔主要是總結我自己個人利用爲QJMQuorum Journal Manager)爲公司測試集羣(hadoop2.2.0)部署HA策略的過程以及自己在部署過程中遇到的一些問題。

2、HDFSHA基本架構

    先來看個手動擋切換的HA架構圖:

wKiom1PLxCWRWGoyAAFSXeD1ZAw943.jpg

    在一個典型的 HDFS  HA 場景中,通常由兩個NameNode 組成,一個處於Active狀態,另一個處於Standby狀態。Active NameNode 對外提供服務,比如處理來自客戶端的 RPC 請求,而 Standby NameNode 則不對外提供服務,僅同步 Active NameNode的狀態,以便能夠在它失敗時快速進行切換。

爲了能夠實時同步 Active Standby 兩個 NameNode 的元數據信息(實際上editlog,需提供一個共享存儲系統,可以是 NFSQJQuorum Journal Manager)或者 BookeeperActive  NameNode 將數據寫入共享存儲系統,我們可以在Active  NameNode50070端口上看到相應的NameNode Journal  Status信息:wKiom1PLxL_TKDIFAAIHocrMywM300.jpg

同時Standby NameNode監聽該系統(QJM管理下的Journalnode進程對應的存儲路徑),一旦發現有新數據寫入,則讀取這些數據,並加載到自己內存中,以保證自己內存狀態與 Active NameNode 保持基本一致,那麼在緊急情況下 standby NameNode便可快速切爲Active NameNode。另外,在Hadoop1.X中的Secondary NameNode或者自己通過nfs熱備的NameNode信息在Hadoop2.X中已經不再需要了,他們被Standby NameNode取代了。 在Yarn的官網中,我還看到一段關於JournalNode錯誤兼容性信息:wKiom1PLxWHRVtBxAAQOByhmflQ995.jpg

大概意思是主備NameNode 之間通過一組JournalNode 同步元數據信息(我的通俗理解就是QJM類似一個數據池,池裏邊裝着多個JournalNode進程存儲editlogActive NameNode往池裏邊的JournalNode進程寫editlogStandBy NameNode向池裏邊的JournalNode取數據同步),一條數據只要成功寫入多數 JournalNode 即認爲寫入成功。啓動的JournalNode的個數必須爲奇數個。如果你的HA策略中啓動了NJournalNode進程那麼整個QJM最多允許(N-1)/2個進程死掉,這樣才能保證editLog成功完整地被寫入。比如 3 JournalNode 時,最多允許 1 JournalNode掛掉,5 JournalNode 時,最多允許 2 JournalNode 掛掉。

3、  HDFS HA部署

 3.1、部署和測試環境

HDFS HA的部署和驗證是在公司的測試集羣中完成,其中測試集羣中數據節點一共有4個主機名分別爲hadoop-slave1hadoop-slave02hadoop-slave03hadoop-slave04master節點的主機名爲hadoop-master。因爲JournalNodeZookeeper進程是非常輕量級的,可以其他服務共用節點。現在的部署情況是:

hadoop-master:作爲Active NameNode

haoop-slave01:  作爲StandBy NameNode

hadoop-slave02: 作爲DataNode,並且啓動一個JournalNode、啓動一個Zookeeper

hadoop-slave03: 作爲DataNode,並且啓動一個JournalNode、啓動一個Zookeeper

hadoop-slave04: 作爲DataNode,並且啓動一個JournalNode、啓動一個Zookeeper

其他軟件:

Apache Hadoop 2.2.0JDK1.6


3.2、修改配置文件

主要配置${HADOOP_HOME}/etc/hadoop/下的hdfs-site.xml。下面是一些配置參數以及說明:

(1)      dfs.nameservices

HDFS的命名服務邏輯名稱,可以自己定義。在已經配置HA策略的HDFS會用到這個邏輯名稱,同時該名稱也會被基於HDFS的系統用,例如HBASE等。另外,如果需要啓動HDFS Federation的話,可以通過該參數指定多個服務邏輯名稱,用“,”作爲分隔符。

 我的配置如下:

<property>
   <name>dfs.nameservices</name>
    <value>mycluster</value>
    <description>Logical name forthis new nameservice</description>
</property>

(2)     dfs.ha.namenodes.[$nameserviceID]

命名服務下面包含的NameNode列表,可爲每個NameNode 指定一個自定義的 ID 名稱,比如命名服務 testCluster 下有兩個 NameNode,分別命名爲 nn1 nn2(到目前爲止一個命名服務下最多包含2NameNode),我的配置如下:

<property>
    <name>dfs.ha.namenodes.testCluster</name>
    <value>nn1,nn2</value>
    <description>Unique identifiers for each NameNode in the nameservice </description>
</property>

(3)      dfs.namenode.rpc-address.[$nameserviceID].[$name node ID]

   這個參數很容易理解,主要是爲每個NameNode設置RPC地址,我的配置如下:

<property>
   <name>dfs.namenode.rpc-address.testCluster.nn1</name>
    <value>hadoop-master:8020</value>
</property>
<property>
   <name>dfs.namenode.rpc-address.testCluster.nn2</name>
   <value>hadoop-slave01:8020</value>
</property>

(4)      dfs.namenode.http-address.[$nameserviceID].[$name node ID]

這個參數主要是爲NameNode設置對外的HTTP地址, 通過此配置的指定你可以執行在瀏覽器中管理HDFS界面等操作。我的配置如下:

<property>
    <name>dfs.namenode.http-address.testCluster.nn1</name>
    <value>hadoop-master:50070</value>
</property>
<property>
    <name>dfs.namenode.http-address.testCluster.nn2</name>
    <value>hadoop-slave01:50070</value> 
</property>

(5)      dfs.namenode.shared.edits.dir

設置一組JournalNodeURL地址,ActiveNameNode會將Edit Log寫入這些JournalNode所配置的本地目錄(可以用nfs等共享文件系統,由參數dfs.journalnode.edits.dir控制)中,而StandByNameNode通過DataNode的心跳通知去讀取這些Edit Log,並且作用在內存中的目錄樹中,其配置格式爲:qjournal://host1:port1;host2:port2;host3:port3/journalId,我的配置如下:

<property>
       <name>dfs.namenode.shared.edits.dir</name>
       <value>qjournal://hadoop-slave02:8485;hadoop-slave03:8485;hadoop-slave04:8485/testcluster</value>
        <description>journalNodeList</description>
</property>

(6)      dfs.journalnode.edits.dir

這個就是剛剛提到的JournalNode所在節點上的一個目錄,用於存放 editlog 和其他狀態信息,該參數只能設置一個目錄,你可以對磁盤做 RIAD 提高數據可靠性。

<property>
       <name>dfs.journalnode.edits.dir</name>
        <value>/home/hadoop/hadoop-2.2.0/journal/node/local/data</value>
</property>

(7)      dfs.client.failover.proxy.provider.[$nameserviceID]

該參數設置HDFS客戶端與ActiveName進行交互的JAVA實現類,HDFS客戶端通過該參數來尋找到集羣中的Active NameNode,此類默認實現ConfiguredFailoverProxyProvider,我的配置如下:

<property>
        <name>dfs.client.failover.proxy.provider.testcluster</name>
       <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>

(8)      dfs.ha.fencing.methods

這個參數比較重要,主要用於在主備節點切換時實現隔離機制的,在官方網站中做了相當詳細的配置說明,其大概意思爲:主備架構解決單點故障問題時,必須要認真解決的是腦裂問題,即出現兩個 master 同時對外提供服務,導致系統處於不一致狀態,可能導致數據丟失等潛在問題。在 HDFS HA中,JournalNode 只允許一個 NameNode 寫數據,不會出現兩個 Active NameNode 的問題,但是,當主備切換時,之前的 Active NameNode 可能仍在處理客戶端的 RPC 請求,爲此,需要增加隔離機制(fencing)將之前的 Active NameNode 殺死。HDFS 允許用戶配置多個隔離機制,當發生主備切換時,將順次執行這些隔離機制,直到一個返回成功。Hadoop 2.0 內部打包了兩種類型的隔離機制,分別是 shell  sshfence

  1sshfence方式

sshfence 通過 ssh 登錄到前一個 ActiveNameNode 並將其殺死。爲了讓該機制成功執行,需配置免密碼 ssh 登陸(注意:這個爲主備節點配置雙向的RSA免密碼登陸),這可通過參數 dfs.ha.fencing.ssh.private-key-files 指定一個私鑰文件。我的配置如下:

<property>
        <name>dfs.ha.fencing.methods</name>
       <value>sshfence</value>
</property>
<property>
       <name>dfs.ha.fencing.ssh.private-key-files</name>
       <value>/home/hadoop/.ssh/id_rsa</value>
</property>

另外,在設置一個超時時間,一旦 ssh 超過該時間,則認爲執行失敗。我的配置如下:

<property>
   <name>dfs.ha.fencing.ssh.connect-timeout</name>
    <value>30000</value>
</property>

  2  shell方式(我沒有采用這種方式)

         執行自定義的Shell腳本命令隔離舊的ActiveNameNode。相比於sshfence方式,個人認爲這種方式有個好處就是,你在shell腳本里邊可以將之前的 Active NameNode 直接kill掉,然後立馬啓動NameNode,此時剛剛啓動的NameNode就是立馬處於一個StandBy狀態,立馬就可以進入HA狀態,如果採用sshfence方式還要手動自己重啓剛剛被kill掉的NameNode從而才能進入HA(這些的前提都是,採用手動HA方式,之前的Acitve NameNode不是宕機而僅僅是NameNode進程掛掉)。配置可以爲:

<property>
   <name>dfs.ha.fencing.methods</name>
   <value>shell(/path/to/my/script.sh arg1 arg2 ...)</value>
</property>

注意, Hadoop 中所有參數將以環境變量的形似提供給該 shell,但所有的“.”被替換成了“_”,比如“dfs.namenode.rpc-address.ns1.nn1”變爲“dfs_namenode_rpc-address”。


3.3、啓動各種服務

HDFS集羣進程啓動的大概順序爲:啓動所有的JournalNodeà啓動nn1nn2à啓動所有DataNode。具體詳細步驟如下:

(1)          啓動所有JournalNode

在所有的配置有JournalNode的服務節點上,以我的配置就是在hadoop-slave02hadoop-slave03hadoop-slave04上分別執行:

$HADOOP_HOME/sbin/hdfs-daemon.sh startjournalnode

(2)          初始化JournalNode

此步驟要注意的是,如果你是將非HA HDFS的集羣轉化成爲HA HDFS那麼這一步驟就需要,如果都是HA HDFS就不需要執行此步驟。該步驟的主要作用是將非HA HDFSNameNodeedit log去初始化JourNalnodes。具體操作在nn1上執行:

 $HADOOP_HOME/bin/hdfs namenode -initializeSharedEdits [-force | -nonInteractive]

此命令默認是交互式的,需要用戶輸入各種YOR N,如果嫌麻煩就直接執行:

$HADOOP_HOME/bin/hdfs namenode–initializeSharedEdits –force

(3)          啓動nn1nn2

子步驟1

進入nn1,如果是新集羣則format(注意,如果不是新集羣千萬不要format):

$HADOOP_HOME/bin/hadoop namenode -format

子步驟2:進入nn1,接着啓動nn1:

hadoop-daemon.sh start namenode

子步驟3:進入nn2,執行下面命令讓nn2nn1上將最新的FSp_w_picpath信息拉回來:

注意:如果是nn2NameNode已經是被format掉了或者是將非HA HDFS的集羣轉化成爲HA HDFS則不需要執行這一個步驟。

$HADOOP_HOME/bin/hdfs namenode -bootstrapStandby -force

子步驟4進入nn2,然後啓動nn2:

hadoop-daemon.sh start namenode

子步驟5啓動所有的DataNode

在各個DataNode節點執行:

hadoop-daemon.sh start datanode

或者直接在nn1節點直接執行:

hadoop-daemons.sh start namenode

各個服務到現在爲止已經啓動完畢,主備節點都還處於StandBy狀態。我們可以看到主備節點的信息:

wKioL1PLyVTyFREgAAFx2OhoUj8896.jpg

wKiom1PLyDrj0IDwAAF2lMzHTf8341.jpg

    在這裏說說一個遇到的“錯誤”問題,我在分別啓動nn1nn2之後,還沒有將其中一個切換爲Acive NameNode時,在nn1nn2的日誌上都報了以下這個“錯誤”:

wKioL1PLyarhnl5SAAxOUiZjzUY964.jpg

其實這個錯誤信息完全可以不用管,出現這個問題原因上面信息已經很明顯了,只要接下來將其中一個切換成Acive NameNodeok了。


3.4、手動切換Active NameNode

    nn1nn2啓動後都處於StandBy狀態,此時都不能夠對外提供服務,現在需要將nn1切換爲Active NameNode,進入nn1節點輸入:

$HADOOP_HOME/bin/hdfs haadmin-transitionToActive nn1

切換後我們再看看50070頁面,nn1已經被切換爲Active了:

wKioL1PLykjC_HGjAAHDEdwSPbc419.jpg

wKiom1PLyS7iK41rAAF9b0gK81Q739.jpg

在來看看之前還沒有切換Acive NameNode的“錯誤”信息已經消失了,下面分別是nn1nn2的日誌信息,非常正常:

wKioL1PLyrfyTWhbAAas2ZqM84I807.jpg

wKiom1PLyZ3R7b8UAAiUOLt1PdY291.jpg

另外,如果你現在想將nn2轉化爲Acive NameNode,則在進入nn2所在節點,輸入命令:

$HADOOP_HOME/bin/hdfs haadmin-failover --forcefence --forceactive nn1 nn2

看看nn2上的日誌:

wKiom1PLyhPTS5P4AA5mkf9FZZk906.jpg

在這裏說說我在切換時遇到過的幾個小問題:

  • 在住備節點上一定要配置雙向的RSA免密碼登陸,不然再切換時會出錯,sshfence方式不能找到舊的Active NameNode,直接被reject掉。

  • 第二,在切換的過程中我遇到了這個錯誤:

wKiom1PLymCDvQ-tAAnc5Wu1wVg264.jpg

這個是權限問題,解決方法是直接在core-site.xml文件添加下面權限控制選項:

<property>
   <name>hadoop.http.filter.initializers</name>
    <value>org.apache.hadoop.security.AuthenticationFilterInitializer</value>
</property>
<property>
   <name>hadoop.http.authentication.type</name>
    <value>simple</value>
</property>
<property>
   <name>hadoop.http.authentication.token.validity</name>
    <value>36000</value>
</property>
<property>
   <name>hadoop.http.authentication.signature.secret.file</name>
    <value>/home/hadoop/hadoop-http-auth-signature-secret</value>
</property>
<property>
   <name>hadoop.http.authentication.cookie.domain</name>
    <value></value>
</property>
<property>
   <name>hadoop.http.authentication.simple.anonymous.allowed</name>
    <value>true</value>
</property>

然後建立/home/hadoop/hadoop-http-auth-signature-secret文件,並且在文件寫入訪問用戶,我寫入的是hadoop,然後將這個文件scp到各個節點,問題解決。

  • 如果你將Active NameNodenn1轉到nn2後,在各個DataNode日誌出現一個“錯誤”信息:

wKioL1PLy9KB-KjfAAUasSkPxVg154.jpg

其實這個是我意料之中的“錯誤”信息,其實是沒有任何問題的。因爲,當你的Acive NameNodenn1切換至nn2時,nn1就會被kill(即hadoop-msater中的NameNode進程會被kill掉),在上面切換日誌我標註紅方框的地方已經很清楚了。此時,各個DataNode還是會同時向Active NameNodeStandBy NameNode同時發送心跳信息的,因爲nn1已經被kill掉了,所有會報這個信息,對系統沒有任何影響,切換後正常使用,如果你重啓nn1則不會再報信息了,新啓動的nn1是處於StandBy模式的。

    我們知道,StandByNameNode是不處理DataNodeRPC請求的,那麼各個DataNode爲什麼還會同時向Active NameNodeStandBy NameNode同時發送心跳呢?這是因爲這2個心跳的用途是不同的,各個DataNodeActive NameNode發送心跳主要是彙報數據塊的狀態信息,而向StandBy NameNode發心跳的主要目的是通知StandBy NameNode告訴它Active NameNode元數據發生了改變,要求StandBy NameNodeQJM區下載更改過的Edit Log信息。


3.5、配置自動切換模式

自動切換模式的實現需要下面兩個組建的額支持:

(1)      Zookeeper實例

需要質數個Zookeeper實例,在本集羣我一個啓用了3Zookeeper實例,分別部署在hadoop-slave02hadoop-slave03hadoop-slave04中。

(2)      ZKFailoverController(簡稱“ZKFC”

ZKFC 是一個 Zookeeper客戶端,負責監控和管理 NameNode 的狀態,每臺運行 NameNode的機器上也會運行一個 ZKFC 進程。

  • 健康狀況監控:

ZKFC 週期性地與本地的NameNode 交互,執行一些健康狀況監測命令。

  • Zookeeper session 管理:

如果本地 NameNode 是健康的,則會持有Zookeeper 上一個 znode,如果它是 Active 的,會持有 zookeeper 的僅有的一個特殊 znode,該 znode 類型爲 ephemeral,一旦 namenode 掛掉後,會自動消失。

  • 基於 zookeeper 的選舉:

如果本地 NameNode 是活的,而沒有其他 Namenode持有特殊的 znodeZKFC 將嘗試獲取這個 znode,一旦獲取成功後,則認爲它“贏得了選舉”,進而隔離之前的Active namenode,自己轉換爲新的 Active namenode。其大概結構如下圖:

wKiom1PLyy3gOWxrAAKQ0Uj7IRQ128.jpg

具體配置步驟:

步驟1:關閉集羣修改hdfs-site.xml配置文件,增加自動切換選項:

<property>

    <name>dfs.ha.automatic-failover.enabled</name>

    <value>true</value>

</property>

步驟2:編輯core-site.xml文件,添加Zookeeper實例:

<property>

    <name>ha.zookeeper.quorum</name>

    <value>hadoop-slave02:2181,hadoop-slave03:2181,hadoop-slave04:2181</value>

</property>

步驟3:啓動節點上的zookeeper實例:

分別進入hadoop-slave02hadoop-slave03hadoop-slave04節點執行:

$ZOOKEEPER_HOME/bin/zkServer.sh start

Zookeeper實例對應的進程名爲:

wKiom1PLy5DSX-H5AAB-yleplXQ550.jpg

步驟4:初始化zookeeper

注意:這個步驟是針對第一次啓動zookeeper實例用的,如果你的zookeeper實例不是第一次啓動則不需要執行此命令。

$HADOOP_HOME/bin/hdfs zkfc -formatZK

步驟5:啓動 JournalNodeNameNode DataNode

步驟6:啓動ZKFC

分別進入hadoop-masterhadoop-slave1即在各個 NameNode 節點上執行:

$HADOOP_HOME/sbin/hadoop-daemon.sh startzkfc

ZKFC對應的進程名爲:

wKioL1PLzKvzOi9OAACkDfchk2U559.jpg

要注意的一點是:我們最先啓動的NameNodeActive NameNode。現在爲止配置完畢,驗證請看下面一小節。

4、 HDFS HA機制的可用性驗證

4.1手動切換模式驗證

這裏我使用的驗證方法主要是模擬ActiveNameNode進程死掉的情況,另外Active NameNode所在節點發生宕機的情況也是一樣的。現在集羣中nn1Active NameNodenn2StandBy NameNode,具體步驟:

步驟1:進入nn1所在節點即hadoop-master,運行kill -9  $NameNodePIDnn1殺死(此時集羣中只有一個StandByNameNode)。

步驟2:往集羣上傳文件,或者執行hadoop fs相關命令提示連接不到(此時,集羣中沒有Active NameNode來處理客戶端的RPC請求)。看錯誤信息:

wKioL1PLzTqhS06nAAd7j72C53I301.jpg


步驟3:恢復集羣,將StandBy NameNode轉換爲Active NameNode。進入nn2所在節點即hadoop-slave01執行:

$HADOOP_HOME/bin/hdfshaadmin -transitionToActive nn2

此時,nn2已經變成爲Active NameNode,看50070

wKioL1PLzYny5_EIAAGPec3rbko752.jpg

步驟4:再次執行hadoop fs相關命令或者上傳文件,一切正常。

步驟5:另外,不要忘記集羣雖然是恢復了,但是此時已經沒有了StandBy NameNode了,這是直接進入nn1所在節點啓動NameNode進程,此時nn1Standby NameNode

wKiom1PLzG_DvTUBAAGmyp--GSc442.jpg

當目前爲止,一起驗證以及恢復已經完成。各個服務的日誌也恢復了正常。


4.2、自動切換模式驗證

自動切換模式的驗證和手動切換基本一樣,還是手動killActive NameNode進程,觀察集羣是否會自動恢復,將備用節點轉換爲Active NameNode。經過測試,當手動killActive NameNode後,Standby NameNode成功地自動轉換爲Active NameNode繼續服務於個個DataNode


參考文獻:

[1] http://hadoop.apache.org/docs/r2.2.0/hadoop-yarn/hadoop-yarn-site/HDFSHighAvailabilityWithQJM.html

[2] http://www.sizeofvoid.net/hadoop-2-0-namenode-ha-federation-practice-zh/

[3] http://yanbohappy.sinaapp.com/?p=205

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章