totxian 2020-02-11
本教程需要3台Linu机器,主机也好,虚机也好。本例中每台内存不少于2G。系统使用CentOS7。
本教程并未采用CDH这样的成型产品,原因有二,一是CDH占用内存较多,少于16G内存的电脑,无法用虚机完成所有教程中的内容;二是学习大数据的时候还是应该尽量从基本的操作开始,这样在遇到问题时更容易定位错误。
如果是生产环境,仍然建议使用CDH,毕竟稳定和监控才是生产环境的追求。
大数据领域,各组件还在各自发展,所以各组件版本间会存在一些适配的情况,如果是第一次安装,建议使用和教程一样的版本安装和学习。
Hadoop | 2.9.2 |
ZooKeeper | 3.5.6 |
Spark | 2.4.4 |
如果是使用虚机的话,当然有很多选择。本教程中使用的是VmWare,版本是15.5。
操作默认在root用户下,如更换用户会明确说明。生产环境建议使用单独的用户。
Hadoop集群安装,NameNode的HA配置,Yarn的ResourceManager的HA配置。
本章,最终搭建后的服务分配如下:
主机名 | node01 | node02 | node03 |
Hadoop | NameNode | NameNode | |
DataNode | DataNode | DataNode | |
JournalNode | JournalNode | JournalNode | |
DFSZKFailoverController | DFSZKFailoverController | ||
ZooKeeper | QuorumPeerMain | QuorumPeerMain | QuorumPeerMain |
Yarn | ResourceManager | ResourceManager | |
NodeManager | NodeManager | NodeManager | |
JobHistoryServer |
vi /etc/sysconfig/network-scripts/ifcfg-ens33 BOOTPROTO="static" IPADDR=192.168.32.110 NETMASK=255.255.255.0 GATEWAY=192.168.32.2 DNS1=8.8.8.8
ifcfg-ens33是网卡的名称,因机器而异。
ip地址和gateway请根据实际情况配置。
三台机器的ip最后一段分别为110,120,130。
在root用户下执行如下命令
systemctl stop firewalld systemctl disable firewalld
在root用户下执行如下命令,在打开的文件中添加如下一行,并保存退出(:wq)
vi /etc/selinux/config SELINUX=disabled
第一台:
hostnamectl set-hostname node01
第二台:
hostnamectl set-hostname node02
第三台:
hostnamectl set-hostname node03
在打开的文件中增加如下三行。
vi /etc/hosts 192.168.32.110 node01 192.168.32.120 node02 192.168.32.130 node03
安装ntp服务,启动ntp
yum install -y ntp systemctl enable ntpd systemctl start ntpd
设置时区为上海
timedatectl set-timezone Asia/Shanghai timedatactl set-ntp yes
查看时间状态
ntpq -p
使用Oracle的JDK8。
检查是否已经安装JDK
rpm -qa|grep jdk
如果已经安装了openjdk,删除。
yum -y remove java-1.7.0-openjdk*
安装JDK8的rpm包。安装包从此处下载:https://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html
创建一个目录存放后面所需要的组件安装文件
>mkdir /tools
将下载的rpm包上传到tools目录中,执行安装命令
rpm -ivh jdk-8u211-linux-x64.rpm
验证安装
java -version
如果显示了java的版本号则标识安装成功。
三台机器上执行如下命令
ssh-keygen -t rsa
将密钥互相拷贝
ssh-copy-id node01 ssh-copy-id node02 ssh-copy-id node03
验证。在三台机器上可以互相免密ssh登录旧可以了。
ssh node0${n}
在profile文件最后添加
vi /etc/profile export JAVA_HOME=/usr/java/default export PATH=$PATH:$JAVA_HOME/bin
让设置生效
source /etc/profile
zookeeper的原理并不复杂,就是在一个分布式环境里建不同的目录,目录里存一些值。其他系统通过设置和读取zookeeper里的值,来明确多个服务之间的竞争关系。
很多大数据组件都是通过zookeeper来实现高可用的。
在node01上安装wget
yum install -y wget
wget https://www-us.apache.org/dist/zookeeper/zookeeper-3.5.6/apache-zookeeper-3.5.6-bin.tar.gz
解压
tar zxf apache-zookeeper-3.5.6-bin.tar.gz
为了后续简化命令,重命名一下目录
mv apache-zookeeper-3.5.6-bin zk-3.5.6
从sample复制一份配置文件
cd zk-3.5.6/conf cp zoo_sample.cfg zoo.cfg vi zoo.cfg
按如下修改
tickTime=2000 dataDir=/data/zkdata clientPort=2181 initLimit=5 syncLimit=2 server.1=node01:2888:3888 server.2=node02:2888:3888 server.3=node03:2888:3888
将node01上的zk-3.5.6目录拷贝到node02和node03上
scp -r zk-3.5.6/ root@node02:/tools scp -r zk-3.5.6/ root@node03:/tools
在三台机器上创建数据目录
mkdir -p /data/zkdata
创建myid文件,myid文件中保存server.X中的X。
node01上编辑
vi /data/zkdata/myid 1
node02上编辑
vi /data/zkdata/myid 2
node03上编辑
vi /data/zkdata/myid 3
修改三台机器的profile文件
vi /etc/profile export ZOOKEEPER_HOME=/tools/zk-3.5.6 export PATH=$PATH:$ZOOKEEPER_HOME/bin
配置生效
source /etc/profile
三台机器都执行启动命令
zkServer.sh start
出现Starting zookeep ... STARTED,则表示起送成功。
查看状态
zkServer.sh status
三台机器中有1台是leader,2台是follower。
用jps命令可以看到QuorumPeerMain的一个进程。
zookeeper安装完毕,有兴趣的可以用zkCli.sh -server node01:2181来登录进zookeeper查看里面的目录结构和值。推出zkCli的命令是quit。
关闭zookeeper的命令是zeServer.sh stop
Hadoop的HA是指NameNode的HA。
在node01上下载hadoop压缩包
cd /tools wget http://mirrors.tuna.tsinghua.edu.cn/apache/hadoop/common/hadoop-2.9.2/hadoop-2.9.2.tar.gz
解压
tar zxf hadoop-2.9.2.tar.gz
修改目录权限
chown -R root:root hadoop-2.9.2
编辑三台机器的/etc/profile
vi /etc/profile export HADOOP_HOME=/tools/hadoop-2.9.2 export HADOOP_PREFIX=$HADOOP_HOME export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
配置生效
source /etc/profile
在node01上设置${HADOOP_HOME}/etc/hadoop/hadoop-env.sh、mapred-env.sh、yarn-env.sh三个文件里的JAVA_HOME
export JAVA_HOME=/usr/java/default
以上是必须配置的。除此以外还可以配置各个服务启动时的参数。
生产环境中有应该再配置HADOOP_PID_DIR和HADOOP_LOG_DIR,两个目录的权限应该设为hadoop的用户才能访问。HADOOP_HEAPSIZE根据机器的内存设置,默认1000MB。
编辑${HADOOP_HOME}/etc/hadoop/hdfs-site.xml,configuration中增加:
<!-- 为名称服务集群其一个名字 --> <property> <name>dfs.nameservices</name> <value>mycluster</value> </property> <!-- 为每个节点的名称服务起一个名字,当前最多只能配2个节点 --> <property> <name>dfs.ha.namenodes.mycluster</name> <value>nn1,nn2</value> </property> <!-- 配置每个节点的rpc监听地址,我们选用node01和node02做名称服务节点 --> <property> <name>dfs.namenode.rpc-address.mycluster.nn1</name> <value>node01:8020</value> </property> <property> <name>dfs.namenode.rpc-address.mycluster.nn2</name> <value>node02:8020</value> </property> <!-- 配置每个节点的http服务地址 --> <property> <name>dfs.namenode.http-address.mycluster.nn1</name> <value>node01:50070</value> </property> <property> <name>dfs.namenode.http-address.mycluster.nn2</name> <value>node02:50070</value> </property> <!-- 设置共享目录服务,用于存储名称服务的共享信息 --> <property> <name>dfs.namenode.shared.edits.dir</name> <value>qjournal://node01:8485;node02:8485;node03:8485/mycluster</value> </property> <!-- HDFS客户端联系激活的名称节点的class --> <property> <name>dfs.client.failover.proxy.provider.mycluster</name> <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value> </property> <!-- 主名称服务发生故障时的,尝试关闭主节点的方法。生产环境中最好先配置sshfence,shell的也不能少 --> <property> <name>dfs.ha.fencing.methods</name> <value>shell(/bin/true)</value> </property> <!-- 设置journalnode的编辑目录 --> <property> <name>dfs.journalnode.edits.dir</name> <value>/data/hadoop/journal</value> </property> <!-- 数据备份数,生产环境不用配这个 --> <property> <name>dfs.replication</name> <value>2</value> </property> <!-- 名称节点和数据节点的存储目录 --> <property> <name>dfs.namenode.name.dir</name> <value>/data/hadoop/dfs/name</value> </property> <property> <name>dfs.datanode.data.dir</name> <value>/data/hadoop/dfs/data</value> </property>
在三台机器上创建目录
mkdir -p /data/hadoop/journal mkdir -p /data/hadoop/dfs
编辑${HADOOP_HOME}/etc/hadoop/core-site.xml,configuration中增加:
<property> <name>fs.defaultFS</name> <value>hdfs://mycluster</value> </property>
编辑${HADOOP_HOME}/etc/hadoop/slaves文件
vi hadoop-2.9.2/etc/hadoop/slaves node01 node02 node03
将node01的hadoop-2.9.2拷贝到node02和node03
scp -r hadoop-2.9.2 root@node02:/tools/ scp -r hadoop-2.9.2 root@node03:/tools/
在三台机器上启动JournalNode守护程序
hadoop-daemon.sh start journalnode
在node01格式化NameNodfe
hdfs namenode -format
启动node01的namenode
hadoop-daemon.sh start namenode
在node02上复制namenode信息
hdfs namenode -bootstrapStandby
关闭node01的namenode
hadoop-daemon.sh stop namenode
启动HDFS
start-dfs.sh
验证,在三台机器上执行jps命令(如果启动了zookeeper,还会有QuorumPeerMain)
JournalNode | JournalNode | JournalNode |
DataNode | DataNode | DataNode |
NameNode | NameNode | Jps |
Jps | Jps |
此时用ha管理工具查看两个namenode都是standby状态
hdfs haadmin -getAllServiceState node01:8020 standby node02:8020 standby
至此我们设置了2个namenode。激活一个后就可以正常工作了,但是激活的发生故障时并不会自动改变另一个的standby状态。所以需要下面的步骤。
先停止HDFS服务,在node01上执行
stop-dfs.sh
编辑node01上的${HADOOP_HOME}/etc/hadoop/hdfs-site.xml,configuration中增加:
<property> <name>dfs.ha.automatic-failover.enabled</name> <value>true</value> </property>
编辑node01上的${HADOOP_HOME}/etc/hadoop/core-site.xml,configuration中增加:
<property> <name>ha.zookeeper.quorum</name> <value>node01:2181,node02:2181,node03:2181</value> </property>
拷贝配置文件到node02和node03上
cd /tools/hadoop-2.9.2/etc/hadoop scp hdfs-site.xml root@node02:`pwd` scp hdfs-site.xml root@node03:`pwd` scp core-site.xml root@node02:`pwd` scp core-site.xml root@node03:`pwd`
三台机器上启动zookeeper(如果已经启动,忽略此步)
在zookeeper里初始化HA的状态
hdfs zkfc -formatZK
启动HDFS
start-dfs.sh
用jps验证服务是否已启动
QuorumPeerMain | QuorumPeerMain | QuorumPeerMain |
JournalNode | JournalNode | JournalNode |
DFSZKFailoverController | DFSZKFailoverController | DataNode |
NameNode | NameNode | |
DataNode | DataNode |
查看当前激活的NameNode是哪个
hdfs haadmin -getAllServiceState node01:8020 active node02:8020 standby
如上,将node01的NameNode服务kill掉,或拔掉node01的网线,或关掉node01,再检查一下NameNode的激活状态,应该变为node02 active。
hdfs haadmin -getAllServiceState 19/12/06 15:25:11 INFO ipc.Client: Retrying connect to server: node01/192.168.32.110:8020. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS) node01:8020 Failed to connect: Call From node01/192.168.32.110 to node01:8020 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused node02:8020 active
yarn的HA是指ResourceManager的高可用。
编辑node01上的${HADOOP_HOME}/etc/hadoop/yarn-site.xml,configuration中增加:
<property> <name>yarn.nodemanager.aux-services</name> <value>mapreduce_shuffle</value> </property> <!-- 启动ResourceManager的HA --> <property> <name>yarn.resourcemanager.ha.enabled</name> <value>true</value> </property> <!-- 集群名称 --> <property> <name>yarn.resourcemanager.cluster-id</name> <value>cluster1</value> </property> <!-- ResourceManager的逻辑名称 --> <property> <name>yarn.resourcemanager.ha.rm-ids</name> <value>rm1,rm2</value> </property> <!-- 每个节点对应的主机地址 --> <property> <name>yarn.resourcemanager.hostname.rm1</name> <value>node01</value> </property> <property> <name>yarn.resourcemanager.hostname.rm2</name> <value>node03</value> </property> <!-- 每个节点的web地址 --> <property> <name>yarn.resourcemanager.webapp.address.rm1</name> <value>node01:8088</value> </property> <property> <name>yarn.resourcemanager.webapp.address.rm2</name> <value>node03:8088</value> </property> <!-- zookeeper服务地址 --> <property> <name>yarn.resourcemanager.zk-address</name> <value>node01:2181,node02:2181,node03:2181</value> </property> <!-- 日志相关设置 --> <property> <name>yarn.log-aggregation-enable</name> <value>true</value> </property> <property> <name>yarn.log-aggregation.retain-seconds</name> <value>604800</value> </property> <property> <name>yarn.log.server.url</name> <value>http://node03:19888/jobhistory/logs</value> </property>
拷贝到node02和node03机器上
cd /tools/hadoop-2.9.2/etc/hadoop scp yarn-site.xml root@node02:`pwd` scp yarn-site.xml root@node03:`pwd`
编辑node01上的${HADOOP_HOME}/etc/hadoop/mapred-site.xml,configuration中增加:
此步与HA无关,运行mapreduce时需要
cd /tools/hadoop-2.9.2/etc/hadoop cp mapred-site.xml.template mapred-site.xml vi mapred-site.xml <property> <name>mapreduce.framework.name</name> <value>yarn</value> </property> <property> <name>mapreduce.jobhistory.address</name> <value>node03:10020</value> </property> <property> <name>mapreduce.jobhistory.webapp.address</name> <value>node03:19888</value> </property>
先启动HDFS,如果已启动请忽略
start-dfs.sh
启动YARN
start-yarn.sh
此时只会启动一个ResouceManager,在node03再启动ResourceManager。
yarn-daemon.sh start resourcemanager
在node03上启动jobhistory服务(此步与HA无关)
mr-jobhistory-daemon.sh start historyserver
验证
yarn rmadmin -getAllServiceState node01:8033 active node03:8033 standby
验证HA,kill掉node01的ResourceManager,再查看状态
yarn rmadmin -getAllServiceState 19/12/06 16:48:38 INFO ipc.Client: Retrying connect to server: node01/192.168.32.110:8033. Already tried 0 time(s); retry policy is RetryUpToMaximumCountWithFixedSleep(maxRetries=1, sleepTime=1000 MILLISECONDS) node01:8033 Failed to connect: Call From node01/192.168.32.110 to node01:8033 failed on connection exception: java.net.ConnectException: Connection refused; For more details see: http://wiki.apache.org/hadoop/ConnectionRefused node03:8033 active
配置客户端的host,增加node01-03的对应关系。
NameNode nn1:node01:50070
NameNode nn2:node02:50070
ResourceManage:node01(node03):8088 #会自动跳转到激活的主机
JobHistory: node03:19888/jobhistory
开启服务:zkServer.sh start
关闭服务:zkServer.sh stop
命令行客户端:zkCli.sh -server xx.xx.xx.xx:2181
启动HDFS:start-dfs.sh
关闭HDFS:stop-dfs.sh
启动JournalNode:hadoop-daemon.sh start journalnode
关闭JournalNode:hadoop-daemon.sh stop journalnode
启动NameNode:hadoop-daemon.sh start namenode
关闭NameNode:hadoop-daemon.sh stop namenode
启动yarn:start-yarn.sh
关闭yarn:stop-yarn.sh
启动ResourceManager:yarn-daemon.sh start resourcemanager
关闭ResourceManager:yarn-daemon.sh stop resourcemanager
启动JobHistoryServer:mr-jobhistory-daemon.sh start historyserver
关闭JobHistoryServer:mr-jobhistory-daemon.sh stop historyserver
写两个脚本,用于启动和关闭所有服务。
hadoop本身带的start-all.sh并不适用于HA的情况,所以需要在node01上写一个。参考如下:
start-mycluster.sh
#!/bin/bash zkServer.sh start ssh node02 > /dev/null 2>&1 <<eeooff zkServer.sh start exit eeooff echo "node02 started ZK." ssh node03 > /dev/null 2>&1 <<eeooff zkServer.sh start exit eeooff echo "node03 started ZK." start-dfs.sh && start-yarn.sh ssh node03 > /dev/null 2>&1 <<eeooff yarn-daemon.sh start resourcemanager mr-jobhistory-daemon.sh start historyserver exit eeooff echo "node03 started resourceManager and historyServer."
stop-mycluster.sh
#!/bin/bash ssh node03 > /dev/null 2>&1 <<eeooff mr-jobhistory-daemon.sh stop historyserver yarn-daemon.sh stop resourcemanager exit eeooff echo "node03 stoped historyServer and resourceManager." stop-yarn.sh && stop-dfs.sh zkServer.sh stop ssh node02 > /dev/null 2>&1 << eeooff zkServer.sh stop exit eeooff echo "node02 stoped ZK." ssh node03 > /dev/null 2>&1 << eeooff zkServer.sh stop exit eeooff echo "node03 stoped ZK."
给两个执行文件权限
chmod 700 start-mycluster.sh chmod 700 stop-mycluster.sh
[1] https://hadoop.apache.org/docs/r2.9.2/hadoop-project-dist/hadoop-common/core-default.xml core-site.xml的参数和默认值