规划
共三台机器,目标是搭建一套配置了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.xml
,hadoop-env.sh
,hdfs-site.xml
和workers
。对于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
- 在使用集群管理脚本的时候,由于使用ssh进行远程登录时不会读取
/etc/profile
文件中的环境变量配置,所以使用ssh的时候java命令不会生效,因此需要在配置文件中显式配置jdk的绝对路径(如果各个节点的jdk路径不一样的话那hadoop-env.sh
中应改成本机的JAVA_HOME
)。 - hadoop 3.x中对角色权限进行了严格限制,相比于hadoop 2.x要额外对角色的所属用户进行规定。
- 此处仅为搭建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
启动集群
- 在所有journalnode节点上启动journalnode(本例中是所有机器):
hdfs --daemon start journalnode
。 - 在namenode(随便哪一个都行)上执行格式化:
hdfs namenode -format
,出现successfully formated即为执行成功。 - 启动刚刚格式化的namenode:
hdfs --daemon start namenode
。 - 在其他namenode节点上同步信息:
hdfs namenode -bootstrapStandby
,出现以下信息即为同步成功。 - 格式化zookeeper节点:
hdfs zkfc -formatZK
,出现以下信息即为执行成功。 - 启动HDFS集群:
start-dfs.sh
。
验证
分别访问两个namenode的web页面,可以查看到一个为active
一个为standby
。
查看datanode信息,共两个节点,正确。
三台机器分别执行jps
命令,查看进程是否与规划的一致。
查看zookeeper集群中的节点信息,抢占成功的节点应与实际active
的一致。
大功告成,另附上HA配置的官方文档(v3.2.1),点这里。