实用功能|【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 了
文章图片
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
文章图片
注意啦:公钥也需要拷贝到本服务器(如 hadoop001 将自己的公钥拷贝到 hadoop001)不然自己五大免密登录自己哦
然后对于其他的容器也是这样做,把每个容器的公钥都拷贝到自己以及另外两台服务器上,就实现了三台服务器互相的免密登录,完毕~
6. 开始编写集群配置 前面做足了准备工作,把每一个容器都配置好了
现在要正式开始集群的搭建啦,首先是集群的配置:
安排一下集群的部署:
hadoop001 | hadoop002 | hadoop003 | |
---|---|---|---|
HDFS | NameNode DataNode |
DataNode | SecondaryNameNode DataNode |
YARN | NodeManager | ResourceManager NodeManager |
NodeManager |
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
初始化完毕后,在配置文件指定的目录下,就会生成
data
和 logs
两个文件———— 接下来正式启动
① 首先启动 DFS:
在 Hadoop001 中操作(配置了 NameNode 的)
进入
sbin
,执行 ./start-dfs.sh
命令然后执行
jps
看是否启动成功,和下图一样说明成功了文章图片
如果上面的配置都没有出错的话,这里应该是很顺利就启动的了
可能出现的错误有:
1、没有配置免密登录,权限不足导致启动失败
2、只把公钥给了其他容器,没有给自己,也会导致权限不足的失败
所以说,免密登录在这里,还是非常非常重要的!!!
② 然后启动 YARN:
在 Hadoop002 中操作(配置了 ResourceManager的)
依旧在
sbin
中执行 ./start-yarn.sh
这个步骤,如果服务器性能不太行的话,会卡死(像我这样—_—卡了两个小时)
文章图片
从晚上九点卡到十一点,还好没放弃 2333
不过在这里也要提醒一下,卡的时候还是经量别强制重启服务器,就像我下午三点多那次,强制重启导致集群出了点问题跑不起来,最后是清空了数据再重启才解决的,慎重噢!
当时出现的错误,是这个
ssh: connect to host master port 22: No route to host找了好久的解决方案,都是说什么防火墙、没固定 IP,没网等等的情况
但我这些都没问题,还是不行,最后就只能重启了(后来者如果出了这个问题,有解决方案的,也可以分享一下哦)
如果启动完毕的话,就执行
jps
检查下各个容器是否如我们规划的那样配置完毕像我下面这种情况就是 OK 的:
文章图片
③ 测试集群
最后的最后,就可以通过外网访问了
如果直接使用容器的 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
文章图片
文章图片
文章图片
接着使用一些简单的功能测试一下:上传文件到集群(在 hadoop001 中执行)
每一步都可以在 9870 的 Browse Directory 窗口观察:
文章图片
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)
推荐阅读
- 宽容谁
- 我要做大厨
- 增长黑客的海盗法则
- 画画吗()
- 2019-02-13——今天谈梦想()
- 远去的风筝
- 三十年后的广场舞大爷
- 叙述作文
- 20190302|20190302 复盘翻盘
- 学无止境,人生还很长