Hadoop2.x集群动态添加删除数据节点

     如果Hadoop集群已经在运行了,这时可能需要动态的添加新的数据节点到Hadoop系统中去,或者将某个数据节点下线,由于业务的需要,集群是不能重启的,那么具体的DataNode添加、删除步骤是什么样的呢?

下面以DataNode的上线为例详细说明下如何动态的给HDFS集群新增数据节点(Hadoop2.0版本)。

    首先简单说下几个相关的配置文件。

(1)由dfs.hosts配置选项指定的白名单文件,当要新上线数据节点的时候,需要把数据节点的名字追加在此文件中;

(2)由dfs.hosts.exclude配置选项指定的黑名单文件,当要下线数据节点的时候,需要把数据节点的名字追加在此文件中;

    下面开始步骤(假设所有新增数据节点上的Hadoop环境都已经部署完毕):

Step1:关闭新加入数据节点的防火墙。

Step2:在两个NameNode节点的hosts文件中加入新增数据节点的hostname。

Step3:在每个新增数据节点的hosts文件中加入两个NameNode的hostname。

Step4:在两个NameNode上,打通向新增数据节点无密钥SSH登录的通道。

Step5:在两个NameNode上的dfs.hosts指定的白名单文件中追加上所有新增的数据节点的hostname,注意是追加!并且,保证在dfs.hosts.exclude指定的黑名单文件中不含有新增的数据节点的hostname。

Step6:找一个客户端,配置文件和其他节点一致,执行如下刷新命令:

  hdfs dfsadmin -refreshNodes

      (此步也可以在任何其他节点上进行)

Step7:还是在第6步的客户端上操作,此时需要更改下hdfs-site.xml中的配置选项,将类似于如下的配置选项:

<property>
         <name>dfs.namenode.rpc-address.mcs.nn0</name>
         <value>namenode0:9000</value>
</property>
<property>
      <name>dfs.namenode.rpc-address.mcs.nn1</name>
      <value>namenode1:9000</value>
</property>

改为:

<property>
    <name>dfs.namenode.rpc-address.mcs.nn0</name>
    <value>namenode1:9000</value>
</property>
<property>
    <name>dfs.namenode.rpc-address.mcs.nn1</name>
    <value>namendoe0:9000</value>
</property>

Step8:在第7步操作的客户端上重新执行命令:

  hdfs dfsadmin -refreshNodes

Step9:在数据节点上启动DataNode进程,命令如下:

  hadoop-daemon.sh start datanode

Step10:查看数据节点进程的情况(通过日志),查看NameNode的web界面。

Step11:在两个NameNode节点上,更改slaves文件,将要上线的数据节点hostname追加到slaves文件中。

至于第7步中为什么要更改配置之后在进行第8步的刷新,是因为在Hadoop2.x版本中引入了Federation机制,用户可根据情况定义多组NameNode,每一组有两个NameNode,一个为active,另一个为standby,实现了HA。由于执行刷新命令的节点相当于一个Client,Client将触发当前nameservice中的第一个NameNode执行刷新命令,要使得两个NameNode都刷新,则要更改下配置之后再刷新。具体来说刷新是调用如下方法:

public int refreshNodes() throws IOException {

    int exitCode = -1; 

    DistributedFileSystem dfs = getDFS();

    dfs.refreshNodes();

    exitCode = 0;

    return exitCode;

  }

    通过获取文件系统对象FileSystem之后,调用FSNamesystem类中的refreshNodes方法:

void refreshNodes() throws IOException {

    checkOperation(OperationCategory.UNCHECKED);

    checkSuperuserPrivilege();

    getBlockManager().getDatanodeManager().refreshNodes(new HdfsConfiguration());

  }

    在检查完相应的操作权限之后,最后由DatanodeManager类来执行具体的刷新实现:

public void refreshNodes(final Configuration conf) throws IOException {

    refreshHostsReader(conf);

    namesystem.writeLock();

    try {

      refreshDatanodes();

    } finally {

      namesystem.writeUnlock();

    }

  }

    其中,refreshHostsReader是重新读取dfs.hosts指定的配置文件,将其中的内容加载到内存中,更新白名单列表includes。之后,执行最关键的一步,刷新数据节点列表:

private void refreshDatanodes() throws IOException {

    for(DatanodeDescriptor node : datanodeMap.values()) {

      // Check if not include.

      if (!inHostsList(node)) {

        node.setDisallowed(true); // case 2.

      } else {

        if (inExcludedHostsList(node)) {

          startDecommission(node); // case 3.

        } else {

          stopDecommission(node); // case 4.

        }

      }

    }

  }

    此处的inHostsList方法是当数据节点发来心跳进行注册的时候,判断此节点是否在白名单之中,如果不在的话,就会拒绝该数据节点的注册请求,并抛出异常:

DisallowedDatanodeException:"Datanode denied communication with namenode: " + nodeID

    至于数据节点的下线,和上述步骤类似,只不过Step5中要换一下文件。真个操作的过程中都不涉及集群的重启~

原文地址:https://www.cnblogs.com/Scott007/p/3134737.html