docker 安装完全分布式Hadoop集群

一、搭建原因

鉴于本人机器性能较低,在机器上运行多个Linux虚拟机比较吃力,如果再在其上运行分布式计算环境,想必更加吃力,我想这也是很多同学的普遍问题,通过百度,我了解到了docker技术,网上有很多docker搭建Hadoop的教程,总是有些简略,对于想我这样的小白,还是存在很多困惑,我想通过这篇文章,与大家一起分享我的经历,尽量把我知道的全部分享。

二、预备知识

  1. 需要了解简单的Linux的命令操作
  2. 需要明白docker的基本概念,至少需要了解Dockerfile,镜像和容器的概念

三、准备工具与Hadoop集群规划

1、docker软件安装:

参考:Ubuntu18安装docker

2、更新docker的镜像库源:

参考:更改阿里镜像源

3、准备JDK和Hadoop软件

JDK安装路径: Java SE 8下载路径
Hadoop安装路径: Hadoop下载路径

4、Hadoop集群规划

打算建立5个容器,一个做namenode,一个做SecondaryNameNode,其余的做DataNode。具体安排如下:

hostnameIP地址功能
Master172.2.0.2NameNode,ResourceManager
SecondMaster172.2.0.3SecondaryNameNode,DataNode,NodeManager
slave1172.2.0.4DataNode,NodeManager
slave2172.2.0.5DataNode,NodeManager
slave3172.2.0.6DataNode,NodeManager

四、对Docker的基本配置

主要对docker进行获取镜像,帮助大家熟悉一下docker的基本命令。

1、简单介绍一下docker

Docker 是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的 Linux或Windows 机器上,也可以实现虚拟化。容器是完全使用沙箱机制,相互之间不会有任何接口。
我们从镜像仓库中拉取镜像,使用docker run命令创建一个容器。
当我们对容器进行修改完善后,可以使用docker commit 进行封装容器,将其作为一个新的docker镜像。
同时我们编写dockerfile脚本,使用docker build指令也是可以创建一个属于我们自己的docker镜像。

2、 从镜像仓库拉取centos镜像

我们这里使用最新版的centos(这里的最新版是centos8),使用命令为:

docker pull centos

如果我们想找一个docker官方提供的,或好评率超过30的centos镜像,可以使用以下命令:

docker search -f stars=30 centos

注1:这里的30 只是一个例子,具体docker指令,可以看官方文档。
注2: 执行这一部分是一定要注意,镜像仓库最好是国内的,不然下载很慢。

3、新建一个目录,作为本次安装的根目录(非必要项),将jdk和hadoop放入resources目录

因为dockerfile被执行时,会将其所在目录的其他文件发送到dockerDaemon中,如果所在目录很大,就会很慢。可以使用.dockerignore来忽略文件,我想还是新建一个目录方便些。
我们新建一个docker_home的目录,然后再新建 resources文件夹,存放需要在容器中安装的软件。

resources % ls
hadoop	input	java

五、在scripts中编辑dockerfile文件

本步骤分别编写dockerfile文件,本次分为 ssh_dockerfile,Hadoop_dockerfile两部分去编写。也可以只编写一个dockerfile文件,为方便讲述和帮助不太了解dockerfile语法的同学做一定的讲解,打算分步骤完成dockerfile编写。

1、编写SSH_Dockerfile文件

目的: 为新的centos镜像添加 Openssh,vim,ifconfig功能,设置root的密码,以便SSH免密登陆。
思想: 首先安装必要的软件,同时将ssh-keygen生成的公钥复制一份为authroized_keys,以便作为镜像模板使用,
代码如下:

# SSH_Dockerfile的作用是为干净的contos镜像添加 vim,ifconfig,ssh基本的功能,

#From centos的作用在于告诉docker对那个镜像进行配置
From centos

#WORKDIR 为进入容器时的路径。我们在这里设置时root的家目录
WORKDIR /root
#安装vim编辑工具,RUN是dockerfile的一个关键字,运行linux的指令
RUN yum install -y vim

#安装ifconfig工具,这里是centos8,ifconfig存在于net-tools-2.0-0.51.20160912git.el8.x86_64中,那么我们就安装这个组件
RUN yum install -y net-tools-2.0-0.51.20160912git.el8.x86_64

#以下两个安装的是ssh
RUN yum install -y openssh-server-8.0p1-4.el8_1.x86_64
RUN yum install -y openssh-clients-8.0p1-4.el8_1.x86_64

#这里手动创建/root/.ssh目录,这里存放id_rsa , id_rsa.pub , authorized_keys, 以及known_hosts文件,这一步 是为了下一步的生成公密钥对提供存放地点
RUN mkdir .ssh

#echo “root” | chpasswd的作用在于 非交互式创建容器的密码,这是为了方便在dockerfile中就能完成root密码的设置,因为SSH登录时需要使用有密码的root用户(一般来说,很多功能都需要带有密码的root)
RUN ssh-keygen -t rsa -f /root/.ssh/id_rsa -N "" && echo "root:root" | chpasswd

#anthorized_keys 是两台机器SSH免密登录,登录方需要存放被登录方公钥的地方。为了让镜像拥有更多的功能,我们这里直接把本机的公钥复制一份给authorized_keys,以便启动多个容器时,直接免密登录。(这里不明白的小伙伴可以参看一下SSH免密登录的知识)
RUN cp .ssh/id_rsa.pub .ssh/authorized_keys

# 使镜像直接开启22端口。这个是SSH连接的端口
EXPOSE 22 





以上完成了对SSH功能的配置,当我们以这个dockerfile文件 build出镜像后,就直接可以拥有SSH功能。接下来对上半部分操作进行验证:

1.1 编写启动的shell脚本

wuzishi@wuzishideMacBook-Pro mydocker % cat start.sh
docker run -tid -h ssh1 --net=br --ip=172.2.0.50 --add-host=ssh2:172.2.0.51 --privileged=true  --name=ssh1 ssh/centos:1.0 /usr/sbin/init
docker run -tid -h ssh2 --net=br --ip=172.2.0.51 --add-host=ssh1:172.2.0.50 --privileged=true  --name=ssh2 ssh/centos:1.0  /usr/sbin/init

这里有三点注意点:
   a、--net 是指定网络设施,br是自己建立的网络, 可以使用 docker network create来创建。
   b、--add-host 是追加容器中的/hosts, 以便容器间相互识别(用主机名代替 用户@IP地址)
   c、--privileged=true 这里是赋予docker容器特殊权限,/usr/sbin/init, 开启init进程。 这里如果不开启init进程,则无法使用SSH服务,如果不为容器设置特殊的权限,则无法启动init进程。(因此,此处不能省略任何一个参数)





1.2 执行脚本,创建容器
这一步 修改刚才建立的shell脚本设置可执行权限,然后执行(这一步,对于熟悉Linux的你很简单,不要嘲笑我这样的小白)
1.3.执行SSH命令

mydocker % ./start.sh
eab3e340a5cec8ce2d13e09c9397170a3cd1eb11c537dd6ed2f13aa4f0fca202
9ed1cc899f627d210c2c90728321b973390d5d528a4a5e35b8ddb6d2570af0e9
mydocker % docker exec -it ssh1 /bin/bash
[root@ssh1 ~]# ssh ssh2
The authenticity of host 'ssh2 (172.2.0.51)' can't be established.
ECDSA key fingerprint is SHA256:ewnTbDPX3wlYd8MbbbfWfbhcacU4dPD1cVKbHXnC+zw.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added 'ssh2,172.2.0.51' (ECDSA) to the list of known hosts.
[root@ssh2 ~]# 
进行下一步之前,需要修改一下 已经下载的hadoop的配置文件,新建一些必要的文件夹, 此步操作在第六步
2、完成HADOOP_Dockerfile的编写

目的: 搭建Java和hadoop的开发环境,设置环境变量。
思想: 使用Dockerfile语法,完成对宿主机中的文件拷贝和容器中环境变量的配置,代码如下:

#HADOOP_Dockerfile文件的内容
From ssh/centos:1.0

#以下三步是用RUN 指令 将内容内容追加到容器中的/etc/profile中,因为当SSH免密登录后,ENV设置环境变量失效,容器会执行新的容器的 source /etc/profile。所以我们可以在镜像设置时就把内容追加上,当我们开启容器时 使用ENV提供的环境变量,当SSH免密登录后,使用/etc/profile提供的环境变量。 这里$是shell中的关键字符,需要转义。
RUN echo "export JAVA_HOME=/usr/local/java" >> /etc/profile
RUN echo "export HADOOP_HOME=/usr/local/hadoop" >>  /etc/profile
RUN echo "export CLASSPATH=.:\$JAVA_HOME/lib/dt.jar:\$JAVA_HOME/lib/tool.jar:\$JAVA_HOME/jre/lib/rt.jar" >>  /etc/profile
RUN echo "export PATH=\$JAVA_HOME/bin:\$HADOOP_HOME/bin:\$HADOOP_HOME/sbin:\$PATH" >> /etc/profile

#以下两步 是将文件拷贝到容器中, 注意 resources是docker_home 的子目录,如果资源所在的目录不是docker build时需要的环境的子目录,就会拷贝失败。 
#这里第一注意 jdk 和hadoop 我都已经解压, 因为COPY命令只拷贝不解压,ADD可以做到拷贝且解压(你可以试试),同时hadoop文件夹我也做了修改,切忌直接拷贝下载下来的xxx.tar.gz文件。
COPY resources/java /usr/local/java
COPY resources/hadoop  /usr/local/hadoop

# ENV 设置容器启动时的环境变量,
ENV  JAVA_HOME   /usr/local/java
ENV  HADOOP_HOME /usr/local/hadoop
ENV  CLASSPATH   .:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tool.jar:$JAVA_HOME/jre/lib/rt.jar
ENV  PATH  $JAVA_HOME/bin:$HADOOP_HOME/bin:$HADOOP_HOME/sbin:$PATH

#开放端口。因为Hadoop的端口比较多,为保障可以正常运行hadoop, 我这里把常见的端口都打开了, 亲自实验过,打开这些端口,就可以正常运行Hadoop了。
EXPOSE 22 50010 50075 50475 50020 50070 50470 8020 8585 8480 8019 8032 8030 8031 8033 8088 8040 8042 8041 10020 19888 60000 60010 60020 60030 2181 3888 9083 10000 2181 2888 3888








使用docker build命令 再次创建新的镜像,我这里命名的是 hadoop/centos:2.0,操作参考第一个镜像的创建。
编写执行的shell脚本,创建5个容器,并分配主机名和IP地址,并映射 50070和8088两个http端口。
代码如下:

#!/bin/bash
#镜像的名称
OS="hadoop/centos:2.0"

#5个容器的IP地址 
ipaddrs=("172.2.0.2" "172.2.0.3" "172.2.0.4" "172.2.0.5" "172.2.0.6");

#容器的主机名。同时也是容器名
list=("master" "secondmaster" "slave1" "slave2" "slave3")

#这一步创建br网络 
docker network  create  -d bridge --subnet=172.2.0.0/24 --gateway=172.2.0.1 -o parent=en1 br

#这一步其实应该是要设置if语句的,但本人又些懒,不影响执行的就不予理睬的原则,就没写
docker rm -f $(docker ps -aq)
for((i=0;i<5;i++))
do
  if [ $i == 0 ];
  then
  #只要master容器 做端口映射, 这里直接共享宿主机的config中的hosts来完成对hosts的追加。 --add-host=xxx ..... 等价于 -v xxx/hosts:/etc/hosts。
     docker run -d -h ${list[$i]} --name=${list[$i]}  -v /Users/wuzishi/wudocker/config/hosts:/etc/hosts  -v  /Users/wuzishi/wudocker/resources/input:/input -p 50071:50070 -p 8087:8088  --privileged=true --net=br  --ip=${ipaddrs[$i]} $OS  /usr/sbin/init
   else
       docker run -d -h ${list[$i]} --name=${list[$i]}  -v /Users/wuzishi/wudocker/config/hosts:/etc/hosts   --privileged=true --net=br  --ip=${ipaddrs[$i]} $OS  /usr/sbin/init
 fi
done

#最后进入master的/bin/bash,进行 hadoop的启动和其他设置的验证。
docker exec -it master /bin/bash




执行脚本,可以获得5个容器,然后使用 hdfs namenode -fomat来格式化hdfs,再使用start-all.sh启动所以节点。

六、对hadoop文件的修改

此处的修改,我建议在宿主机上修改, 使用图形化界面的编辑工具比较方便一些。
此处 我创建了hadoop/tmp/目录,同时对 Hadoop-env.sh, core-site.xml,hdfs-site.xml,mapred-site.xml ,yarn.xml和slave进行修改。
我想看到此博客的同学们一定在虚拟机或宿主机上搭建过Hadoop集群环境,对于以上的配置文件和作用应该有一点了解的,我就直接晒自己的修改内容啦:

1、修改Hadoop-env.sh的配置

hadoop-env.sh中配置JAVA_HOME
# The java implementation to use.
export JAVA_HOME=/usr/local/java

2、完善core-site.xml的配置

这一内容防在configuration标签中
<property>
     <name>fs.defaultFS</name>
     <value>hdfs://master:9000</value>
</property>
<property>
     <name>hadoop.tmp.dir</name>
     <value>file:/usr/local/hadoop/tmp</value>
     <description>Abase for other temporary directories.</description>
</property>

3、对hdfs-site.xml文件进行完善,方式如上

<property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>secondmaster:50090</value>
</property>
<property>
   <name>dfs.replication</name>
   <value>3</value>
</property>
<property>
    <name>dfs.namenode.name.dir</name>
    <value>file:/usr/local/hadoop/tmp/dfs/name</value>
</property>
<property>
    <name>dfs.datanode.data.dir</name>
    <value>file:/usr/local/hadoop/tmp/dfs/data</value>
</property>

4、对mapred-site.xml文件的修改,这里要将 mapped-site.xml.temple文件重命名

<property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
</property>
<property>
    <name>mapreduce.jobhistory.address</name>
    <value>master:10020</value>
 </property>
<property>
     <name>mapreduce.jobhistory.webapp.address</name>
     <value>master:19888</value>
</property>

5、对yarn-site.xml文件进行完善

<property>
     <name>yarn.resourcemanager.hostname</name>
     <value>master</value>
</property>
<property>
     <name>yarn.nodemanager.aux-services</name>
     <value>mapreduce_shuffle</value>
</property>

6、对slaves文件的修改

slave1
slave2
slave3
~     
    
七、 环境搭建验收

1、 使用docker ps 查看 容器是否正常启动

这里我删去了一部分内容 主要展示进程是启动了的
 % docker ps
CONTAINER ID          COMMAND           STATUS              NAMES      
a81ce9b0ec0b     "/usr/sbin/init"     Up 21 seconds         slave3
97fac11d7aed     "/usr/sbin/init"     Up 20 seconds         slave2    
73cf48f37152     "/usr/sbin/init"     Up 20 seconds         slave1
8452b9faa662     "/usr/sbin/init"     Up 19 seconds       secondmaster
bf6a2ff885b5     "/usr/sbin/init"     Up 18 seconds         master
% 

2、在容器中使用JPS 查看节点是否都正常启动:

[root@master ~]# jps
708 NameNode
1268 Jps
998 ResourceManager

[root@secondmaster ~]# jps
723 Jps
563 NodeManager
441 SecondaryNameNode
361 DataNode

[root@slave1 ~]# jps
613 Jps
457 NodeManager
333 DataNode

[root@slave2 ~]# jps
673 Jps
517 NodeManager
393 DataNode

[root@slave3 ~]# jps
576 NodeManager
452 DataNode
731 Jps

如果和我展示的一样,恭喜你在容器里搭建成功了。

3、测试端口映射是否可用:
在宿主机浏览器中输入 localhost:50071和localhost:8087 (这个端口是我们是上面我们自己设置的). 如果如图所示,则你和我做的一样了。
在这里插入图片描述

在这里插入图片描述

感谢大家耐心的看完我的教程,
相关代码:我的GIT仓库
docker镜像:吴子誓的阿里云镜像库

  • 7
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值