前面學習了使用命令hdfs haadmin -failover手動進行故障轉移,在該模式下,即使現役NameNode已經失效,系統也不會自動從現役NameNode轉移到待機NameNode,下面學習如何配置部署HA自動進行故障轉移。自動故障轉移為HDFS部署增加了兩個新組件:ZooKeeper和ZKFailoverController(ZKFC)進程。ZooKeeper是維護少量協調數據,通知客戶端這些數據的改變和監視客戶端故障的高可用服務。HA的自動故障轉移依賴于ZooKeeper的以下功能:
- 故障檢測:集群中的每個NameNode在ZooKeeper中維護了一個持久會話,如果機器崩潰,ZooKeeper中的會話將終止,ZooKeeper通知另一個NameNode需要觸發故障轉移。
- 現役NameNode選擇:ZooKeeper提供了一個簡單的機制用于唯一的選擇一個節點為active狀態。如果目前現役NameNode崩潰,另一個節點可能從ZooKeeper獲得特殊的排外鎖以表明它應該成為現役NameNode。
ZKFC是自動故障轉移中的另一個新組件,是ZooKeeper的客戶端,也監視和管理NameNode的狀態。每個運行NameNode的主機也運行了一個ZKFC進程,ZKFC負責:
- 健康監測:ZKFC使用一個健康檢查命令定期地ping與之在相同主機的NameNode,只要該NameNode及時地回復健康狀態,ZKFC認為該節點是健康的。如果該節點崩潰,凍結或進入不健康狀態,健康監測器標識該節點為非健康的。
- ZooKeeper會話管理:當本地NameNode是健康的,ZKFC保持一個在ZooKeeper中打開的會話。如果本地NameNode處于active狀態,ZKFC也保持一個特殊的znode鎖,該鎖使用了ZooKeeper對短暫節點的支持,如果會話終止,鎖節點將自動刪除。
- 基于ZooKeeper的選擇:如果本地NameNode是健康的,且ZKFC發現沒有其它的節點當前持有znode鎖,它將為自己獲取該鎖。如果成功,則它已經贏得了選擇,并負責運行故障轉移進程以使它的本地NameNode為active。故障轉移進城與前面描述的手動故障轉移相似,首先如果必要保護之前的現役NameNode,然后本地NameNode轉換為active狀態。
在典型部署中,ZooKeeper守護進程運行在三個或者五個節點上,但由于ZooKeeper本身需要較少的資源,所以將ZooKeeper部署在與現役NameNode和待機NameNode相同的主機上,還可以將ZooKeeper部署到與YARN的ResourceManager相同的節點上。建議配置ZooKeeper將數據存儲在與HDFS元數據不同的硬盤上以得到最好的性能和隔離性。在配置自動故障轉移之前需要先停掉集群,目前在集群運行時還不可能將手動故障轉移的安裝轉換為自動故障轉移的安裝。接下來看看如何配置HA的自動故障轉移。首先在hdfs-site.xml中添加下面的參數,該參數的值默認為false:
- <property>
- <name>dfs.ha.automatic-failover.enabled</name>
- <value>true</value>
- </property>
在core-site.xml文件中添加下面的參數,該參數的值為ZooKeeper服務器的地址,ZKFC將使用該地址。
- <property>
- <name>ha.zookeeper.quorum</name> <value>zk1.example.com:2181,zk2.example.com:2181,zk3.example.com:2181</value>
- </property>
在HA或者HDFS聯盟中,上面的兩個參數還需要以NameServiceID為后綴,比如dfs.ha.automatic-failover.enabled.mycluster。除了上面的兩個參數外,還有其它幾個參數用于自動故障轉移,比如ha.zookeeper.session-timeout.ms,但對于大多數安裝來說都不是必須的。
在添加了上述的配置參數后,下一步就是在ZooKeeper中初始化要求的狀態,可以在任一NameNode中運行下面的命令實現該目的,該命令將在ZooKeeper中創建znode:
在啟用自動故障轉移的集群中,start-dfs.sh腳本將在任何運行NameNode的主機上自動啟動ZKFC守護進程,一旦ZKFC啟動完畢,它們將自動選擇一個NameNode為現役NameNode。如果手動管理集群中的服務,需要在每臺運行NameNode的主機上手動啟動ZKFC,命令為:
- hadoop-daemon.sh start zkfc
- hdfs zkfc
如果正在運行一個安全的集群,可能想確保存儲在ZooKeeper中的信息也是安全的,這將阻止惡意的客戶端修改ZooKeeper中的元數據或者潛在地觸發一個錯誤的故障轉移。為了保護ZooKeeper中的信息,首先在core-site.xml中添加下面的參數:
- <property>
- <name>ha.zookeeper.auth</name>
- <value>@/path/to/zk-auth.txt</value>
- </property>
- <property>
- <name>ha.zookeeper.acl</name>
- <value>@/path/to/zk-acl.txt</value>
- </property>
參數值中的@字符表示參數值保存在@后的硬盤文件中。第一個配置文件指定了ZooKeeper的認證列表,其格式與ZK CLI使用的相同,例如:digest:hdfs-zkfcs:mypassword,其中hdfs-zkfcs為ZooKeeper的用戶名,mypassword為密碼。其次使用下面的命令為該認證生成一個ZooKeeper訪問控制列表:
- $ java -cp $ZK_HOME/lib/*:$ZK_HOME/zookeeper-3.4.2.jar org.apache.zookeeper.server.auth.DigestAuthenticationProvider hdfs-zkfcs:mypassword
- output: hdfs-zkfcs:mypassword->hdfs-zkfcs:P/OQvnYyU/nF/mGYvB/xurX8dYs=
拷貝->之后的字符串并添加digest:前綴,然后粘貼到zk-acls.txt中,例如:digest:hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=:rwcda。要想使ACLs生效,需要再次運行zkfc –formatZK。最后可能像下面這樣在ZK CLI中驗證ACLs:
- [zk: localhost:2181(CONNECTED) 1] getAcl /hadoop-ha
- 'digest,'hdfs-zkfcs:vlUvLnd8MlacsE80rDuu6ONESbM=
- : cdrwa
在安裝完成自動故障轉移后,或許需要測試一下。首先定位現役NameNode,可以通過訪問NameNode的web頁面來確定哪個NameNode是active狀態的。一旦確定了處于active狀態的NameNode,就需要在該節點上制造點故障,比如使用命令kill -9 <pid of NN>模擬JVM崩潰,或重啟主機或拔掉網線來模擬不同的中斷。一旦觸發了自動故障轉移,另一個NameNode應該自動在幾秒鐘內變為active狀態。檢測到故障并觸發故障轉移由參數ha.zookeeper.session-timeout.ms控制,該參數為與core-site.xml中,默認為5秒。如果測試不成功,可能是配置問題,檢查ZKFC和NameNode進程的日志以進一步診斷問題,通常錯誤都是很明顯的。