一、前提条件

以下所有操作都基于Docker,需要Docker基础并具备Docker环境

二、备份和恢复镜像

先将配置好的Docker容器提交为镜像:

[xiaokang@hadoop docker_teach]$ sudo docker commit -a "xiaokang" -m "This is for backup" dadfd67c672d xiaokangxxs/hadoop-commit:2.7.7

备份镜像:

#将上面构建出来的镜像保存为docker_teach目录下的docker-hadoop-pseudo_distributed.tar.gz文件
[xiaokang@hadoop docker_teach]$ sudo docker save -o hadoop-commit-pseudo.tar.gz xiaokangxxs/hadoop-commit:2.7.7

Docker环境下Hadoop完全分布式_分布式

恢复镜像:

[xiaokang@hadoop docker_teach]$ sudo docker load -i hadoop-commit-pseudo.tar.gz

Docker环境下Hadoop完全分布式_分布式_02

三、集群规划

这里搭建一个 5 个节点的 Hadoop 集群,其中四台主机均部署 ​​DataNode​​​ 和 ​​NodeManager​​​ 服务,但其中 hadoop02 上部署 ​​SecondaryNameNode​​​服务和 ​​NTP服务器​​​,hadoop01 上部署 ​​NameNode​​​ 、 ​​ResourceManager​​​ 和​​JobHistoryServer​​ 服务。

Docker环境下Hadoop完全分布式_服务器_03

节点ip分配情况如下:

hadoop01=172.24.0.2
hadoop02=172.24.0.3
hadoop03=172.24.0.4
hadoop04=172.24.0.5
hadoop05=172.24.0.6

四、创建并启动容器

4.1 手动启动(一个一个的)

#下面会用到systemctl 管理服务需要加上参数 --privileged 来增加权并且不能使用默认的bash,换成 init
[xiaokang@hadoop ~]$ sudo docker run -d --name hadoop01 --hostname hadoop01 --net xiaokang-network --ip 172.24.0.2 -P -p 50070:50070 -p 8088:8088 -p 19888:19888 --privileged 56a73b3d978d /usr/sbin/init

[xiaokang@hadoop ~]$ sudo docker run -d --name hadoop02 --hostname hadoop02 --net xiaokang-network --ip 172.24.0.3 -P -p 50090:50090 --privileged 56a73b3d978d /usr/sbin/init

[xiaokang@hadoop ~]$ sudo docker run -d --name hadoop03 --hostname hadoop03 --net xiaokang-network --ip 172.24.0.4 -P --privileged 56a73b3d978d /usr/sbin/init

[xiaokang@hadoop ~]$ sudo docker run -d --name hadoop04 --hostname hadoop04 --net xiaokang-network --ip 172.24.0.5 -P --privileged 56a73b3d978d /usr/sbin/init

[xiaokang@hadoop ~]$ sudo docker run -d --name hadoop05 --hostname hadoop05 --net xiaokang-network --ip 172.24.0.6 -P --privileged 56a73b3d978d /usr/sbin/init

4.2 Shell脚本方式启动

shell脚本​​hadoop-cluster.sh​​:

#!/bin/bash
# description:Batch start Containers Script
# author:xiaokang
if [ $# -ne 1 ];then
echo "You need to start several containers explicitly."
echo "Some like './hadoop-cluster.sh 3' or 'sh hadoop-cluster.sh 3'"
exit 1
fi
#要启动的容器数量
NUM_CONTAINERS=$1
#自定义网络名称
NETWORK_NAME=xiaokang-network
#镜像ID
IMAGE_ID=56a73b3d978d
#前缀
PREFIX="0"
for (( i=1;i<=$NUM_CONTAINERS;i++ ))
do
if [ $i -eq 1 ];then
sudo docker run -d --name hadoop$PREFIX$i --hostname hadoop$PREFIX$i --net ${NETWORK_NAME} --ip 172.24.0.$[$i+1] -P -p 50070:50070 -p 8088:8088 -p 19888:19888 --privileged $IMAGE_ID /usr/sbin/init
elif [ $i -eq 2 ];then
sudo docker run -d --name hadoop$PREFIX$i --hostname hadoop$PREFIX$i --net ${NETWORK_NAME} --ip 172.24.0.$[$i+1] -P -p 50090:50090 --privileged $IMAGE_ID /usr/sbin/init
else
sudo docker run -d --name hadoop$PREFIX$i --hostname hadoop$PREFIX$i --net ${NETWORK_NAME} --ip 172.24.0.$[$i+1] -P --privileged $IMAGE_ID /usr/sbin/init
fi
done
echo "$NUM_CONTAINERS containers started!"
echo "==================================="
sudo docker ps | grep hadoop
echo "============IPv4==================="
sudo docker inspect $(sudo docker ps -q) | grep -i ipv4
echo "==================================="

这里我采用shell脚本的方式来启动5个容器(也就是5个Hadoop节点):

[xiaokang@hadoop ~]$ sh /home/xiaokang/docker_teach/hadoop-cluster.sh 5

Docker环境下Hadoop完全分布式_大数据_04

五、容器内进行集群配置

5.1 进入容器

复制五个终端并以交互式进入容器进行操作:

[xiaokang@hadoop ~]$ sudo docker exec -ti b21f882c365a /bin/bash
[root@hadoop01 ~]#

[xiaokang@hadoop ~]$ sudo docker exec -ti fd8d441aa6c9 /bin/bash
[root@hadoop02 ~]#

[xiaokang@hadoop ~]$ sudo docker exec -ti bb284e8f9aec /bin/bash
[root@hadoop03 ~]#

[xiaokang@hadoop ~]$ sudo docker exec -ti 096b8023df80 /bin/bash
[root@hadoop04 ~]#

[xiaokang@hadoop ~]$ sudo docker exec -ti 198e4e47d230 /bin/bash
[root@hadoop05 ~]#

5.2 配置映射

配置 ip 地址和主机名映射(所有节点都需要配置):

172.24.0.2 hadoop01
172.24.0.3 hadoop02
172.24.0.4 hadoop03
172.24.0.5 hadoop04
172.24.0.6 hadoop05

5.3 配置主从节点免密登录

5.3.1 生成密钥

每台主机上使用 ​​ssh-keygen​​ 命令生成公钥私钥对:

[xiaokang@hadoop01 ~]$ ssh-keygen -t rsa -N '' -C "xiaokang.188@qq.com"

5.3.2 复制公钥

将 ​​hadoop01​​​ 的公钥写到本机和远程机器的 ​​~/ .ssh/authorized_keys​​ 文件中(另外四台机器上需要做同样的动作):

[xiaokang@hadoop01 ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop01
[xiaokang@hadoop01 ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop02
[xiaokang@hadoop01 ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop03
[xiaokang@hadoop01 ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop04
[xiaokang@hadoop01 ~]$ ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop05

5.3.3 验证免密登录

[xiaokang@hadoop01 ~]$ ssh hadoop01
[xiaokang@hadoop01 ~]$ ssh hadoop02
[xiaokang@hadoop01 ~]$ ssh hadoop03
[xiaokang@hadoop01 ~]$ ssh hadoop04
[xiaokang@hadoop01 ~]$ ssh hadoop05

5.4 同步集群时间

5.4.1 配置时间服务器(hadoop02)

1. 检查ntp包是否安装
[xiaokang@hadoop02 ~]$ rpm -qa | grep ntp
[xiaokang@hadoop02 ~]$

#没有安装的话,执行以下命令进行安装(每个节点都要安装)
[xiaokang@hadoop02 ~]$ sudo yum -y install ntp
2. 设置时间配置文件
[xiaokang@hadoop02 ~]$ sudo vim /etc/ntp.conf
#修改一(设置本地网络上的主机不受限制)
#restrict 192.168.1.0 mask 255.255.255.0 nomodify notrap
restrict 172.24.0.0 mask 255.255.255.0 nomodify notrap
#修改二(添加默认的一个内部时钟数据,使用它为局域网用户提供服务)
server 127.127.1.0
fudge 127.127.1.0 stratum 10
#修改三(设置为不采用公共的服务器)
server 0.centos.pool.ntp.org iburst
server 1.centos.pool.ntp.org iburst
server 2.centos.pool.ntp.org iburst
server 3.centos.pool.ntp.org iburst 为
#server 0.centos.pool.ntp.org iburst
#server 1.centos.pool.ntp.org iburst
#server 2.centos.pool.ntp.org iburst
#server 3.centos.pool.ntp.org iburst
3. 设置BIOS与系统时间同步
[xiaokang@hadoop02 ~]$ sudo vim /etc/sysconfig/ntpd
#增加如下内容(让硬件时间与系统时间一起同步)
OPTIONS="-u ntp:ntp -p /var/run/ntpd.pid -g"
SYNC_HWCLOCK=yes
4. 启动ntp服务并测试
[xiaokang@hadoop02 ~]$ sudo systemctl start ntpd
[xiaokang@hadoop02 ~]$ systemctl status ntpd
#设置ntp服务开机自启
[xiaokang@hadoop02 ~]$ sudo systemctl enable ntpd.service


[xiaokang@hadoop02 ~]$ ntpstat
synchronised to local net (127.127.1.0) at stratum 11
time correct to within 3948 ms
polling server every 64 s
[xiaokang@hadoop02 ~]$ sudo ntpq -p
remote refid st t when poll reach delay offset jitter
==============================================================================
*LOCAL(0) .LOCL. 10 l 39 64 3 0.000 0.000 0.000

5.4.2 其它节点与时间服务器同步时间

先关闭非时间服务器节点的ntpd服务​​sudo systemctl stop ntpd​

1. 手动同步
#设置时区为Asia/Shanghai
[xiaokang@hadoop02 ~]$ sudo timedatectl set-timezone Asia/Shanghai
2. 定时同步

在其他机器配置10分钟与时间服务器同步一次

#非时间服务器都安装crond服务
[xiaokang@hadoop01 ~]$ sudo yum -y install vixie-cron crontabs
#非时间服务器节点都编写定时同步时间任务
[xiaokang@hadoop03 ~]$ sudo vim /etc/crontab
编写定时任务如下:
*/1 * * * * /usr/sbin/ntpdate hadoop02

#加载任务,使之生效
[xiaokang@hadoop03 ~]$ sudo crontab /etc/crontab

修改时间服务器时间:

sudo date -s "2020-11-24 11:24:00"

sudo ntpdate -u ntp.api.bz
#十分钟后查看机器是否与时间服务器同步

​ps:测试的时候可以将10分钟调整为1分钟,节省时间​

5.5 修改主节点配置文件

先创建所需目录:

[xiaokang@hadoop01 ~]$ mkdir /opt/software/hadoop-2.7.7/tmp
[xiaokang@hadoop01 ~]$ mkdir -p /opt/software/hadoop-2.7.7/dfs/namenode_data
[xiaokang@hadoop01 ~]$ mkdir -p /opt/software/hadoop-2.7.7/dfs/datanode_data
[xiaokang@hadoop01 ~]$ mkdir -p /opt/software/hadoop-2.7.7/checkpoint/dfs/cname

1. hadoop-env.sh

#25行 export JAVA_HOME
export JAVA_HOME=/opt/moudle/jdk1.8.0_191
#33行 export HADOOP_CONF_DIR
export HADOOP_CONF_DIR=/opt/software/hadoop-2.7.7/etc/hadoop

2. core-site.xml

<configuration>
<property>
<!--用来指定hdfs的老大,namenode的地址-->
<name>fs.defaultFS</name>
<value>hdfs://hadoop01:9000</value>
</property>
<property>
<!--用来指定hadoop运行时产生文件的存放目录-->
<name>hadoop.tmp.dir</name>
<value>/opt/software/hadoop-2.7.7/tmp</value>
</property>
<property>
<!--设置缓存大小,默认4kb-->
<name>io.file.buffer.size</name>
<value>4096</value>
</property>
</configuration>

3. hdfs-site.xml

指定副本系数和hdfs操作权限:

<configuration>
<property>
<!--数据块默认大小128M-->
<name>dfs.block.size</name>
<value>134217728</value>
</property>
<property>
<!--副本数量,不配置的话默认为3-->
<name>dfs.replication</name>
<value>3</value>
</property>
<property>
<!--定点检查-->
<name>fs.checkpoint.dir</name>
<value>/opt/software/hadoop-2.7.7/checkpoint/dfs/cname</value>
</property>
<property>
<!--namenode节点数据(元数据)的存放位置-->
<name>dfs.name.dir</name>
<value>/opt/software/hadoop-2.7.7/dfs/namenode_data</value>
</property>
<property>
<!--datanode节点数据(元数据)的存放位置-->
<name>dfs.data.dir</name>
<value>/opt/software/hadoop-2.7.7/dfs/datanode_data</value>
</property>
<property>
<!--指定secondarynamenode的web地址-->
<name>dfs.namenode.secondary.http-address</name>
<value>hadoop02:50090</value>
</property>
<property>
<!--hdfs文件操作权限,false为不验证-->
<name>dfs.permissions</name>
<value>false</value>
</property>
</configuration>

4. mapred-site.xml

说明:在${HADOOP_HOME}/etc/hadoop的目录下,只有一个mapred-site.xml.template文件,复制一个进行更改。

[xiaokang@hadoop hadoop]$ cp mapred-site.xml.template mapred-site.xml
<configuration>
<property>
<!--指定mapreduce运行在yarn上-->
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
<property>
<!--配置任务历史服务器地址-->
<name>mapreduce.jobhistory.address</name>
<value>hadoop01:10020</value>
</property>
<property>
<!--配置任务历史服务器web-UI地址-->
<name>mapreduce.jobhistory.webapp.address</name>
<value>hadoop01:19888</value>
</property>
</configuration>

5. yarn-site.xml

<configuration>
<property>
<!--指定yarn的老大resourcemanager的地址-->
<name>yarn.resourcemanager.hostname</name>
<value>hadoop01</value>
</property>
<property>
<name>yarn.resourcemanager.address</name>
<value>hadoop01:8032</value>
</property>
<property>
<name>yarn.resourcemanager.webapp.address</name>
<value>hadoop01:8088</value>
</property>
<property>
<name>yarn.resourcemanager.scheduler.address</name>
<value>hadoop01:8030</value>
</property>
<property>
<name>yarn.resourcemanager.resource-tracker.address</name>
<value>hadoop01:8031</value>
</property>
<property>
<name>yarn.resourcemanager.admin.address</name>
<value>hadoop01:8033</value>
</property>
<property>
<!--NodeManager获取数据的方式-->
<name>yarn.nodemanager.aux-services</name>
<value>mapreduce_shuffle</value>
</property>
<property>
<!--开启日志聚集功能-->
<name>yarn.log-aggregation-enable</name>
<value>true</value>
</property>
<property>
<!--配置日志保留7天-->
<name>yarn.log-aggregation.retain-seconds</name>
<value>604800</value>
</property>
</configuration>

6. master

在当前配置文件目录内是不存在master文件的,我们使用vim写入内容到master内保存即可

[xiaokang@hadoop01 hadoop]$ vim master
hadoop01

7. slaves

配置所有从属节点的主机名或 IP 地址,每行一个。所有从属节点上的 ​​DataNode​​​ 服务和 ​​NodeManager​​ 服务都会被启动。

hadoop02
hadoop03
hadoop04
hadoop05

5.6 分发程序

将 Hadoop 安装包分发到其他四台服务器,分发后建议在这四台服务器上也配置一下 Hadoop 的环境变量。

[xiaokang@hadoop01 hadoop]$ sudo scp -r /opt/software/hadoop-2.7.7/ xiaokang@hadoop02:/opt/software/
[xiaokang@hadoop01 hadoop]$ sudo scp -r /opt/software/hadoop-2.7.7/ xiaokang@hadoop03:/opt/software/
[xiaokang@hadoop01 hadoop]$ sudo scp -r /opt/software/hadoop-2.7.7/ xiaokang@hadoop04:/opt/software/
[xiaokang@hadoop01 hadoop]$ sudo scp -r /opt/software/hadoop-2.7.7/ xiaokang@hadoop05:/opt/software/

shell脚本​​scp-config.sh​​:

#!/bin/bash
#description:节点间复制文件
#author:xiaokang

#首先判断参数是否存在
args=$#
if [ args -eq 0 ];then
echo "no args"
exit 1
fi
#获取文件名称
p1=$1
fname=$(basename $p1)
echo faname=$fname
#获取上级目录到绝对路径
pdir=$(cd $(dirname $p1);pwd -P)
echo pdir=$pdir
#获取当前用户名称
user=$(whoami)
#循环分发
for(( host=2;host<6;host++ ));do
echo "------hadoop0$host------"
scp -r $pdir/$fname $user@hadoop0$host:$pdir
done
echo "------All done xiaokangxxs------"

5.7 初始化

[xiaokang@hadoop01 ~]$ hdfs namenode -format

六、启动集群

在 ​​hadoop01​​​ 上启动 Hadoop集群。此时 ​​hadoop02​​​ 、​​hadoop03​​​ 、​​hadoop04​​​ 、​​hadoop05​​ 上的相关服务也会被启动:

# 启动dfs服务
[xiaokang@hadoop01 ~]$ start-dfs.sh
# 启动yarn服务
[xiaokang@hadoop01 ~]$ start-yarn.sh
# 启动任务历史服务器
[xiaokang@hadoop01 ~]$ mr-jobhistory-daemon.sh start historyserver

在每台服务器上使用 ​​jps​​​ 命令查看服务进程,或直接进入 Web-UI 界面进行查看,端口为 ​​50070​​​。可以看到此时有四个可用的 ​​Datanode​​:

[xiaokang@hadoop01 ~]$ jps
1972 JobHistoryServer
1688 ResourceManager
1417 NameNode
2043 Jps

[xiaokang@hadoop02 ~]$ jps
1280 NodeManager
1110 DataNode
1179 SecondaryNameNode
1388 Jps

[xiaokang@hadoop03 ~]$ jps
1138 NodeManager
1032 DataNode
1243 Jps

[xiaokang@hadoop04 ~]$ jps
1249 Jps
1144 NodeManager
1038 DataNode

[xiaokang@hadoop05 ~]$ jps
963 DataNode
1174 Jps
1069 NodeManager

Docker环境下Hadoop完全分布式_服务器_05

点击 ​​Live Nodes​​​ 进入,可以看到每个 ​​DataNode​​ 的详细情况:

Docker环境下Hadoop完全分布式_hadoop_06

​SecondaryNameNode​​​ 端口为 ​​50090​​ 

​Yarn​​​ 端口号为 ​​8088​​ 

七、集群测试

这里提交 Hadoop 内置的计算 Pi 的示例程序为例,在任何一个节点上执行都可以,命令如下:

[xiaokang@hadoop03 ~]$ hadoop jar /opt/software/hadoop-2.7.7/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.7.jar pi 11 24

任务完成后可以在任务历史服务器(端口​​19888​​)中找到相应的job:

Docker环境下Hadoop完全分布式_hadoop_07