本文重点介绍的是 Hadoop ha 模式本身的配置及操作,相关环境配置就不在此赘述了。
Hadoop HA 的作用是保证在一个 namenode 挂掉的时候,另外一个 namenode 可以立即启动来代替这个挂掉的 namenode。这样就不会发生单点故障问题。
一 角色规划
节点名 | 角色名 |
---|---|
master1 | namenode、zkfc、resourcemanager、QuorumPeerMain |
master2 | namenode、zkfc、resourcemanager、QuorumPeerMain |
slave01 | datanode、nodemanager、QuorumPeerMain |
slave02 | datanode、nodemanager、journalnode |
slave03 | datanode、nodemanager、journalnode |
slave04 | datanode、nodemanager、journalnode |
slave05 | datanode、nodemanager |
slave06 | datanode、nodemanager |
slave07 | datanode、nodemanager |
slave08 | datanode、nodemanager |
… | … |
二 hdfs的文件配置
需要修改的配置文件在 $HADOOP_HOME/etc/hadoop 目录下面,具体修改内容如下:
2.1 core-site.xml
-
配置集群服务名称
<property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> <description>指定hdfs的nameservice为mycluster</description> </property>
这个地方的 9000 端口配置移到 hdfs-site.xml 里面了。namenode 对外开放的 URI 不再需要指定单独的机器和端口了,因为两个 namenode 已经组成了一个服务集群,对外只需要暴露服务 ID(nameservice ID)就可以了。
至此你可能会有疑惑:
给我一个 id,我还是不知道怎么连接上去,因为计算机网络的访问本质还是需要一个 ip 和端口啊!答案是各个客户端都是那这个服务 ID(nameservice ID)去 ZooKeeper 集群中查处活跃状态(active)的 namenode 和端口,再进行连接的。
-
指定选举中心
<property> <name>ha.zookeeper.quorum</name> <value>master1:2181,master2:2181,slave01:2181</value> <description>指定zookeeper地址</description> </property>
2.2 hdfs-site.xml
- 增加服务id
现在有两个 namenode 了,就不能再写死用哪个 namenode,因为它们会互相切换,所以就有了一个新的概念——服务id:<property> <name>dfs.nameservices</name> <value>mycluster</value> </property>
- 配置服务 id 内含有的 namenode
此处 mycluster 就是刚刚所配置的服务 id 名称,如果你换了个名称,比如 alexcluster,那么。配置名就要叫做 dfs.ha.namenodes.alexcluster。此处使用 mycluster 作为服务 id:
nn1,nn2 别分是给两个 namenode 取的别名。<property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property>
- 配置 namenode 的 rpc 访问地址
<property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>master1:9000</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>master2:9000</value> </property>
- 配置 namenode 的 http 访问地址
<property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>master1:50070</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>master2:50070</value> </property>
- 配置 journalnode 集群的访问地址
“不要把鸡蛋都放在一个篮子里”。如果条件允许,请单独分配几台机器来搭建 journalnode 集群(ZooKeeper 集群可以安装到 journalnode 集群的机器上来节省成本)。namenode 如果宕机了,往往不只是 namenode 本身的问题,有可能那台服务器有问题,比如网络不通,或者硬盘坏了,这样一来,这台服务器上别的服务也会有问题。如果把 journalnode 配置到namenode 上,那么namenode 机器挂掉的时候,这个 journalnode 节点也会跟着一起坏掉。<property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://slave02:8485;slave03:8485;slave04:8485/mycluster</value> </property>
- 配置 dfs 客户端
dfs 客户端的作用是判断哪个 namenode 是活跃的。现在要配置 dfs 客户端的 Java 类名。目前就一个实现,除非你要自定义一个类,否则照着这个配置写就对了。<property> <name>dfs.client.failover.proxy.provider.ns</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property>
- 配置杀(kill)掉 namenode 的方式
杀掉死掉的节点,是为了让活的节点活得更好。当需要“故障切换”(failover)发生的时候,被判断为故障的 namenode 有可能停不下来,这样就有可能引发“脑裂现象”。为了防止这种情况,需要配置一个终极解决方案,比如直接 SSH 过去 kill 掉它!我们就配置成 SSH 手段好了。
此处,private-key-files 配置成 SSH 免密登录所生成的 id_sra 文件,因为 Hadoop 到时候会用这个文件来免密登录到另外一个 namenode 上去 kill 掉进程。<property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/hadoop/.ssh/id_rsa</value> </property>
- 配置自动 failover
自动 failover 是基于 ZooKeeper 的,所以请先确保 ZooKeeper 已经都启动并在 core-site.xml 中正确配置了。 添加自动 failover 配置到 hdfs-site.xml。<property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
2.3 hadoop-env.sh
在配置下列环境时,尽量先在此文件中找一下是否存在此配置,若存在,则在其基础上变更,若不存在,则新增。
-
java 环境变量
export JAVA_HOME=/usr/java/jdk1.8.0_181-amd64
-
日志文件位置
export HADOOP_LOG_DIR=/data/hadoop/logs
-
进程 ID 文件
export HADOOP_PID_DIR=/data/hadoop/pids
2.4 slaves
slaves 文件只作用在 namedode 上面,里面记录的是集群里所有 datanode 的主机名。示例:
slave01
slave02
slave03
slave04
slave05
slave06
slave07
slave08
三 yarn 的文件配置
3.1 yarn-site.xml
- 启用 yarn 的 ha 模式
<property> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property>
- yarn 集群标识
<property> <name>yarn.resourcemanager.cluster-id</name> <value>yarn-cluster</value> </property>
- RM 的逻辑标识
<property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property>
- 指定 RM 标识的主机名
<property> <name>yarn.resourcemanager.hostname.rm1</name> <value>master1</value> </property> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>master2</value> </property>
- 选举中心地址
<property> <name>yarn.resourcemanager.zk-address</name> <value>master1:2181,master2:2181,slave01:2181</value> </property>
3.2 yarm-env.sh
直接将下列配置放在其实配置的前面即可,请将具体的目录地址修改为实际地址。
-
日志文件位置
YARN_LOG_DIR=/data/hadoop/yarn/logs
默认路径为:$HADOOP_YARN_HOME/logs
-
进程 ID 文件
YARN_PID_DIR=/data/hadoop/yarn/pid
原始默认路径为:/tmp
四 启动
4.1 hdfs 的启动
首次启动时,必须严格按照下面的步骤执行。
-
启动 journalnode
在被配置为 dfs.namenode.shared.edits.dir 的值的节点上启动 journalnode。你想启动几个 journalnode 就启动几个,在这里除了数量必须是奇数以外,没有别的要求。启动命令如下:hadoop-daemon.sh start journalnode
不要敲完命令就不管了,下面几个事情还是要照做的。
- 用 jps 看看有没有 Journalnode 进程启动。
- 如果没有就看看 journalnode 的日志,解决一下错误。
- 如果想停止,就把启动命令中的 start 换成 stop 就行了。
-
启动 namenode 主节点
- 格式化 namenode
命令执行后,到 namenode 的数据文件位置检查是否有hdfs namenode -format
- 启动 namenode 主节点
hadoop-daemon.sh start namenode
- 格式化 namenode
-
启动 namenode 备节点
在启动之前,须先同步主节点和备节点之间的元数据。namenode 主节点格式化后会在 /data/hadoop/dfs 下生成个 name 文件夹,将该 name 拷贝到备节点的 /data/hadoop/dfs/ 下。- 直接拷贝
scp -r /data/hadoop/dfs/* master2:/data/hadoop/dfs/
- 使用内置命令(推荐)
该命令一定要在保证主节点的 namenode 已经启动的情况下执行。hdfs namenode -bootstrapStandby
在元数据同步之后,就可以启动备节点的 namenode 了。
hadoop-daemon.sh start namenode
- 直接拷贝
-
zkfc
在配置 zkfc 之前,可通过 hadoop 的 webUI 看到,两个 namenode 都是 standby。- 初始化
在任一台 namenode 节点上执行一遍初始化命令即可:
可通过 zookeeper 的 client 查看是否在 zookeeper 中注册一个名为 hadoop-ha 根节点。hdfs zkfc -formatZK
- 启动 zkfc
分别在两个 namenode 节点执行启动命令:hadoop-haemon.sh start zkfc
两个 namenode 节点都启动 zkfc 后,通过 webUI 可见,始终有一台处于 active。可通过人工杀死目前处于 active 状态的 namenode,检测另一台 namenode 状态,来确认是否会自动 failover。
- 初始化
-
DataNode
- 启动所有节点的 datanode(需要配置了 slaves 文件,否则只在本机启动 datanode)
直接在 namenode 的主节点上启动 datanode:start-dfs.sh
- 启动指定节点的 datanode
在指定的节点上启动 datanode:hadoop-daemon.sh start datanode
- 启动所有节点的 datanode(需要配置了 slaves 文件,否则只在本机启动 datanode)
4.2 yarn 的启动
- 启动 active
在两台 mater 中的任意一台上执行启动命令,即可启动 yarn。(若在 slaves 文件配置了相关信息,则对应节点上的 NodeManager 也会一起启动。另一台 ResourceManager 需要手动启动)start-yarn.sh
- 启动 standby
在另一台 master 机器上执行如下命令,以启动 standby 的 ResourceManager。yarn-daemon.sh start resourcemanager
附录
以下是最终的配置文件,仅供参考。
- core-site.xml
<configuration> <property> <name>fs.defaults</name> <value>hdfs://mycluster</value> </property> <property> <name>hadoop.tmp.dir</name> <value>/data/hadoop/tmp</value> </property> <property> <name>ha.zookeeper.quorum</name> <value>master1:2181,master2:2181,slave01:2181</value> </property> </configuration>
- hdfs-site.xml
<configuration> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>master1:9000</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>master1:50070</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>master2:9000</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>master2:50070</value> </property> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://slave02:8485;slave03:8485;slave04:8485/mycluster</value> </property> <property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property> <property> <name>dfs.client.failover.proxy.provider.ns</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> <property> <name>dfs.ha.fencing.methods</name> <value>sshfence</value> </property> <property> <name>dfs.ha.fencing.ssh.private-key-files</name> <value>/home/hadoop/.ssh/id_rsa</value> </property> <property> <name>dfs.journalnode.edits.dir</name> <value>/data/hadoop/dfs/journal</value> </property> <property> <name>dfs.namenode.name.dir</name> <value>file:/data/hadoop/dfs/name,file:/home/hadoop/data/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>file:/data/hadoop/dfs/data</value> </property> <property> <name>dfs.replication</name> <value>3</value> </property> <property> <name>dfs.webhdfs.enabled</name> <value>true</value> </property> </configuration>
- yarn-site.xml
<configuration> <property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <property> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <property> <name>yarn.resourcemanager.cluster-id</name> <value>yarn-cluster</value> </property> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>yrm1,yrm2</value> </property> <property> <name>yarn.resourcemanager.hostname.yrm1</name> <value>master1</value> </property> <property> <name>yarn.resourcemanager.hostname.yrm2</name> <value>master2</value> </property> <property> <name>yarn.resourcemanager.zk-address</name> <value>master1:2181,master2:2181,slave01:2181</value> </property> <configuration>
- mapred-site.xml
<configuration> <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <property> <name>mapreduce.jobhistory.intermediate-done-dir</name> <value>/data/hadoop/mr/tmp</value> </property> <property> <name>mapreduce.jobhistory.intermediate-done-dir</name> <value>/data/hadoop/mr/tmp</value> </property> <property> <name>mapreduce.jobhistory.done-dir</name> <value>/data/hadoop/mr</value> </property> </configuration>