扩展为HA需要注意的问题

原Namenode称为namenode1,新增的Namenode称为namenode2.

从namenode单节点扩展为HA模式官网上有详细的教程,下面是扩展过程中疏忽的地方。

  • namenode2部署后需要复制namenode1格式化好的数据,就是namenode1部署的时候,通过hdfs namenode -format生成的数据。
  • journalnode部署好后,也需要格式化数据。格式化方式为:journalnode启动之后,在namenode执行hdfs namenode -bootstrapStandby来初始化journalnode,namenode不能是在运行状态,否则会报数据被锁定的异常。
    然后执行hadoop/bin/hdfs haadmin -transitionToActive nn1手动吧nn1切换成active节点。

下面是简写的笔记,按照个人知识基础写的,建议部署过程参照官网。

HA 原理

hadoop可以通过nfs和quorum journal manager(QJM)实现。

通过QJM共享edit log。

当主节点挂了,备从edit log迅速成为主节点。

架构

HA 集群中有一个namenode是Active ,另一个是Standby

部署Standby的时候,把Active节点上格式化好的数据拷贝到Standby。

要布署HA,需要准备一下内容:

  • Namenode: 主节点和备节点。
  • JournalNode:JournalNode是轻量级的,所以JournalNode可以布署在其他的Hadoop机器上,比如job tracker或者yarn RecourceManager。注意:必须至少三个JournalNode,这种结构允许系统有一个节点故障。可以大于单台,但是要增加允许故障节点的数量,journalnode的数量必须时奇数。因为系统健康状况的最低标准为(n/2)+1 个。所以三个节点只允许一台挂掉,4个节点也允许1台挂掉。

HA配置

参数说明

hdfs-site.xml

dfs.nameservices 用于标识集群

<property>
  <name>dfs.nameservices</name>
  <value>mycluster</value>
</property>

dfs.ha.namenodes.[nameservice ID] 集群mycluster的namenode成员

<property>
  <name>dfs.ha.namenodes.mycluster</name>
  <value>nn1,nn2</value>
</property>

dfs.namenode.rpc-address.[nameservice ID].[name node ID]

<property>
  <name>dfs.namenode.rpc-address.mycluster.nn1</name>
  <value>machine1.example.com:8020</value>
</property>
<property>
  <name>dfs.namenode.rpc-address.mycluster.nn2</name>
  <value>machine2.example.com:8020</value>
</property>

dfs.namenode.http-address.[nameservice ID].[name node ID]

<property>
  <name>dfs.namenode.http-address.mycluster.nn1</name>
  <value>machine1.example.com:50070</value>
</property>
<property>
  <name>dfs.namenode.http-address.mycluster.nn2</name>
  <value>machine2.example.com:50070</value>
</property>

dfs.namenode.shared.edits.dir 配置edits共享地址,journalnode的地址。

mycluster是nameservice ID

<property>
  <name>dfs.namenode.shared.edits.dir</name>
  <value>qjournal://node1.example.com:8485;node2.example.com:8485;node3.example.com:8485/mycluster</value>
</property>

dfs.client.failover.proxy.provider.[nameservice ID] 客户端用来连接avtive namenode的类。

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

dfs.ha.fencing.methods 再故障转移时的一种保护机制。Hadoop可以使用shell和sshfence的方式。

sshfence参数远程连接到目标节点杀死进程。

<property>
      <name>dfs.ha.fencing.methods</name>
      <value>sshfence</value>
    </property>

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

shell 可以使用的变量

$target_host

hostname of the node to be fenced

$target_port

IPC port of the node to be fenced

$target_address

the above two, combined as host:port

$target_nameserviceid

the nameservice ID of the NN to be fenced

$target_namenodeid

the namenode ID of the NN to be fenced

<property>
      <name>dfs.ha.fencing.methods</name>
      <value>shell(/path/to/my/script.sh --nameservice=$target_nameserviceid $target_host:$target_port)</value>
    </property>

core-site.xml

<property>
  <name>fs.defaultFS</name>
  <value>hdfs://mycluster</value>
</property>

dfs.journalnode.edits.dir journalnode保存edits的路径

JournalNode的配置

<property>
  <name>dfs.journalnode.edits.dir</name>
  <value>/path/to/journal/node/local/data</value>
</property>

JournalNode

上面是配置,启动方式为:

hadoop-2.9.2/sbin/hadoop-daemon.sh --config /opt/hadoop-2.9.2/etc/hadoop --script hdfs start journalnode

journalnode启动之后在namenode执行hdfs namenode -bootstrapStandby来初始化journalnode

然后执行hadoop/bin/hdfs haadmin -transitionToActive nn1手动吧nn1切换成active节点。

namenode|secondarynamenode|datanode|journalnode|dfs|dfsadmin|fsck|balancer|zkfc|portmap|nfs3|dfsrouter

自动故障转移

上面的配置只能使用手动转移。

zookeeper布署

namenode

core-site.xml

<configuration>
<property>
    <name>fs.defaultFS</name>
    <value>hdfs://ns1</value>
</property>
<property>
    <name>hadoop.tmp.dir</name>
    <value>/opt/modules/App/hadoop-2.5.0/data/tmp</value>
</property>
<property>
    <name>hadoop.http.staticuser.user</name>
    <value>beifeng</value>
</property>
<property>
    <name>ha.zookeeper.quorum</name>
    <value>bigdata-01:2181,bigdata-02:2181,bigdata-03:2181</value>
</property>
</configuration>

hdfs-site.xml

<configuration>
<property>
    <name>dfs.replication</name>
    <value>3</value>
</property>
property>
    <name>dfs.permissions.enabled</name>
    <value>false</value>
</property>
<property>
    <name>dfs.nameservices</name>
    <value>ns1</value>
</property>
<property>
    <name>dfs.blocksize</name>
    <value>134217728</value>
</property>
<property>
    <name>dfs.ha.namenodes.ns1</name>
    <value>nn1,nn2</value>
</property>
<!-- nn1的RPC通信地址,nn1所在地址  -->
<property>
    <name>dfs.namenode.rpc-address.ns1.nn1</name>
    <value>bigdata-01:8020</value>
</property>
<!-- nn1的http通信地址,外部访问地址 -->
<property>
    <name>dfs.namenode.http-address.ns1.nn1</name>
    <value>bigdata-01:50070</value>
</property>
<!-- nn2的RPC通信地址,nn2所在地址 -->
<property>
    <name>dfs.namenode.rpc-address.ns1.nn2</name>
    <value>bigdata-02:8020</value>
</property>
<!-- nn2的http通信地址,外部访问地址 -->
<property>
    <name>dfs.namenode.http-address.ns1.nn2</name>
    <value>bigdata-02:50070</value>
</property>
<!-- 指定NameNode的元数据在JournalNode日志上的存放位置(一般和zookeeper部署在一起) -->
<property>
    <name>dfs.namenode.shared.edits.dir</name>
    <value>qjournal://bigdata-01:8485;bigdata-02:8485;bigdata-03:8485/ns1</value>
</property>
<!-- 指定JournalNode在本地磁盘存放数据的位置 -->
<property>
    <name>dfs.journalnode.edits.dir</name>
    <value>/opt/modules/App/hadoop-2.5.0/data/journal</value>
</property>
<!--客户端通过代理访问namenode,访问文件系统,HDFS 客户端与Active 节点通信的Java 类,使用其确定Active 节点是否活跃  -->
<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</value>     ----这个参数的值可以有多种,你也可以换成shell(/bin/true)试试,也是可以的,这个脚本do nothing 返回0
</property>
<!-- 这个是使用sshfence隔离机制时才需要配置ssh免登陆 -->
<property>
    <name>dfs.ha.fencing.ssh.private-key-files</name>
    <value>/home/beifeng/.ssh/id_rsa</value>
</property>
<!-- 配置sshfence隔离机制超时时间,这个属性同上,如果你是用脚本的方法切换,这个应该是可以不配置的 -->
<property>
    <name>dfs.ha.fencing.ssh.connect-timeout</name>
    <value>30000</value>
</property>
<!-- 这个是开启自动故障转移,如果你没有自动故障转移,这个可以先不配 -->
<property>
    <name>dfs.ha.automatic-failover.enabled</name>
    <value>true</value>
</property>
</configuration>

mapred-site.xml

<configuration>
<property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
</property>
<property>
    <name>mapreduce.jobhistory.address</name>
    <value>bigdata-01:10020</value>
</property>
<property>
    <name>mapreduce.jobhistory.webapp.address</name>
    <value>bigdata-01:19888</value>
</property>
</configuration>

yarn-site.xml

<configuration>
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname</name>
        <value>bigdata-03</value>
    </property>
    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
        <property>
        <name>yarn.log-aggregation.retain-seconds</name>
        <value>106800</value>
    </property>
</configuration>