实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)


—— 步骤 ——

  • 0. 背景
  • 1. 创建出第一个容器
  • 2. 为该容器配置 java 和 hadoop 环境
  • 3. 配置允许外界通过 ssh 连接容器
  • 4. 由该容器克隆出多个容器
  • 5. 为各个容器配置 ssh 免密登录
  • 6. 开始编写集群配置
  • 7. 启动集群

0. 背景 看到网上的教程,都是使用虚拟机克隆出多台虚拟机模拟集群
但在真正的服务器上,发现这种方法行不通了
这时候就想起 Docker 了,仔细想象 Docker 学完到现在还没真正实战过,这次正好是一个好机会
实现思路也很简单,在 Docker 中创建多个 Centos 容器
每个容器当作一台服务器用,就可以模拟出集群环境了
好,动手!
还不熟悉 Docker 的,可以参考这里:【Java 之轨迹】Docker 入门使用(穿插踩坑经历)
本博客 Hadoop 版本为 3.1.3,参考尚硅谷视频
1. 创建出第一个容器
1) 首先拉取 centos docker pull centos2) 创建一个 centos docker run --privileged=true --name=hadoop001 -dit centos /sbin/init -dit 表示交互式且后台运行,少了 -it 容器会自动停止 --privileged=true 和 /sbin/init 表示特权启动,后面可能需要实用到 service 命令,需要由这个权限才可以 没有上面这个,再使用时会报 PID 1 的错误哦

2. 为该容器配置 java 和 hadoop 环境 将 jdk 和 hadoop 从主机复制到该容器中
docker cp <容器id>:<容器路径> docker cp<容器id>:<容器路径>

在 /etc/profile.d/ 下创建文件 mydev.sh
vim mydex.sh 文件内容如下
# Java export JAVA_HOME= export PATH=$PATH:$JAVA_HOME/bin# Hadoop export HADOOP_HOME= export PATH=$PATH:$HADOOP_HOME/bin export PATH=$PATH:$HADOOP_HOME/sbin# Constant export HDFS_NAMENODE_USER=root export HDFS_DATANODE_USER=root export HDFS_SECONDARYNAMENODE_USER=root export YARN_RESOURCEMANAGER_USER=root export YARN_NODEMANAGER_USER=root

第一第二个是两个环境,最后一个是一些常量,在启动集群的时候,还要用到这些常量,否则可能启动失败
最后执行 source /etc/profile 使配置文件生效
3. 配置允许外界通过 ssh 连接容器 我们需要让各个容器产生联系,才能构成集群,但默认情况下,容器并不能被其他容器直接通过 ssh 访问,所以这里需要配置
1) 首先需要设置密码(输入以下命令,回车设置密码即可) passwd root 大概率会提示没有该命令,就得下载它,然后再设置就好了 yum install passwd2) 然后下载 ssh,以下三步(安装了服务端和客户端) yum install openssh yum install openssh-server yum install openssh-clients3) 然后检查配置文件,查看以下两个配置是否一样(默认应该都是这样的) vim /etc/ssh/sshd_config PermitRootLogin yes PasswordAuthentication yes 这两个配置允许外网通过 ssh 连接该服务器(容器)4) 如果发现不是这样,就修改它,同时需要重启 ssh 是指生效 service sshd restart 同样该命令可能不存在,就下载它 yum install initscripts

通过上面一顿操作,外网已经可以通过 ssh 访问该容器了,我们可以试试:
1) 首先在容器内,使用 ifconfig 查看 IP 地址 ifconfig 没有这个命令的话,就下载他[doge] yum install net-tools2) 在服务器本机中,通过 ssh 访问该 IP 地址尝试连接 ssh 然后要求输入密码,就是上面我们已经设置了的密码

ohhh 然后我们会发现,成功进入容器内部了,这次时通过 ssh 而不是通过 docker 了
实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

4. 由该容器克隆出多个容器 首先要克隆出多个容器,就需要将该容器打包成镜像,再由该镜像创建出多个容器,步骤如下:
1) 创建镜像 docker commit -a='IceClean' -m='Hadoop cluster example through docker by IceClean' 5a8 hadoop-docker2) 由该进项克隆多个容器模拟集群(这里以三台服务器的集群为例) docker run --privileged=true --name=hadoop002 -dit hadoop-docker /sbin/init docker run --privileged=true --name=hadoop003 -dit hadoop-docker /sbin/init

在这些容器生成好后,为它们配置一个 IP 地址映射
往后就不用去记住每一个容器的 IP 地址了
但同时由于 docker 网桥模式的特性,当容器重启时,会按顺序为该容器分配一个 IP,使得该 IP 地址不是固定的会变化,这对我们已经做的映射非常不友好,所以接下来的第一步,是为每个容器固定一个 IP 地址(这里需要借助 pipework)
1) 安装 pipewoek(下载并复制可执行文件到 bin 目录) git clone https://github.com/jpetazzo/pipework cp ~/pipework/pipework /usr/local/bin/2) 安装 bridge-utils yum -y install bridge-utils3) 创建网络(这里 IP 地址自定义) brctl addbr br0 ip link set dev br0 up ip addr add 172.16.10.1 dev br04) 为各个容器设置固定的 IP pipework br0 <容器名> IP/掩码,如: pipework br0 hadoop001 172.16.10.10/24 pipework br0 hadoop002 172.16.10.11/24 pipework br0 hadoop003 172.16.10.12/245) 测试这几个 IP 是否可用 ping 172.16.10.106) 中途如果不小心操作错了(比如说我--),想删除网络或IP,可执行如下 删除网络: ip link set dev br0 down brctl delbr 删除 IP: ip link set dev <名称> down 其中<名称>来自于 ifconfig 查找到的 veth1plxxx

这样就成功地为每一个容器固定好 IP 地址了,接下来就可以在容器内配置映射了
1) 在每一台容器中,修改 hosts 文件 vim /etc/hosts 比如说我的,就在文件中增加: 172.16.10.10 hadoop001 172.16.10.11 hadoop002 172.16.10.12 hadoop0033) 配置完毕后,我们就可以直接通过名字轻松连接各个容器了,如: ssh hadoop003

5. 为各个容器配置 ssh 免密登录 容器之间虽然能正常互相连接了,但如果每次都需要输入密码,那是及其不方便的
再而,到后面启动集群的时候,如果没有免密登录,既有可能会失败噢
所以我们可以为各个集群中的容器配置免密登录,实现各个容器之间的顺畅连接
首先我们来了解一下免密登录的原理(以 hadoop001 和 hadoop002 为例)
在 hadoop001 中,可以使用 ssh-key-gen 生成密钥
—— 分为公钥和私钥,私钥保密,公钥可以给别人
然后如果将 hadoop001 的公钥拷贝给 hadoop002
—— 通过命令拷贝,该公钥会保存在 hadoop002 中的 Authorized_keys 中
往后 hadoop001 想要连接 hadoop002,就可以直接通过公钥连接,无需密码
所以我们可以知道,免密登录的实现,就是将目标服务器的公钥拷贝到对方的服务器上,这样对方即可免密登录该目标服务器,而如果两台服务器要互相免密登录,当然就要互相拷贝到对方的公钥啦~ 开始行动!
1) 首先在 hadoop001 中,生成公钥和私钥(一路回车到底就行了,不需要输入内容) ssh-keygen -t rsa 其中 id_rsa 为私钥,id_rsa.pub 为公钥2) 将 hadoop001 的公钥拷贝到 hadoop002 ssh-copy-id hadoop002

出现这个提示说明添加成功了,以后我们可以直接通过 ssh hadoop002 连接 hadoop002
实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

注意啦:公钥也需要拷贝到本服务器(如 hadoop001 将自己的公钥拷贝到 hadoop001)不然自己五大免密登录自己哦
然后对于其他的容器也是这样做,把每个容器的公钥都拷贝到自己以及另外两台服务器上,就实现了三台服务器互相的免密登录,完毕~
6. 开始编写集群配置 前面做足了准备工作,把每一个容器都配置好了
现在要正式开始集群的搭建啦,首先是集群的配置:
安排一下集群的部署:
hadoop001 hadoop002 hadoop003
HDFS NameNode
DataNode
DataNode SecondaryNameNode
DataNode
YARN NodeManager ResourceManager
NodeManager
NodeManager
hadoop001 兼任主节点,配置 NameNode
hadoop002 兼任资源管理,配置 ResourceManager
hadoop003 兼任备份结点,配置 SecondaryNameNode
接着按照这个规划,修改 hadoop 配置文件
先说明一下各个配置文件及其位置(~ 表示 hadoop 所在目录)
系统配置文件:~/share/doc/hadoop
用户自定义配置文件:~/etc/hadoop
需要我们自定义配置的文件在 etc 目录下,总共有四个,分别是:
core-site.xml,``
① 配置 hadoop001
首先到主节点 hadoop001 里边,配置 core-site.xml
下面是我自己的配置,需要配置两个东西
① 将 hadoop001 设置为主节点,端口推荐为 8020
② 将数据的默认存储位置改为 hadoop 目录下的 data 文件夹(如果不存在的话,会自动创建)
fs.defaultFS hdfs://hadoop001:8020 hadoop.tmp.dir /home/hadoop/hadoop-3.1.3/data

然后配置 hdfs-site.xml
dfs.namenode.http-address hadoop001:9870 dfs.namenode.secondary.http-address hadoop003:9868 dfs.webhdfs.enabled true

然后是 yarn-site.xml
yarn.nodemanager.aux-services mapreduce_shuffle yarn.resourcemanager.hostname hadoop002 yarn.nodemanager.env-whitelist JAVA_HOME,HADOOP_COMMON_HOME,HADOOP_HDFS_HOME,HADOOP_CONF_DIR,CLASSPATH_PREPEND_DISTCACHE,HADOOP_YARN_HOME,HADOOP_MAPRED_HOME

最后配置 mapred-site.xml
mapreduce.framework.name yarn

② 将编写好的四个配置文件,同步到其他两台服务器上(hadoop002,hadoop003)
只需执行下面这一句,就能将四个配置文件远程复制到另外一个容器中
由于之前设置了免密登录,所以它可以直接远程复制,而不需要输入密码,可以很方便地在哥哥容器之间拷贝文件(hadoop003 也同理)
scp core-site.xml hdfs-site.xml yarn-site.xml mapred-site.xml root@hadoop002:/home/hadoop/hadoop-3.1.3/etc/hadoop

③ 配置 workers
同样是在 hadoop001 中,修改文件 /etc/hadoop/workers
将里边的内容去掉(把 localhost 删掉)然后换成我们的三个容器:
注意:行末不能有空格,以及不能有空行的出现
hadoop001 hadoop002 hadoop003

然后将该文件同步到其他两个容器
scp workers root@hadoop002:/home/hadoop/hadoop-3.1.3/etc/hadoop/ scp workers root@hadoop003:/home/hadoop/hadoop-3.1.3/etc/hadoop/

7. 启动集群 第一次启动时,需要进行初始化(往后就不用了,再初始化会清空数据哦)
hdfs namenode -format

初始化完毕后,在配置文件指定的目录下,就会生成 datalogs 两个文件
———— 接下来正式启动
① 首先启动 DFS:
在 Hadoop001 中操作(配置了 NameNode 的)
进入 sbin,执行 ./start-dfs.sh 命令
然后执行 jps 看是否启动成功,和下图一样说明成功了
实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

如果上面的配置都没有出错的话,这里应该是很顺利就启动的了
可能出现的错误有:
1、没有配置免密登录,权限不足导致启动失败
2、只把公钥给了其他容器,没有给自己,也会导致权限不足的失败
所以说,免密登录在这里,还是非常非常重要的!!!
② 然后启动 YARN:
在 Hadoop002 中操作(配置了 ResourceManager的)
依旧在 sbin 中执行 ./start-yarn.sh
这个步骤,如果服务器性能不太行的话,会卡死(像我这样—_—卡了两个小时)
实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

从晚上九点卡到十一点,还好没放弃 2333
不过在这里也要提醒一下,卡的时候还是经量别强制重启服务器,就像我下午三点多那次,强制重启导致集群出了点问题跑不起来,最后是清空了数据再重启才解决的,慎重噢!
当时出现的错误,是这个 ssh: connect to host master port 22: No route to host找了好久的解决方案,都是说什么防火墙、没固定 IP,没网等等的情况 但我这些都没问题,还是不行,最后就只能重启了(后来者如果出了这个问题,有解决方案的,也可以分享一下哦)

如果启动完毕的话,就执行 jps 检查下各个容器是否如我们规划的那样配置完毕
像我下面这种情况就是 OK 的:
实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

③ 测试集群
最后的最后,就可以通过外网访问了
如果直接使用容器的 IP 进行访问,大概是不行的(不知道是不是我装了 nginx 的原因)
但使用 nginx 进行代理却很方便解决这个问题,下面是实现的步骤
先将安全组和防火墙的 9870,9868 以及 8088 端口打
分别对应 NameNode SecondaryNameNode ResourceManager
然后让 nginx 代理这三个端口,转发到对应的 hadoop 容器完成访问,如下:
server {listen9870; server_namewww.xxx.xxx; location / {proxy_pass http://hadoop001:9870; } }server {listen9868; server_namewww.xxx.xxx; location / {proxy_pass http://hadoop003:9868; } }server {listen8088; server_namewww.xxx.xxx; location / {proxy_pass http://hadoop002:8088; } }# 这里也是后面发现,然后回来填坑的,将对容器的访问交给 nginx代理 server {listen9864; server_namewww.xxx.xxx; location / {proxy_pass http://hadoop001:9864; } }

最后在外网,直接通过 域名+端口号 就可以访问到 hadoop 集群啦!!看到一下的页面算成功(三张图对应端口顺序:9870,9868,8088)
后面上来的填坑,需要修改本机的 hosts 文件(想要详细了解的,看下边实操记录哦)
位置:C:\Windows\System32\drivers\etc\hosts 在这里边加上(域名可以是服务器和虚拟机的) 域名 hadoop001 域名 hadoop002 域名 hadoop003

实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

接着使用一些简单的功能测试一下:上传文件到集群(在 hadoop001 中执行)
每一步都可以在 9870 的 Browse Directory 窗口观察:
实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)
文章图片

1) 创建文件夹(注意这里的根路径 '/' 是指集群的根路径,往后都是按照这个根路径来) hadoop fs -mkdir /firstDir2) 上传文件(随便上传一个,一下表示将 README.txt 上传到集群根目录下的 firstDir 文件夹) hadoop fs -put README.txt /firstDir3) 点击文件,可以查看和下载文件,至此测试完毕(还存在问题的话,可以看下面黑框)4) 执行 wordcount 函数,并将结果保存在 output 文件夹中

下面这部分是实操记录,已经对上文有做修改了,可以跳过这个黑框往下看
—————— 好叭,苦逼的我发现,文件内容预览不了,到网上一查发现配少了个东西 明明是一步步跟着视频做的,不会又要等两个小时把 v…v 不过还好,只需要重启 NameNode,步骤如下(当然我已经在前面有补充了,这里应该不用管)在 hdfs-site.xml 添加如下配置,然后分发到各个容器,再重启就行了dfs.webhdfs.enabled true —————— Why?怎么还是访问不了?这时的我终于打开了控制台,发现了这个: http://hadoop001:9864/webhdfs/v1/firstDir/test.txt?op=OPEN&namenoderpcaddress=hadoop001:8020&offset=0噢,秒懂了 我们之前是使用 nginx 代理的,有提到不能直接使用容器名访问 但这个请求是自动发起的,怎么让它依旧访问到我们自己的服务器,让 nginx 代理呢? 这时候就需要修改本机的 hosts 文件了,改变域名和 IP 地址的映射关系位置:C:\Windows\System32\drivers\etc\hosts 在这里边加上: 域名 hadoop001 域名 hadoop002 域名 hadoop003其中域名是服务器的 IP (当然也可以是虚拟机的) 这一段表示,将三个容器的名称都变成我们的域名,这样就能成功地走我们服务器的代理啦 当然了,有了这个,以后我们也可以直接通过容器名,访问到上面列出来的三个页面了 (突然发现在写这篇博客的过程中,收获了很多网络的知识呀 2333)最后的最后,当然是配置 nginx 啦(这里我也有补充在上面了~) server {listen9864; server_namewww.xxx.xxx; location / {proxy_pass http://hadoop001:9864; } }

至此,测试完毕!
【实用功能|【Docker x Hadoop】使用 Docker 搭建 Hadoop 集群(从零开始保姆级)】每一把刀,都插在恰到合适的位置(IceClean)

    推荐阅读