NameNode HA的部署方法

在部署flink的時候,發現hdfs的namenode有可能會有單點故障問題,所以給它做一個HA的部署。

關注點:

1、NameNode HA模式下,active的NameNode掛掉之後,切換時間有多長?

答:根據測試來看,切換時間非常短。kill掉active的NameNode之後,再去查詢standby的NameNode狀態,會發現已經變成active。

具體時間可能有更多因素影響:(1)zk心跳間隔(2)NameNode的qps

2、Flink是否會受到NameNode切換的影響?

答:從運行一個路口的指標計算程序來看,沒有受到影響,程序沒有任何重啓。

其他需額外關注的點:(1)路口增多時是否會有變化(2)任務增多時是否有變化(3)有checkpoint的任務是否會受到影響

注意點(調研過程中發現的一些點):

(1)啓用了HA的hadoop集羣,不能再有secondary namenode了,否則會報錯

(2)Flink能識別hadoop的nameservice,是因爲加載了其配置,方法如下,在flink-conf.yaml文件中添加如下內容:

# 如果使用Hadoop HA的時候,一定要配置hadoop conf目錄,把hadoop 集羣的配置文件拷貝到這個目錄裏面,這樣 flink就會知道hadoop-ha-nameservice的具體active的nameNode的地址。
env.hadoop.conf.dir: /root/software/hadoop-2.8.5/etc/hadoop


# 另外,其他使用hdfs路徑的地方都要配置hadoop HA中core-site.xml中配置的HA nameservice,而不是用namenode的域名

此配置的介紹 :  https://ci.apache.org/projects/flink/flink-docs-release-1.10/ops/config.html#env-hadoop-conf-dir

配置參考:http://moheqionglin.com/site/serialize/02006013006/detail.html

(3)當前一個nameservice只支持最多兩個namenode;hadoop還支持多個nameservice(這是另外的特性了)

(4)journal node至少需要三個節點,但是隻有兩臺機器,充分利用一下其中一臺機器,部署兩個進程。需要在hdfs-site.xml文件中添加如下內容,修改默認端口,避免衝突

<property>
    <name>dfs.journalnode.rpc-address</name>
    <value>0.0.0.0:8486</value>
</property>
<property>
    <name>dfs.journalnode.http-address</name>
    <value>0.0.0.0:8487</value>
</property>
<property>
    <name>dfs.journalnode.https-address</name>
    <value>0.0.0.0:8488</value>
</property>


<!-- 這個目錄配置修改一下,避免衝突 -->
<property>
      <name>dfs.journalnode.edits.dir</name>
      <value>/root/software/hadoop-2.8.5_another/journal_node_data</value>
</property>

相關配置項的含義:https://hadoop.apache.org/docs/r2.4.1/hadoop-project-dist/hadoop-hdfs/hdfs-default.xml

修改hadoop-env.sh文件

# 這個配置默認是/tmp目錄,如果要在一臺機器上啓動不同hadoop組件,需要使他們的pid不在一起,避免衝突
export HADOOP_PID_DIR=/root/software/hadoop-2.8.5_another/pids


(5)如果是一個已有的hadoop集羣,從非HA變成HA,需要首先創建Journal node日誌的目錄,其次需要執行下面的命令進行格式化。這個在官網也有說明。

$ hdfs namenode -initializeSharedEdits

 

 

 

詳細步驟:

前置條件:

三臺機器、機器之間已經配置免密、jdk已經安裝

1、Download Hadoop

2、配置etc/hadoop/core-site.xml

<configuration>
        <property>
                <name>fs.defaultFS</name>
<!--這裏用的是nameservice id,和hdfs-site.xml中的配置保持一致-->
                <value>hdfs://mycluster</value>
        </property>
        <property>
                <name>ha.zookeeper.quorum</name>
<!-- zookeeper集羣 -->
                <value>zk-ip:2181</value>
         </property>
        <property>
                <name>hadoop.tmp.dir</name>
                <value>/root/software/hadoop-2.8.5/hadoop_tmp</value>
        </property>
        <property>
                <name>io.file.buffer.size</name>
                <value>4096</value>
        </property>
</configuration>

3、配置etc/hadoop/hdfs-site.xml

<configuration>
<!-- 完全分佈式集羣名稱,nameservice id,core-site.xml中的fs.default.xml用的就是這裏的配置-->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value>
    </property>
<!-- 集羣中NameNode節點名稱,隨意起名,可以保持不變 -->
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value>
    </property>
<!-- nn1的RPC通信地址,用域名和IP都可以,保險用IP -->
    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn1</name>
      <value>1.2.3.4:8020</value>
    </property>
<!-- nn2的RPC通信地址,用域名和IP都可以,保險用IP -->
    <property>
      <name>dfs.namenode.rpc-address.mycluster.nn2</name>
      <value>1.1.1.1:8020</value>
    </property>
<!-- nn1的http通信地址,用域名和IP都可以,保險用IP;百度內網改成8070端口便於訪問 -->
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>1.2.3.4:50070</value>
    </property>
<!-- nn2的http通信地址,用域名和IP都可以,保險用IP,百度內網改成8070端口便於訪問 -->
    <property>
          <name>dfs.namenode.http-address.mycluster.nn2</name>
          <value>1.1.1.1:50070</value>
    </property>
<!-- 指定NameNode元數據在JournalNode上的存放位置,保持此格式,修改ip和端口;mycluster和nameservice保持一致 -->
<!-- Journal node的默認端口都是8485,如有特殊,需修改-->
    <property>
          <name>dfs.namenode.shared.edits.dir</name>
            <value>qjournal://1.2.3.4:8485;1.1.1.1:8485;1.1.1.1:8486/mycluster</value>
    </property>
    <!-- 訪問代理類:client,mycluster,active配置失敗自動切換實現方式-->
    <property>
          <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</value>
    </property>
<!-- 使用隔離機制時需要ssh無祕鑰登錄,根據具體使用到的用戶來進行配置,一般是/root的用戶 -->
    <property>
          <name>dfs.ha.fencing.ssh.private-key-files</name>
          <value>/root/.ssh/id_rsa</value>
    </property>
<!-- 聲明journalnode服務器存儲目錄,根據線上目錄情況調整-->
    <property>
          <name>dfs.journalnode.edits.dir</name>
          <value>/root/software/hadoop-2.8.5/journal_node_data</value>
    </property>
    <!-- 關閉權限檢查-->
    <property>
        <name>dfs.permissions.enable</name>
        <value>false</value>
    </property>
    <!--開啓Automatic Failover模式-->
    <property>
           <name>dfs.ha.automatic-failover.enabled</name>
           <value>true</value>
     </property>

    <property>
        <name>dfs.replication</name>
        <value>3</value>
    </property>
    <property>
        <name>dfs.namenode.name.dir</name>
        <value>file:/root/software/hadoop-2.8.5/hdfs/namenode</value>
    </property>
    <property>
        <name>dfs.datanode.data.dir</name>
        <value>file:/root/software/hadoop-2.8.5/hdfs/datanode</value>
    </property>
</configuration>

4、配置etc/hadoop/mapred-site.xml

$ cp mapred-site.xml.template mapred-site.xml
增加如下內容
<configuration>
     <!--指定mapreduce運行框架-->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
    <property>
        <name>mapreduce.jobhistory.address</name>
<!--歷史服務的通信地址 -->
        <value>node2:10020</value>
    </property>
    <property>
        <name>mapreduce.jobhistory.webapp.address</name>
<!--歷史服務的web ui地址 -->
        <value>node2:19888</value>
    </property>
</configuration>

5、配置etc/hadoop/yarn-site.xml

<configuration>
    <property>
        <name>yarn.resourcemanager.hostname</name>
<!--yarn resourceManager地址 -->
        <value>node2</value>
    </property>
    <property>
        <name>yarn.resourcemanager.address</name>
        <value>${yarn.resourcemanager.hostname}:8032</value>
    </property>
    <property>
        <name>yarn.resourcemanager.scheduler.address</name>
        <value>${yarn.resourcemanager.hostname}:8030</value>
    </property>
    <property>
        <name>yarn.resourcemanager.webapp.address</name>
        <value>${yarn.resourcemanager.hostname}:8088</value>
    </property>
    <property>
        <name>yarn.resourcemanager.webapp.https.address</name>
        <value>${yarn.resourcemanager.hostname}:8090</value>
    </property>
    <property>
        <name>yarn.resourcemanager.resource-tracker.address</name>
        <value>${yarn.resourcemanager.hostname}:8031</value>
    </property>
    <property>
        <name>yarn.resourcemanager.admin.address</name>
        <value>${yarn.resourcemanager.hostname}:8033</value>
    </property>
    <property>
        <name>yarn.nodemanager.local-dirs</name>
        <value>/root/software/hadoop-2.8.5/hadoop_tmp/yarn/local</value>
    </property>
    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <property>
        <name>yarn.nodemanager.remote-app-log-dir</name>
        <value>/root/software/hadoop-2.8.5/hadoop_tmp/logs</value>
    </property>
    <property>
        <name>yarn.log.server.url</name>
        <value>http://node2:19888/jobhistory/logs/</value>
        <description>URL for job history server</description>
    </property>
    <property>
        <name>yarn.nodemanager.vmem-check-enabled</name>
        <value>false</value>
    </property>
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <name>yarn.nodemanager.aux-services.mapreduce.shuffle.class</name>
        <value>org.apache.hadoop.mapred.ShuffleHandler</value>
    </property>
    <property>
        <name>yarn.nodemanager.resource.memory-mb</name>
        <value>2048</value>
    </property>
     <property>
        <name>yarn.scheduler.minimum-allocation-mb</name>
        <value>512</value>
    </property>
    <property>
        <name>yarn.scheduler.maximum-allocation-mb</name>
        <value>4096</value>
    </property>
    <property>
        <name>mapreduce.map.memory.mb</name>
        <value>2048</value>
    </property>
    <property>
        <name>mapreduce.reduce.memory.mb</name>
        <value>2048</value>
    </property>
    <property>
        <name>yarn.nodemanager.resource.cpu-vcores</name>
        <value>1</value>
    </property>
</configuration>

6、配置etc/hadoop/slaves。將所有worker節點都寫進文件,如果只配置一個節點,就是隻在這個節點上有datenode和nodeManager

node2
node3

7、配置etc/hadoop/hadoop-env.sh

# 搜索到JAVA_HOME,修改成線上安裝的jdk路徑
export JAVA_HOME=/root/software/jdk1.8.0_131

8、配置etc/hadoop/yarn-env.sh

# 搜索到JAVA_HOME,修改成線上安裝的jdk路徑
export JAVA_HOME=/root/software/jdk1.8.0_131

9、配置etc/hadooop/mapred-env.sh

# 搜索到JAVA_HOME,修改成線上安裝的jdk路徑
export JAVA_HOME=/root/software/jdk1.8.0_131

10、然後通過scp命令將文件發送到其他所有機器

# 多機器地址保持一致
$ scp -r hadoop-2.8.5 root@node3:/root/software/

11、在所有機器上分別啓動QJM,至少啓動3臺機器。(如果機器不夠3臺,可以做僞分佈式,前文“注意”部分已經給出方法)

$ sbin/hadoop-daemon.sh start journalnode

啓動後,jps會發現多了  JournalNode  進程

12、格式化NameNode並啓動(注意:先格式化一臺namenode,然後另一臺namenode同步第一臺namenode,如果兩臺都格式化就會有問題)

格式化namanode(只在第一次啓動集羣之前操作)

# 格式化第一臺機器的NameNode,並啓動
$ bin/hdfs namenode -format
$ sbin/hadoop-daemon.sh start namenode




# 第二個namenode同步第一個NameNode的數據
[root@hadoop003 hadoop-2.6.5]# bin/hdfs namenode -bootstrapStandby
# 啓動第二個namenode
[root@hadoop003 hadoop-2.6.5]# sbin/hadoop-daemon.sh start namenode

操作完成後會發現生成了/root/software/hadoop-2.8.5/hdfs/namenode目錄,下面有初始化的namenode信息。如果需要將集羣數據重置,可以將下面的數據全部刪除(datanode數據也刪除,每個機器上都清除數據),重新格式化namenode。

13、此時,兩個NameNode都是standby模式,需手動將一個NameNode設置爲active

# 可以看到nn1和nn2都是standby狀態
$ bin/hdfs haadmin -getServiceState nn1
standby
$ bin/hdfs haadmin -getServiceState nn2
standby


# 手動將nn1改成active狀態(這裏是強制操作);執行過程中需要輸入y確認執行
$ bin/hdfs haadmin -transitionToActive --forcemanual nn1


# 此時再看nn1狀態已經變成active
$ bin/hdfs haadmin -getServiceState nn1
active
$ bin/hdfs haadmin -getServiceState nn2
standby

14、在zookeeper上配置故障自動轉移節點

[root@hadoop001 hadoop-2.6.5]# bin/hdfs zkfc -formatZK
[zk: localhost:2181(CONNECTED) 5] ls /
[zookeeper, hadoop-ha]
# 可以看到zookeeper上已經有了hadoop-ha節點了

15、啓動dfs(這一步必須要執行,因爲它會把DFSZKFailoverController啓動起來,只有這個進程啓動,才能實現故障自動切換)

$ sbin/start-dfs.sh

停止dfs(不必要)

$ sbin/stop-dfs.sh

Test

$ bin/hdfs dfs -mkdir /aa
$ bin/hdfs dfs -ls /

訪問NameNode UI:http:1.2.3.4:50070

16、啓動yarn(不必要)

$ sbin/start-yarn.sh

訪問Yarn UI:http://1.2.3.4:8088

停止yarn

$ sbin/stop-yarn.sh

17、全部啓動

$ sbin/start-all.sh

全部停止

$ sbin/stop-all.sh

18、配置環境變量(方便使用),在/etc/profile文件中增加如下配置:

export HADOOP_HOME=/root/software/hadoop-2.8.5
export PATH=$PATH:${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin

19、測試自動切換功能是否生效

# 在nn1機器上執行
$ jps
6708 DFSZKFailoverController
6549 DataNode
5814 JournalNode
6103 NameNode
6825 Jps
5021 QuorumPeerMain

# 殺掉namenode進程
[root@hadoop003 hadoop-2.6.5]# kill -9 6103

#查看nn1狀態,連接不上了
$ bin/hdfs haadmin -getServiceState nn1
18/08/21 16:28:52 INFO ipc.Client: Retrying connect to server: hadoop003/192.168.170.133:8020. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS)
Operation failed: Call From hadoop003/192.168.170.133 to hadoop003:8020 failed on connection exception: java.net.ConnectException: Connection refused; For more details see:  http://wiki.apache.org/hadoop/ConnectionRefused

# 查看nn2狀態,已經激活了
$ bin/hdfs haadmin -getServiceState nn2
active




# nn1同步nn2,並重新啓動nn1
$ bin/hdfs namenode -bootstrapStandby
$ sbin/hadoop-daemon.sh start namenode


# 這時,nn1是standby狀態,nn2是active狀態;可以殺掉nn2,會發現自動切換到nn1

 

 

Flink中的相關配置:

1、修改flink-conf.yaml文件,然後分發到集羣所有機器上。

# 如果使用Hadoop HA的時候,一定要配置hadoop conf目錄
# 如果Hadoop和Flink在同一臺機器上,把hadoop 集羣的配置文件拷貝到這個目錄裏面,這樣 flink就會知道hadoop-ha-nameservice的具體active的nameNode的地址。
# 如果有Flink的機器上沒有Hadoop,那麼需要將Hadoop的配置拷貝到該機器的某個目錄下,並配置在下面。
# 所有機器需要保持一致,避免產生問題。
env.hadoop.conf.dir: /root/software/hadoop-2.8.5/etc/hadoop


# 另外,其他使用hdfs路徑的地方都要配置hadoop HA中core-site.xml中配置的HA nameservice,而不是用namenode的域名;例如:
jobmanager.archive.fs.dir: hdfs://mycluster/flink/completed-jobs/

2、啓動Flink集羣。(如果是已有的集羣,有可能因爲上面的操作產生數據丟失導致重啓失敗,最好將zk和hadoop中關於Flink的數據刪除後再啓動)

3、測試:

(1)啓動一個Flink任務在運行狀態(比如指標計算),手動殺死active的namenode,Flink程序無感,沒有產生任何崩潰,指標照常產生。

(2)啓動一個有checkpoint的程序,手動殺死active的namenode,觀察現象。

 

 

 

 

 

 

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