背景
在搭建完hadoop伪分布式后会发现,hadoop中只有一个NameNode,对于只有一个NameNode的集群,如果NameNode机器出现意外情况,将导致整个集群无法使用,直到NameNode 重新启动。
影响HDFS集群不可用主要包括以下两种情况:一是NameNode机器宕机,将导致集群不可用,重启NameNode之后才可使用;二是计划内的NameNode节点软件或硬件升级,导致集群在短时间内不可用。
所以我们还需要搭建NameNode集群解决此问题,HDFS HA:通过主备NameNode解决
如果主NameNode发生故障,则切换到备NameNode上。
1 机器规划
准备四台虚拟机,规划如下
主机 | node2 | node3 | node4 | node5 |
---|---|---|---|---|
节点 | NameNode | NameNode | ||
节点 | DataNode | DataNode | DataNode | |
节点 | ZooKeper | ZooKeper | ZooKeper | |
节点 | ZKFC | ZKFC | ||
节点 | JournalNode | JournalNode | JournalNode |
2 安装前准备
2.1 创建目录
四台机器创建安装包目录 apps
以及软件安装目录 app
mkdir - p /apps
mkdir - p /opt/app
xshell5 可以4台机器一起执行
2.2 设置免密登录
2.2.1设置主机名字
在node2 上编辑配置文件/etc/hosts
vim /etc/hosts
添加如下内容
192.168.8.62 node2
192.168.8.63 node3
192.168.8.64 node4
192.168.8.66 node5
然后把文件传到node3,node4,node5上
scp /etc/hosts node3:"/etc/"
scp /etc/hosts node4:"/etc/"
scp /etc/hosts node5:"/etc/"
还未设置免密登录,所有要输入密码。
2.2.2 免密登录设置
所有机器回到home目录,
cd ~
然后在node2、node3、node4、node5 执行 生成公钥,
ssh-keygen -t dsa -P '' -f .ssh/id_dsa
然后在node2 上执行下面代码,把公钥追加到authorized_keys
cat .ssh/id_dsa.pub >>.ssh/authorized_keys
从node2上把authorized_keys传给node3
scp .ssh/authorized_keys node3:".ssh/"
在node3上执行,追加公钥到authorized_keys
cat .ssh/id_dsa.pub >>.ssh/authorized_keys
再把authorized_keys传给node4.
scp .ssh/authorized_keys node4:".ssh/"
在node4上追加公钥到authorized_keys
然后再把文件传给node5
scp .ssh/authorized_keys node5:".ssh/"
在node5上追加公钥到authorized_keys
然后再把文件传给node2
scp .ssh/authorized_keys node2:".ssh/"
再回到node2上可以查看authorized_keys ,可以看到所有主机的公钥都有了。
再把文件传给node3、node4
然后可以看到所有主机都可以免密登录了。最好每一台都验证一下。不然后面程序启动的时候会让输入密码。
3 安装包准备
在上一篇hadoop 伪分布式搭建实例中有下载hadoop下载教程,这里不做赘述。
将jdk hadoop zookeper 安装包上传 到node2 /apps 目录下
通过node2 把安装包传到node3,node4,node5 上
scp /apps/* node3:"/apps/" && scp /apps/* node4:"/apps/" && scp /apps/* node5:"/apps/"
4 jdk安装
所有机器切换到安装包目录
cd /apps
然后
rpm -ivh jdk-8u221-linux-x64.rpm
安装完以后在node2上配置环境变量
vim /etc/profile
添加
export JAVA_HOME=/usr/java/default
export PATH=$PATH:$JAVA_HOME/bin
5.安装 hadoop
所有机器在apps目录下解压hadoop 包
tar -zxvf hadoop-2.6.5-centos-2.6.32-754.3.5.el6.x86_64.tar.gz -C /opt/app
在node2 上 hadoop环境变量配置
vim /etc/profile
添加
export HADOOP_HOME=/opt/app/hadoop-2.6.5/
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
6 环境变量文件配置
然后把node2 上的/etc/profile 传到node[3-5]上
scp /etc/profile node3:"/etc" && scp /etc/profile node4:"/etc" && scp /etc/profile node5:"/etc"
然后所有机器 使profile配置文件生效
7 zookeper 安装
7.1 解压
在规划中,zookeper 服务器为node3,4,5.在这三台上解压
tar -zxvf zookeeper-3.4.6.tar.gz -C /opt/app
7.2 环境变量配置
在node3上 编辑环节变量配置文件
添加
export ZOOKEPER_PREFIX=/opt/app/zookeeper-3.4.6/
export PATH=$PATH:$ZOOKEPER_PREFIX/bin
7.3 zoo.cfg配置
在node3 上 进入
cd /opt/app/zookeeper-3.4.6/conf
执行
cp zoo_sample.cfg zoo.cfg
vim zoo.cfg
修改文件存目录
dataDir=/var/wh/zookeper/data
以及添加zookeper集群
server.1=node3:2881:3881
server.2=node4:2881:3881
server.3=node5:2881:3881
7.4 同步配置文件
把node3上的 profile 以及zoo.cfg同步到node4,node5上
scp zoo.cfg node4:"/opt/app/zookeeper-3.4.6/conf"
scp zoo.cfg node5:"/opt/app/zookeeper-3.4.6/conf"
scp /etc/profile node4:"/etc/" && scp /etc/profile node5:"/etc/"
使配置文件生效,在node3,node4 node5 上执行
source /etc/profile
7.5 创建zookeper文件目录
在node3-5上都执行如下命令,这个文件也就是zoo.cfg中的文件存放目录
mkdir -p /var/wh/zookeper/data
然后在node3上存入myid,
echo 1 >>/var/wh/zookeper/data/myid
然后在node4上存入myid 值为2,
echo 2 >>/var/wh/zookeper/data/myid
然后在node5上存入myid值为3,
echo 3 >>/var/wh/zookeper/data/myid
7.6 启动 zookeper
在 node3上 启动
zkServer.sh start
然后再查看zookeper状态
zkServer.sh status
发现 zookeper 提示没有启动,这是由于过半原理,这里zookeper集群有三台,所以至少要启动两台,zookeper才是真正的启动
再回到node4上启动
看到启动以后zookeper状态为运行状态,并且leader为node4,因为node4刚刚配置的myid为2,比node3的myid=1 大,所以node4为leade
回到node5上也启动zookeper,并查看zookeper状态,发现node5虽然myid为3,最大。但是因为zookeper已经在运行了,所以node5只能是follower。
8 hadoop 配置
8.1hadoop java 环境变量配置
回到node2上 执行
vim /opt/app/hadoop-2.6.5/etc/hadoop/hadoop-env.sh
修改文件中java环境变量
export JAVA_HOME=/usr/java/default
8.2 core-site.xml
在node2上
vim /opt/app/hadoop-2.6.5/etc/hadoop/core-site.xml
在 configuration里面添加如下配置
<property>
<name>fs.defaultFS</name>
<value>hdfs://mycluster</value>
</property>
<property>
<name>hadoop.tmp.dir</name>
<value>/var/wh/hadoop/ha</value>
</property>
<!-- 指定每个zookeeper服务器的位置和客户端端口号 -->
<property>
<name>ha.zookeeper.quorum</name>
<value>node3:2181,node4:2181,node5:2181</value>
</property>
8.3 hdfs-site.xml
在node2上
vim /opt/app/hadoop-2.6.5/etc/hadoop/hdfs-site.xml
在 configuration里面添加如下配置
<!-- 指定block默认副本个数 -->
<property>
<name>dfs.replication</name>
<value>2</value>
</property>
<!-- 用于解析fs.defaultFS中hdfs://mycluster中的mycluster地址 -->
<property>
<name>dfs.nameservices</name>
<value>mycluster</value>
</property>
<!-- mycluster下面由两个namenode服务支撑 -->
<property>
<name>dfs.ha.namenodes.mycluster</name>
<value>nn1,nn2</value>
</property>
<!--指定nn1的地址和端口号,发布的是一个hdfs://的服务-->
<property>
<name>dfs.namenode.rpc-address.mycluster.nn1</name>
<value>node2:8020</value>
</property>
<property>
<name>dfs.namenode.rpc-address.mycluster.nn2</name>
<value>node3:8020</value>
</property>
<!--指定三台journal服务器的地址-->
<property>
<name>dfs.namenode.shared.edits.dir</name>
<value>qjournal://node2:8485;node3:8485;node4:8485/mycluster</value>
</property>
<!-- 指定客户端查找active的namenode的策略:
会给所有namenode发请求,以决定哪个是active的 -->
<property>
<name>dfs.client.failover.proxy.provider.mycluster</name>
<value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
</property>
<!--在发生故障切换的时候,ssh到对方服务器,将namenode进程kill掉 kill -9 55767-->
<property>
<name>dfs.ha.fencing.methods</name>
<value>sshfence</value>
</property>
<property>
<name>dfs.ha.fencing.ssh.private-key-files</name>
<value>/root/.ssh/id_dsa</value>
</property>
<!-- 指定journalnode在哪个目录存放edits log文件 -->
<property>
<name>dfs.journalnode.edits.dir</name>
<value>/var/wh/hadoop/ha/jnn</value>
</property>
<!--启用自动故障切换-->
<property>
<name>dfs.ha.automatic-failover.enabled</name>
<value>true</value>
</property>
8.4 datanode配置
datanode为node3-5
vim /opt/app/hadoop-2.6.5/etc/hadoop/slaves
文件内容为
node3
node4
node5
文件
8.5 同步hadoop配置文件
把node2上的文件同步到node3-5上
scp /opt/app/hadoop-2.6.5/etc/hadoop/* node3:"/opt/app/hadoop-2.6.5/etc/hadoop/"
scp /opt/app/hadoop-2.6.5/etc/hadoop/* node4:"/opt/app/hadoop-2.6.5/etc/hadoop/"
scp /opt/app/hadoop-2.6.5/etc/hadoop/* node5:"/opt/app/hadoop-2.6.5/etc/hadoop/"
9 启动hadoop
9.1 启动journalnode
node2,node3,node4为journalnode节点 所有在这三台上启动journalnode
hadoop-daemon.sh start journalnode
启动后查看java 进程,已启动 journalnode
9.2 NameNode格式化HDFS
规划NameNode为node2或者node3,所有任意选择一台执行
hdfs namenode -format
表示成功格式化
9.3 启动NameNode
在node2上启动
hadoop-daemon.sh start namenode
在另一台namenode node3上同步元数据
hdfs namenode -bootstrapStandby
同步后 在node3上进入
/var/wh/hadoop/ha/dfs/name/current 目录可以看到数据
cd /var/wh/hadoop/ha/dfs/name/current
9.4 初始化zkfc
初始化zookeeper上的内容 一定是在namenode节点上。
hdfs zkfc -formatZK
在zookeper创建节点
9.5 启动hadoop集群
可在node2到node5这四台服务器上任意位置执行start-dfs.sh,停止命令为
stop-dfs.sh
看到hadoop集群启动后,按照规划启动了namenode,datanode,journalnode以及zkfc
9.6 本地 hosts文件配置
本地配置hosts文件,以便能解析node[3-5],
目录C:\Windows\System32\drivers\etc\hosts
添加如下集群服务器信息
192.168.8.62 node2
192.168.8.63 node3
192.168.8.64 node4
192.168.8.66 node5
10 验证
浏览器输入
http://node2:50070/
看到现在node2为主namenode
浏览器输入:http://node3:50070/
看到node3处于standby状态
当我们会到node2上 kill掉namenode进程,模拟namenode故障宕机。
jps
kill -9 1851
然后再刷新浏览器http://node2:50070/ 无法访问,然后刷新http://node3:50070/ 。
看到node3状态变为active
datanode信息也与我们配置一样为node3.node4,node5
然后我们再回到node2上启动namenode。
hadoop-daemon.sh start namenode
然后再次访问node2:50070看到node2状态为standby
后台验证,在zookeper任意一台服务器上
输入
zkCli.sh
输入
ls /hadoop-ha/mycluster
get /hadoop-ha/mycluster/ActiveStandbyElectorLock
这里表示node3为active