规划

共三台机器,目标是搭建一套配置了HA的双副本hadoop集群,关于zkfc,journalnode的详细原理不再赘述,集群详细规划如下:

namenode

datanode

journalnode

ZKFC

master

*

*

*

slave1

*

*

*

*

slave1

*

*

*

出于简单方便,我个人并没有使用zookeeper集群,而是在docker环境中启动了一个容器,暂且主机名叫zookeeper吧,实际生产中务必是集群模式,要不然又会出现单点故障问题了。

准备工作

  • ssh免秘钥
  • 修改hosts
  • jdk 1.8+
  • 时间同步
  • zookeeper集群

集群配置

hadoop所有配置文件都集中在{hadoop_home}/etc/hadoop这个目录中,针对HDFS集群主要修改的有core-site.xmlhadoop-env.shhdfs-site.xmlworkers。对于hadoop集群中所有节点配置文件都是一样的,所以只在一台机器上进行修改然后分发即可,下面分开进行说明。

core-site.xml
<configuration>
    # HDFS主入口,mycluster仅是作为集群的逻辑名称,可随意更改但务必与hdfs-site.xml中dfs.nameservices值保持一致
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value>
    </property>
    
    # 默认的hadoop.tmp.dir指向的是/tmp目录,将导致namenode与datanode数据全都保存在易失目录中,此处进行修改
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/var/hadoop</value>
    </property>

    # 用户角色配置,不配置此项会导致web页面报错
    <property>
        <name>hadoop.http.staticuser.user</name>
        <value>root</value>
    </property>

    # zookeeper集群地址,这里只配置了单台,如是集群以逗号进行分隔
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>zookeeper:2181</value>
    </property>
</configuration>
hadoop-env.sh
  1. 在使用集群管理脚本的时候,由于使用ssh进行远程登录时不会读取/etc/profile文件中的环境变量配置,所以使用ssh的时候java命令不会生效,因此需要在配置文件中显式配置jdk的绝对路径(如果各个节点的jdk路径不一样的话那hadoop-env.sh中应改成本机的JAVA_HOME)。
  2. hadoop 3.x中对角色权限进行了严格限制,相比于hadoop 2.x要额外对角色的所属用户进行规定。
  3. 此处仅为搭建HDFS集群,如果涉及到YARN等内容的话应一并修改对应yarn-env.sh等文件中的配置

在脚本末尾添加以下内容:

export JAVA_HOME=/opt/jdk1.8.0_241
export HDFS_NAMENODE_USER="root"
export HDFS_DATANODE_USER="root"
export HDFS_ZKFC_USER="root"
export HDFS_JOURNALNODE_USER="root"
hdfs-site.xml
<configuration>
    # 副本数配置
    <property>
        <name>dfs.replication</name>
        <value>2</value>
    </property>

    # 集群名称,此值在接下来的配置中将多次出现务必注意同步修改
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value>
    </property>
    # 所有的namenode列表,此处也只是逻辑名称,非namenode所在的主机名称
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value>
    </property>

    # namenode之间用于RPC通信的地址,value填写namenode所在的主机地址
    # 默认端口8020,注意mycluster与nn1要和上文的配置一致
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>master:8020</value>
    </property>
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>slave1:8020</value>
    </property>

    # namenode的web访问地址,默认端口9870
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>master:9870</value>
    </property>
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>slave1:9870</value>
    </property>

    # journalnode主机地址,最少三台,默认端口8485
    # 格式为 qjournal://jn1:port;jn2:port;jn3:port/${nameservices}
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://master:8485;slave1:8485;slave2:8485/mycluster</value>
    </property>

    # 故障时自动切换的实现类,照抄即可
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>
        <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>

    # 故障时相互操作方式(namenode要切换active和standby),这里我们选ssh方式
    <property>
      <name>dfs.ha.fencing.methods</name>
      <value>sshfence</value>
    </property>
    # 修改为自己用户的ssh key存放地址
    <property>
      <name>dfs.ha.fencing.ssh.private-key-files</name>
      <value>/root/.ssh/id_rsa</value>
    </property>

    # namenode日志文件输出路径,即journalnode读取变更的位置
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/var/hadoop/journalnode</value>
    </property>

    # 启用自动故障转移
    <property>
        <name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
</configuration>
workers

在hadoop 2.x中这个文件叫slaves,配置所有datanode的主机地址,只需要把所有的datanode主机名填进去就好了

slave1
slave2

启动集群

  1. 在所有journalnode节点上启动journalnode(本例中是所有机器):hdfs --daemon start journalnode
  2. 在namenode(随便哪一个都行)上执行格式化:hdfs namenode -format,出现successfully formated即为执行成功。
  3. 启动刚刚格式化的namenode:hdfs --daemon start namenode
  4. 在其他namenode节点上同步信息:hdfs namenode -bootstrapStandby,出现以下信息即为同步成功。
  5. 格式化zookeeper节点:hdfs zkfc -formatZK,出现以下信息即为执行成功。
  6. 启动HDFS集群:start-dfs.sh

验证

分别访问两个namenode的web页面,可以查看到一个为active一个为standby

hdfs副本从1增加到3怎么操作_hdfs副本从1增加到3怎么操作


hdfs副本从1增加到3怎么操作_hdfs副本从1增加到3怎么操作_02


查看datanode信息,共两个节点,正确。

hdfs副本从1增加到3怎么操作_hadoop_03


三台机器分别执行jps命令,查看进程是否与规划的一致。

hdfs副本从1增加到3怎么操作_zookeeper_04


hdfs副本从1增加到3怎么操作_hadoop_05


hdfs副本从1增加到3怎么操作_hdfs_06


查看zookeeper集群中的节点信息,抢占成功的节点应与实际active的一致。

hdfs副本从1增加到3怎么操作_zookeeper_07


大功告成,另附上HA配置的官方文档(v3.2.1),点这里