從零開始搭建HDFS高可用(HA)環境(使用QJM)

背景

      在Hadoop 1.x 中,Namenode是集羣的單點故障,一旦Namenode出現故障,整個集羣將不可用,重啓或者開啓一個新的Namenode才能夠從中恢復。值得一提的是,Secondary Namenode並沒有提供故障轉移的能力。集羣的可用性受到影響表現在:

  • 當機器發生故障,如斷電時,管理員必須重啓Namenode才能恢復可用。
  • 在日常的維護升級中,需要停止Namenode,也會導致集羣一段時間不可用。

架構演變

一、普通的HDFS架構

這裏寫圖片描述
這是最簡單的HDFS架構,一個集羣只有一個NameNode,一旦由於某種原因它發生故障這整個HDFS將無法工作。

二、兩個NN的HDFS架構

      在典型的HA集羣中我們配置兩個完全獨立的機器爲NameNode,但是,在同一時間一個設置爲Active狀態(活躍),一個設置爲Standby狀態(備用)。活躍狀態的機器保持和客戶端的讀寫服務,而備機只是用於發生故障時的快速切換。
      當活躍狀態的機器發生故障崩潰時備機是沒有對應的元數據信息的,故障後又不可能再從主機獲取了,所以爲了使備機的切換快速應該使主機和備機保持一個同步狀態。兩個NameNode爲了數據同步,會通過一組稱作JournalNode(3個以上且爲奇數個)的獨立進程進行相互通信。當active狀態的NameNode的命名空間有任何修改時,會告知大部分的JournalNodes進程。standby狀態的NameNode有能力讀取JNs中的變更信息,並且一直監控edit log的變化,把變化應用於自己的命名空間。standby可以確保在集羣出錯時,命名空間狀態已經完全同步了。
      爲了確保快速切換,Standby狀態的NameNode有必要知道集羣中所有數據塊的位置。爲了做到這點,所有的datanode必須配置兩個NameNode的地址,發送數據塊位置信息和心跳給他們兩個。
      對於HA集羣而言,確保同一時刻只有一個NameNode處於active狀態是至關重要的。否則,兩個NameNode的數據狀態就會產生分歧,可能丟失數據,或者產生錯誤的結果。爲了保證這點,JN必須確保同一時刻只有一個NameNode可以向自己寫數據。架構如下圖所示:
這裏寫圖片描述
      到這裏爲止初步實現了個HA的HDFS集羣,但是一旦故障發生備用的NameNode是不會主動轉爲活躍狀態的,人工切換。

三、自動切換的兩個NN的HDFS架構

      爲實現NN的自動切換需要引入Zookeeper。使用Zookeeper Quorum和ZKFailoverController process(簡稱ZKFC)這兩個組件。所以在部署HDFS的前我們需要使用至少三臺(奇數)機器搭建一個小小的ZK集羣。
Zookeeper的任務包括:

  • 失敗檢測:
    每個Namnode都在ZK中維護一個持久性session,如果Namnode故障,session過期,使用zk的事件機制通知其他Namenode需要故障轉移。
  • Namenode選舉:
    如果當前Active namenode掛了,另一個namenode會嘗試獲取ZK中的一個排它鎖,獲取這個鎖就表名它將成爲下一個Active NN。

在每個Namenode守護進程的機器上,同時也會運行一個ZKFC,用於完成以下任務:

  • Namenode健康檢查
  • ZK Session管理
  • 基於ZK的Namenode選舉

      如果ZKFC所在機器的Namenode健康狀態良好,並且用於選舉的znode鎖未被其他節點持有,則ZKFC會嘗試獲取鎖,成功獲取這個排它鎖就代表獲得選舉,獲得選舉之後負責故障轉移,如果有必要,會fencing掉之前的namenode使其不可用,然後將自己的namenode切換爲Active狀態。結構圖如下:
這裏寫圖片描述

環境搭建

      我準備了10臺linux(64位Centos6.5)服務器(node1~node10)使用ntpdate cn.pool.ntp.orghwclock --systohc將10臺機器時間設置一致,安裝jdk1.7,hadoop版本爲2.5.1,Zookpeer版本爲3.4.6。
資源下載:
Hadoop2.5.1
Zookpeer3.4.6

Zookpeer集羣搭建

切記先將防火牆關閉,我在第一次安裝時沒有關閉防火牆導致安裝失敗。

在搭建HDFS前我們要先搭建ZK集羣。選擇3臺機器(node8~node10)搭建。
1、將zookeeper3.4.6上傳至/home目錄下,解壓:tar -zxvf zookeeper-3.4.6.tar.gz
2、在zookeeper-3.4.6的conf目錄下創建一個名爲zoo.cfg的文件,文件內容爲:

tickTime=2000
dataDir=/opt/zookeeper
clientPort=2181
initLimit=5
syncLimit=2
server.1=node8:2888:3888
server.2=node9:2888:3888
server.3=node10:2888:3888

dataDir可以自己設置,nodeX根據自身服務器進行設置。server.X列出構成ZooKeeper服務的服務器。當服務器啓動時,它通過在數據目錄(即上面的dataDir)中查找文件myid來知道它是哪個服務器。所以我們需要在三個機器dataDir對應的目錄下創建一個myid文件,裏面的值就是X的值。

現在我們在三個機器上就可以啓動ZK了:

cd /home/zookeeper-3.4.6/bin
./zkServer.sh start

這裏寫圖片描述
你可以查看/home/zookeeper-3.4.6/bin下的日誌文件zookeeper.out來判斷是否出錯。

使用zkServer.sh status查看zk狀態:
node8:
這裏寫圖片描述
node9:

node10:
這裏寫圖片描述

ZK集羣啓動完畢後就不需要關閉了,現在我們來安裝高可用HDFS。

高可用HDFS搭建

一、配置文件的編寫

1、配置hadoop目錄下的hdfs-site.xml文件,添加如下配置:

<property>
    <name>dfs.nameservices</name>
    <value>hcpcluster</value> #這個名字自定義,記住這個值,在後續配置中一直使用
</property>
<property>
    <name>dfs.ha.namenodes.hcpcluster</name>
    <value>nn1,nn2</value> #選擇兩個節點作爲NN,名字設置爲nn1和nn2
</property>
<property>
    <name>dfs.namenode.rpc-address.hcpcluster.nn1</name>
    <value>node1:8020</value> #選擇node1爲NN
</property>
<property>
    <name>dfs.namenode.rpc-address.hcpcluster.nn2</name>
    <value>node2:8020</value> #選擇node2爲NN
</property>
<property>
    <name>dfs.namenode.rpc-address.hcpcluster.nn1</name>
    <name>dfs.namenode.http-address.hcpcluster.nn2</name>
    <value>node2:50070</value>
</property>
<property>
    <name>dfs.namenode.shared.edits.dir</name>    <value>qjournal://node5:8485;node6:8485;node7:8485/hcpcluster</value>  
</property>
<property>
    <name>dfs.client.failover.proxy.provider.hcpcluster</name>
    <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<property>
    <name>dfs.ha.fencing.methods</name>
    <value>sshfence</value>
</property>
<property>
    <name>dfs.ha.fencing.ssh.private-key-files</name>
    <value>/root/.ssh/id_rsa</value>
</property>
<property>
    <name>dfs.journalnode.edits.dir</name>
    <value>/opt/journalnode</value>
</property>

2、配置core-site.xml文件,添加如下配置:

<property>
    <name>fs.defaultFS</name>
    <value>hdfs://hcpcluster</value>
</property>   
<property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/hadoop-2.5</value>
</property>

3、配置到這裏還是沒有完成,到此整個HDFS集羣仍然做不到自動切換,若要則需要在hdfs-site.xml中添加如下配置:

<property>
   <name>dfs.ha.automatic-failover.enabled</name>
   <value>true</value>
</property>

在core-site.xml中添加如下配置:

<property>
    <name>ha.zookeeper.quorum</name>
    <value>node8:2181,node9:2181,node10:2181</value>
</property>

4、配置DataNode,我選擇node2,node3,node4爲DataNode,在slaves中配置:

node2
node3
node4

二、啓動journalnode

我選擇了node5,node6,node7作爲journalnode,現在需要將他們都啓動。

hdfs-daemon.sh start journalnode

這裏寫圖片描述
查看對應的日誌文件判斷是否啓動成功。

三、啓動HDFS

1、在其中一臺NameNode上進行格式化操作,使用以下命令:

hdfs namenode -format

2、在另外一臺NameNode中執行以下命令以格式化產生的元數據:

hdfs namenode -bootstrapStandby

其實我們也可以手動複製格式化產生的元數據到指定目錄(目錄在core-site.xml中配置了的)

3、初始化Zookeeper所需的狀態。在一個NameNode中執行以下命令:

hdfs zkfc -formatZK

這將創建一個znode用於ZK的自動故障轉移系統存儲數據。

4、啓動HDFS:

start-dfs.sh

這裏寫圖片描述

通過瀏覽器訪問兩個NameNode:
這裏寫圖片描述
這裏寫圖片描述
可以發現兩個NN其中一個在active狀態,另外一個在standby狀態。

四、檢測自動切換

      雖然我們可以發現兩個處於不同狀態的NN,但是這並不意味着當其中一個NN故障後另外一個會自動激活。
      現在我將node1中的namenode殺死,查看node2是否會切換:
這裏寫圖片描述
這裏寫圖片描述
很遺憾!沒有自動切換。
因爲node2沒有自動切換所有我們需要查看node2中zkfc的日誌:
這裏寫圖片描述
原來是我在core-site.xml中沒有配置

<property>
   <name>ha.zookeeper.quorum</name>
   <value>node8:2181,node9:2181,node10:2181</value>
</property>

再次啓動hdfs後Zookeeper將node2投爲active了,不打緊。
這裏寫圖片描述
這裏寫圖片描述
現在我殺死node2中的namenode:
這裏寫圖片描述
查看node1的狀態,成功轉爲active:
這裏寫圖片描述
搭建成功!!!

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