Hadoop集群(一)—— 高可用集群搭建

caroly 2020年05月06日 148次浏览

以下所有操作均在测试环境中执行

环境准备

于『VMWare』中安装『CentOS-6.8-x86_64』。注:尽量安装最新版VM,旧版会因一些操作导致虚拟机卡死,这将对我们接下来的操作产生严重影响

安装过程没什么可说的,唯一一点就是在创建磁盘分区的时候尽量选择『Create Custom Layout』(创建自定义布局)。

分区大小(M)
/boot200
swap2048
/Fill to maximum allowable size(使用全部可用空间)

配置静态『IP』。

vi /etc/sysconfig/network-scripts/ifcfg-eth0
参数参数值
HWADDR^1注释掉该行
ONBOOTyes
BOOTPROTOstatic
IPADDR^2虚拟网络编辑器-->VMnet8-->子网IP(替换第四组的0为100+)
NETMASK虚拟网络编辑器-->VMnet8-->子网掩码
GATEWAYNAT设置-->网关IP
DNS1114.114.114.114
DNS2^38.8.8.8

重新启动下网络。

service network restart

关闭防火墙^4

service iptables stop

禁用防火墙。

chkconfig iptables off

禁用安全模块^5

vi /etc/selinux/config
参数参数值
SELINUXdisabled

此文件中会利用『eth0』和硬件地址做一个关联绑定。为方便后续克隆,保证克隆出的系统『eth0』接口可用,需要将此文件删除^6,解除绑定关系。

rm -rf /etc/udev/rules.d/70-persistent-net.rules

poweroff 关机拍快照。

在快照管理器中选中快照,点击克隆,一路默认到设置虚拟机名称,输入自定义名称(PS:caroly01),选择克隆路径进行克隆。重复此操作克隆四台虚拟机(caroly01、caroly02、caroly03、caroly04)。


给四台克隆虚拟机分配『IP』,分别为『240.151』『240.152』『240.153』『240.154』,并重启网络。

service network restart

给四台克隆虚拟机重设主机名。

vi /etc/sysconfig/network

更改『HOSTNAME』的值分别为『caroly01』『caroly02』『caroly03』『caroly04』。注:主机名生效需要重启虚拟机

给四台克隆虚拟机配置『hosts』^7

vi /etc/hosts

本地物理机配置『hosts』

C:\Windows\System32\drivers\etc\hosts
IP地址主机名
192.168.240.151caroly01
192.168.240.152caroly02
192.168.240.153caroly03
192.168.240.154caroly04

poweroff 关机拍快照。

重新登陆虚拟机可以进行互通测试。


使用『MobaXterm』连接四台虚拟机,向四台虚拟机发送同步时间指令。

ntpdate 0.centos.pool.ntp.org

输入『date』可以查看系统当前时间。

注:点击菜单栏的『MultiExec』,可以同时向四台虚拟机发送相同指令


检查一下是否可以在没有密码的情况下SSH到本虚拟机。

ssh localhost

如果需要输入密码才能SSH到本虚拟机,执行以下命令:

ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat ~/.ssh/id_dsa.pub >> ~/.ssh/authorized_keys

将『caroly01』的 .ssh/id_dsa.pub分发给其他三台虚拟机^10

scp id_dsa.pub caroly02:`pwd`/caroly01.pub
scp id_dsa.pub caroly03:`pwd`/caroly01.pub
scp id_dsa.pub caroly04:`pwd`/caroly01.pub

分发完毕后在被分发的虚拟机中追加此文件内容到 authorized_keys 文件

cat caroly01.pub >> authorized_keys

可以测试一下配置是否正确。


将『JDK』的『RPM』包上传到四台虚拟机,安装。

rpm -i jdk-8u251-linux-x64.rpm

配置环境变量,在最后新增两行^8

vi + /etc/profile
export JAVA_HOME=/usr/java/jdk1.8.0_251-amd64
PATH=$PATH:$JAVA_HOME/bin

保存退出后重新执行该文件使之生效^9

. /etc/profile

Hadoop配置

主机名NameNodeSecondaryNameNodeDataNode
caroly01
caroly02
caroly03
caroly04
  • NameNode:是HDFS的管理节点,它存储了元数据(文件对应的数据块位置、文件大小、文件权限等)信息,同时负责读、写调度和存储分配。
  • SecondaryNameNode:负责合并NameNode的edit logs到fsimage中。
  • DataNode:该节点是真正的数据存储节点,用来存储数据。另外,在DataNode上的每个数据块会根据设置的副本数进行分级复制,保证同一个文件的每个数据块副本都不在同一个机器上。

解压『Hadoop』到目录 opt/caroly

tar xf hadoop-2.9.2.tar.gz -C /opt/caroly

配置环境变量,在最后新增两行:

vi + /etc/profile
export HADOOP_HOME=/opt/caroly/hadoop-2.9.2
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin

修改以下可执行文件:cd /opt/caroly/hadoop-2.9.2/etc/hadoop

文件名修改参数
hadoop-env.shexport JAVA_HOME=/usr/java/jdk1.8.0_251-amd64
mapred-env.shexport JAVA_HOME=/usr/java/jdk1.8.0_251-amd64
yarn-env.shexport JAVA_HOME=/usr/java/jdk1.8.0_251-amd64

修改以下配置文件:

vi /opt/caroly/hadoop-2.9.2/etc/hadoop/core-site.xml

<configuration>
    <!-- 指定在Hadoop中要使用的文件系统 -->
    <property>
        <name>fs.defaultFS</name>
        <value>hdfs://mycluster</value>
    </property>
    <!-- Hadoop文件系统依赖的基础配置,很多路径都依赖它。默认路径在/tmp下,Linux重启后会删除,需更改位置。 -->
    <property>
        <name>hadoop.tmp.dir</name>
        <value>/var/caroly/hadoop/full</value>
    </property>
    <!-- 指定zookeeper地址 -->
    <property>
        <name>ha.zookeeper.quorum</name>
        <value>caroly02:2181,caroly03:2181,caroly04:2181</value>
    </property>
</configuration>

vi /opt/caroly/hadoop-2.9.2/etc/hadoop/hdfs-site.xml

<configuration>
    <!-- 默认块复制。创建文件时可以指定实际的复制数量。如果未在创建时指定复制,则使用默认值。 -->             
    <property>
        <name>dfs.replication</name>
        <value>2</value>
    </property>
	<!-- 集群的逻辑名称 -->
    <property>
        <name>dfs.nameservices</name>
        <value>mycluster</value>
    </property>
	<!-- 每个NameNode的唯一标识符,以下是两个 -->
    <property>
        <name>dfs.ha.namenodes.mycluster</name>
        <value>nn1,nn2</value>
    </property>
    <!-- nn1监听的RPC地址 -->
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn1</name>
        <value>caroly01:8020</value>
    </property>
    <!-- nn2监听的RPC地址 -->
    <property>
        <name>dfs.namenode.rpc-address.mycluster.nn2</name>
        <value>caroly02:8020</value>
    </property>
    <!-- nn1监听的HTTP地址 -->
    <property>
        <name>dfs.namenode.http-address.mycluster.nn1</name>
        <value>caroly01:50070</value>
    </property>
    <!-- nn2监听的HTTP地址 -->
    <property>
        <name>dfs.namenode.http-address.mycluster.nn2</name>
        <value>caroly02:50070</value>
    </property>
    <!-- 配置提供共享编辑存储的JournalNodes的地址,该地址由Active NameNode写入并由Standby NameNode读取,以与Active NameNode所做的所有文件系统更改保持最新。 -->
    <property>
        <name>dfs.namenode.shared.edits.dir</name>
        <value>qjournal://caroly01:8485;caroly02:8485;caroly03:8485/mycluster</value>
    </property>
    <!-- 配置Java类的名称,DFS客户端将使用该Java类来确定哪个NameNode是当前的Active,从而确定哪个NameNode当前正在服务于客户端请求。 -->
    <property>
        <name>dfs.client.failover.proxy.provider.mycluster</name>   <value>org.apache.hadoop.hdfs.server.namenode.ha.ConfiguredFailoverProxyProvider</value>
    </property>
    <!-- 为了保证系统的正确性,在任何给定时间只有一个NameNode处于Active状态。重要的是,使用Quorum Journal Manager时,将只允许一个NameNode写入JournalNodes,因此不会因"脑裂"情况而损坏文件系统元数据。多个机制用换行分割。 -->
    <property>
        <name>dfs.ha.fencing.methods</name>
        <value>sshfence</value>
    </property>
    <!-- 使用sshfence隔离机制时需要ssh免登录 -->
    <property>
        <name>dfs.ha.fencing.ssh.private-key-files</name>
        <value>/root/.ssh/id_dsa</value>
    </property>
    <!-- 指定JournalNode在本地磁盘存放数据的位置 -->
    <property>
        <name>dfs.journalnode.edits.dir</name>
        <value>/var/caroly/hadoop/ha/journalnode</value>
    </property>
    <!-- 启用故障转移机制 -->
    <property>
   	<name>dfs.ha.automatic-failover.enabled</name>
        <value>true</value>
    </property>
</configuration>

vi /opt/caroly/hadoop-2.9.2/etc/hadoop/slaves

#localhost
caroly02
caroly03
caroly04

配置好后进入 opt 目录,将 caroly 目录分发^11给其他三台虚拟机,并在其他三台虚拟机中配好『JDK』以及『Hadoop』的环境变量。

scp -r caroly/ caroly02:`pwd`
scp -r caroly/ caroly03:`pwd`
scp -r caroly/ caroly04:`pwd`
----------------------------------
scp /etc/profile caroly02:/etc/
scp /etc/profile caroly03:/etc/
scp /etc/profile caroly04:/etc/
----------------------------------
. /etc/profile

ZooKeeper配置

NN-HA

主机名NameNode-1NameNode-2DataNodeZKZKFCJN
caroly01
caroly02
caroly03
caroly04
  • NameNode-1:主节点(active)。
  • NameNode-2:备节点(standby)。
  • DataNode:该节点是真正的数据存储节点,用来存储数据。另外,在DataNode上的每个数据块会根据设置的副本数进行分级复制,保证同一个文件的每个数据块副本都不在同一个机器上。
  • ZK(ZooKeeper):ZooKeeper提供了一个Leader Election机制,利用这个机制你可以在集群中开启多个master并使它们都注册到ZooKeeper实例。ZooKeeper会管理使其中只有一个是active的,其他的都是standby的。active状态的master可以提供服务,standby状态的则不可以。ZooKeeper保存了集群的状态信息,该信息包括所有的Worker,Driver 和Application。当active的Master出现故障时,ZooKeeper会从其他standby的master中选举出一台,然后该新选举出来的master会恢复挂掉了的master的状态信息,之后该Master就可以正常提供调度服务。
  • ZKFC(ZooKeeperFailoverController):是一个ZooKeeper客户端,监视和管理NameNode的状态。运行NameNode的每台机器也运行ZKFC,只有NameNode才有ZKFC进程,并且每个NameNode各一个。
    • 健康检测:ZKFC会周期性的向它监控的NameNode发生健康探测命令,从而鉴定某个NameNode是否处于正常工作状态。如果机器宕机,心跳失败,那么ZKFC就会标记它处于不健康的状态。
    • 会话管理:如果NameNode是健康的,ZKFC机会保持在Zookeeper中保持一个打开的会话,如果NameNode是active状态的,那么ZKFC还会在Zookeeper中占有一个类型为短暂类型的zNode。当这个NameNode挂掉时,这个zNode将会被删除。然后备用的NameNode得到这把锁,升级为主的NameNode,同时标记状态为active。当宕机的NameNode重新启动会再次注册Zookeeper,发现已经有zNode了,就自动变为standby状态。如此往复循环,保证高可靠性,但是目前仅支持最多配置两个NameNode。
    • master选举:如上所述,通过在Zookeeper中维持一个短暂类型的zNode,来实现抢占式的锁机制,从而判断哪个NameNode为active状态。
  • JN(JournalNode):NameNode之间共享数据,两个NameNode为了数据同步,会通过JournalNodes的独立进程进行相互通信。当active状态的NameNode的命名空间有任何修改时,会告知大部分的JournalNodes进程。standby状态的NameNode有能力读取JNs中的变更信息,并且一直监控edit log的变化,把变化应用于自己的命名空间。standby可以确保在集群出错时,命名空间状态已经完全同步了。

在『caroly02』『caroly03』『caroly04』中配置『ZooKeeper』。

tar xf zookeeper-3.4.6.tar.gz -C /opt/caroly/
cd /opt/caroly/
ln -s zookeeper-3.4.6 zookeeper
cd /opt/caroly/zookeeper-3.4.6/

修改配置文件:

cd conf/
mv zoo_sample.cfg zoo.cfg
vi zoo.cfg
#修改以下内容
dataDir=/var/caroly/zookeeper
#新增以下内容
server.1=caroly02:2888:3888
server.2=caroly03:2888:3888
server.3=caroly04:2888:3888

配置好后将『zookeeper-3.4.6』目录^14分发给『caroly03』『caroly04』。

cd /opt/caroly/
scp -r zookeeper-3.4.6/ caroly03:`pwd`
scp -r zookeeper-3.4.6/ caroly04:`pwd`

在『caroly03』『caroly04』中创建『ZooKeeper』的软链接。

cd /opt/caroly/
ln -s zookeeper-3.4.6 zookeeper

在『caroly02』『caroly03』『caroly04』中创建目录:

mkdir -p /var/caroly/zookeeper

为『ZooKeeper』配置编号:

​ 在『caroly02』中输入命令:

echo 1 > /var/caroly/zookeeper/myid

​ 在『caroly03』中输入命令:

echo 2 > /var/caroly/zookeeper/myid

​ 在『caroly04』中输入命令:

echo 3 > /var/caroly/zookeeper/myid

配置环境变量,在最后新增两行:

vi + /etc/profile
export ZOOKEEPER_HOME=/opt/caroly/zookeeper
PATH=$PATH:$JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$ZOOKEEPER_HOME/bin

保存退出后将此文件分发给『caroly03』『caroly04』:

scp /etc/profile caroly03:/etc/
scp /etc/profile caroly04:/etc/

重新执行该文件使之生效。

. /etc/profile

启动『ZooKeeper』集群,在『caroly02』『caroly03』『caroly04』中输入以下命令:

zkServer.sh start

启动『JournalNode』,在『caroly01』『caroly02』『caroly03』中输入以下命令:

hadoop-daemon.sh start journalnode

格式化节点,『caroly01』和『caroly02』任选一个,在『caroly01』中输入以下命令:

hdfs namenode -format

启动格式化的主节点『caroly01』:

hadoop-daemon.sh start namenode

把主节点上的元数据信息拷贝到当前目录之下,在『caroly02』中输入以下命令:

hdfs namenode -bootstrapStandby

在『ZooKeeper』中初始化所需的状态,在『caroly01』中输入以下命令:

hdfs zkfc -formatZK

启动当前集群,在『caroly01』中输入以下命令:

start-dfs.sh

集群启动


关闭当前集群,在『caroly01』中输入以下命令:

stop-dfs.sh

关闭『ZooKeeper』,在『caroly02』『caroly03』『caroly04』中输入以下命令:

zkServer.sh stop

再次启动集群需先启动『ZooKeeper』:

zkServer.sh start
start-dfs.sh

Hadoop MapReduce V2

ResourceManager(RM)负责跟踪集群中的资源,并调度应用程序(例如MapReduce作业)。

主机名NN-1NN-2DNZKZKFCJNRMNM
caroly01
caroly02
caroly03
caroly04
  • RM(ResourceManager):当应用程序对集群资源需求时,RS是Yarn集群主控节点,负责协调和管理整个集群(所有NodeManager)的资源。
  • NM(NodeManager):管理一个Yarn集群中的每一个节点。比如监视资源使用情况(CPU,内存,硬盘,网络),跟踪节点健康等。
  • ApplicationMaster:用户向Yarn集群提交应用程序(包含ApplicationMaster程序,ApplicationMaster启动命令,用户自己的程序)时:ApplicationMaster向资源调度器申请执行任务的资源容器Container,运行用户自己的程序任务job(可以用浏览器看Yarn里的job进展),监控整个任务的执行,跟踪整个任务的状态,处理任务失败等异常情况。
  • Container:资源分配的体现要用到一个抽象概念"容器"(Container)表示,Container将内存、CPU、磁盘、网络等资源封装在一起,这样可以起到限定资源边界的作用。比如给定一个Container的资源,里面包含3个G的内存,1G硬盘。当销毁Container时,连带的内存、硬盘都没有了。

在『caroly01』中修改以下配置文件:

cd /opt/caroly/hadoop-2.9.2/etc/hadoop

mv mapred-site.xml.template mapred-site.xml

vi mapred-site.xml

<configuration>
    <!-- 配置Yarn框架执行map-reduce处理程序-->
    <property>
        <name>mapreduce.framework.name</name>
        <value>yarn</value>
    </property>
    <!--日志监控服务的地址,一般填写为namenode机器地址,此处配置在caroly02上 -->
    <property>
        <name>mapreduce.jobhistroy.address</name>
        <value>caroly02:10020</value>
    </property>
</configuration>

vi yarn-site.xml

<configuration>
    <!-- NodeManager上运行的附属服务。需配置成mapreduce_shuffle,才可运行MapReduce程序 -->
    <property>
        <name>yarn.nodemanager.aux-services</name>
        <value>mapreduce_shuffle</value>
    </property>
    <!-- 开启高可用(RM HA)-->
    <property>
        <name>yarn.resourcemanager.ha.enabled</name>
        <value>true</value>
    </property>
    <!-- 集群标识,确保RM不会接管另一个集群(即不会成为其他集群的Active RM)-->
    <property>
        <name>yarn.resourcemanager.cluster-id</name>
        <value>cluster1</value>
    </property>
    <!-- RM的逻辑ID,比如rm1,rm2-->
    <property>
        <name>yarn.resourcemanager.ha.rm-ids</name>
        <value>rm1,rm2</value>
    </property>
    <!-- 为每个rm-id声明一个对应的主机名,也可以声明RM的服务地址 -->
    <property>
        <name>yarn.resourcemanager.hostname.rm1</name>
        <value>caroly03</value>
    </property>
    <property>
        <name>yarn.resourcemanager.hostname.rm2</name>
        <value>caroly04</value>
    </property>
    <!-- rm-zk的地址,同时用于状态存储和leader选举 -->
    <property>
        <name>yarn.resourcemanager.zk-address</name>
        <value>caroly02:2181,caroly03:2181,caroly04:2181</value>
    </property>
    <!-- 启用日志聚合功能,日志聚合开启后保存到HDFS上 -->
    <property>
        <name>yarn.log-aggregation-enable</name>
        <value>true</value>
    </property>
    <!-- 指定RM的web端访问地址 -->      
    <property>
        <name>yarn.resourcemanager.webapp.address.rm1</name>
        <value>caroly03:8088</value>
    </property>
    <!-- 指定RM的web端访问地址 -->    
    <property>
        <name>yarn.resourcemanager.webapp.address.rm2</name>
        <value>caroly04:8088</value>
    </property>
</configuration>

vi log4j.properties

# 添加如下
log4j.logger.org.apache.hadoop.util.NativeCodeLoader=ERROR

将这三个文件分发给『caroly02』『caroly03』『caroly04』:

scp mapred-site.xml yarn-site.xml log4j.properties caroly02:`pwd`
scp mapred-site.xml yarn-site.xml log4j.properties caroly03:`pwd`
scp mapred-site.xml yarn-site.xml log4j.properties caroly04:`pwd`

因『caroly03』『caroly04』配置高可用切换,需要配置免密登陆:

# 在caroly03中执行以下命令
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat id_dsa.pub >> authorized_keys
scp id_dsa.pub caroly04:`pwd`/caroly03.pub
#测试配置是否成功
ssh caroly04
---------------------------------------------
# 在caroly04中执行以下命令
ssh-keygen -t dsa -P '' -f ~/.ssh/id_dsa
cat id_dsa.pub >> authorized_keys
scp id_dsa.pub caroly03:`pwd`/caroly04.pub
# 测试配置是否成功
ssh caroly03

启动集群:

# 在caroly02、caroly03、caroly04中输入启动zk的命令
zkServer.sh start
# 在caroly01中启动hdfs
start-dfs.sh
# 在caroly01中启动yarn
start-yarn.sh
# 上述两条命令可以用 start-all.sh 替换
# 在caroly03、caroly04中启动RM
yarn-daemon.sh start resourcemanager
# 在四台虚拟机中启动historyserver
mr-jobhistory-daemon.sh start historyserver

通过浏览器访问RM:

caroly03:8088
或
caroly04:8088

其中,『Active Nodes』的值为 3 表示搭建成功(从节点为3个)。


单词统计,在『caroly01』中执行:

cd /opt/caroly/hadoop-2.9.2/share/hadoop/mapreduce
# 此目录下有一个mapreduce的例子包,封装有一些写好的job任务
# 此处用到这个包的wordcount程序
hadoop jar hadoop-mapreduce-examples-2.9.2.jar wordcount /user/root/test.txt /wordcount
# 执行这个jar包下的wordcount程序,计算第一个路径下的test.txt文件,输出目录为第二个路径下的wordcount目录。
# /wordcount目录可以不存在,若是存在必须是空目录。
# 查看结果
hdfs dfs -cat /wordcount/part-r-00000

关闭集群:

# 在caroly03、caroly04中关闭RM
yarn-daemon.sh stop resourcemanager
# 在四台虚拟机中关闭historyserver
mr-jobhistory-daemon.sh stop historyserver
# 在caroly01中关闭集群
stop-all.sh
# 在caroly02、caroly03、caroly04中关闭zk
zkServer.sh stop