Docker搭建Hadoop分布式集群

docker是一个轻量化部署工具,相比虚拟机,Docker构建部署包更小,启动更快速,占用资源更少。

接下来,我们考虑在单机上创建5个Docker容器,包括一个master容器和四个slave容器,容器之间相互隔离,通过加入创建的Docker虚拟网络hadoop_network实现网络互联。

下载与安装

地址:https://hub.docker.com/editions/community/docker-ce-desktop-mac

构建JDK镜像

我们考虑直接下载Docker hub上的Ubuntu系统来编写镜像。

我们创建一个镜像目录image_jdk,下载的jdk文件放到该目录下,然后在目录中编写两个文件build.sh和Dockerfile:

#build.sh
Docker image build -t centos_jdk:1.0 .
#Dockerfile

#初始镜像继承centos
FROM centos:centos7.7.1908

#镜像维护者信息
MAINTAINER wenhuan

#构建容器命令
#安装openssh-server、openssh-clients、sudo、vim和net-tools软件包
RUN yum -y install openssh-server openssh-clients sudo vim net-tools

#设置密码
RUN echo "root:wenhuan" | chpasswd

#生成相应的主机密钥文件【rsa、ecdsa、ed25519都是算法名称】
RUN ssh-keygen -t rsa -f /etc/ssh/ssh_host_rsa_key
RUN ssh-keygen -t ecdsa -f /etc/ssh/ssh_host_ecdsa_key
RUN ssh-keygen -t ed25519 -f /etc/ssh/ssh_host_ed25519_key

#将JDK文件放到镜像/opt目录下,ADD命令会自动解压。
ADD ./jdk-8u181-linux-x64.tar.gz /opt/
#重命名解压后的JDK文件目录
RUN mv /opt/jdk1.8.0_181 /opt/java
#创建环境变量
ENV JAVA_HOME /opt/java
ENV JRE_HOME ${JAVA_HOME}/jre
ENV CLASSPATH .:${JAVA_HOME}/lib:${JRE_HOME}/lib
ENV PATH $PATH:$JAVA_HOME/bin

之后执行以下命令即构建了centos_jdk1.0,至此JDK镜像构建成功:

sh build.sh

构建Hadoop镜像

先创建一个镜像目录image_hadoop, 下载hadoop压缩包和解压后的安装包放到image_hadoop目录下,编写构建命令,保存到build.sh:

Docker image build -t cluster_hadoop:1.0 .

编辑hadoop-env.sh文件如下:

export JAVA_HOME=/opt/java

export HADOOP_CONF_DIR=/opt/hadoop/etc/hadoop

编辑core-site.xml文件如下:

<configuration>
  <property>
    <!--hadoop临时目录-->
    <name>hadoop.tmp.dir</name>
    <value>file:/data/hadoop/tmp</value>
    <description>默认存在/tmp目录</description>
  </property>
  <property>
    <!--HDFS NameNode地址-->
    <name>fs.defaultFS</name>
    <value>hdfs://master:9000</value>
    <description>指定hdfs的主节点</description>
  </property>
</configuration>

编辑hdfs-site.xml文件如下:

<configuration>
  <property>
    <!--HDFS副本数-->
    <name>dfs.replication</name>
    <value>2</value>
    <description>指定hdfs的副本数</description>
  </property>
  <property>
    <name>dfs.namenode.name.dir</name>
    <value>file:/home/hadoop/hadoop/tmp/dfs/name</value>
    <description>指定namenode数据的目录</description>
  </property>
  <property>
    <name>dfs.datanode.data.dir</name>
    <value>file:/home/hadoop/hadoop/tmp/dfs/data</value>
    <description>指定datanode数据的目录</description>
  </property>
  <property>
    <name>dfs.namenode.secondary.http-address</name>
    <value>master:9001</value>
    <description>指定secondarynamenode的节点</description>
  </property>
  <property>
    <name>dfs.permissions</name>
    <value>false</value>
    <description>任何人都可以hdfs上操作文件</description>
  </property>
</configuration>

编辑mapred-site.xml文件如下:

<configuration>
  <property>
    <name>mapreduce.framework.name</name>
    <value>yarn</value>
    <description>指定MapReduce运行在yarn上</description>
  </property>
  <property>
    <name>mapreduce.jobhistory.address</name>
    <value>master:10020</value>
    <description>任务历史服务器地址</description>
  </property>
  <property>
    <name>mapreduce.jobhistory.webapp.address</name>
    <value>master:19888</value>
    <description>任务历史服务器web-ui地址</description>
  </property>
</configuration>

编辑yarn-site.xml文件如下:

<configuration>
  <property>
    <name>yarn.resourcemanager.hostname</name>
    <value>master</value>
    <description>指定yarn的主节点</description>
  </property>
  <property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce_shuffle</value>
    <description>允许MapReduce运行在yarn上</description>
  </property>
  <property>
    <name>yarn.log-aggregation-enable</name>
    <value>true</value>
  </property>
  <property>
    <name>yarn.log-aggregation.retain-seconds</name>
    <value>604800</value>
  </property>
</configuration>

编辑slaves文件,填写从属节点的主机名:

slave1
slave2
slave3
slave4

编写Dockerfile文件:

#继承之前构建的镜像
FROM centos_jdk:1.0

#将Hadoop包复制到镜像中
ADD hadoop-2.7.7.tar.gz /opt/
RUN mv /opt/hadoop-2.7.7 /opt/hadoop
#将本地的配置文件复制到镜像中并覆盖对应的文件
COPY hadoop/etc/hadoop/hadoop-env.sh /opt/hadoop/etc/hadoop
COPY hadoop/etc/hadoop/core-site.xml /opt/hadoop/etc/hadoop
COPY hadoop/etc/hadoop/hdfs-site.xml /opt/hadoop/etc/hadoop
COPY hadoop/etc/hadoop/mapred-site.xml /opt/hadoop/etc/hadoop
COPY hadoop/etc/hadoop/yarn-site.xml /opt/hadoop/etc/hadoop
COPY hadoop/etc/hadoop/slaves /opt/hadoop/etc/hadoop

ENV HADOOP_HOME /opt/hadoop
ENV HADOOP_INSTALL=$HADOOP_HOME
ENV HADOOP_MAPRED_HOME=$HADOOP_HOME
ENV HADOOP_COMMON_HOME=$HADOOP_HOME
ENV HADOOP_HDFS_HOME=$HADOOP_HOME
ENV YARN_HOME=$HADOOP_HOME
ENV PATH ${HADOOP_HOME}/bin:${HADOOP_HOME}/sbin:$PATH
EXPOSE 22
ENV HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native

执行build.sh构建镜像。
构建Hive镜像
先创建一个镜像目录image_hive, 下载Hive压缩包和解压后的安装包放到image_hive目录下,编写构建命令,保存到build.sh:

Docker image build -t cluster_hive:1.0 .

编写Docker文件:

#继承之前的镜像
FROM cluster_hadoop:1.0
#复制hive文件到镜像/opt目录下
ADD apache-hive-1.2.2-bin.tar.gz /opt
#修改镜像hive目录名称,创建/opt/data及以下目录
RUN mv /opt/apache-hive-1.2.2-bin/ /opt/hive/ && mkdir -p /opt/data/hive_resources /opt/data/hive && chmod 666 /opt/data/hive
#声明环境变量
ENV HIVE_HOME /opt/hive
ENV PATH ${HIVE_HOME}/bin:$PATH
#目录切换到/opt/hive/conf
WORKDIR /opt/hive/conf
RUN mv hive-default.xml.template hive-site.xml && mv hive-log4j.properties.template hive-log4j.properties
#sed替换hive-site.xml的配置项
RUN sed -i "s?\${system:java.io.tmpdir}?/opt/data?g" hive-site.xml && 
    sed -i "s?\${system:user.name}?hive?g" hive-site.xml
RUN cp -r /opt/hive/lib/jline-2.12.jar /opt/hadoop/share/hadoop/yarn/lib

执行build.sh构建镜像。
构建Spark镜像
先创建一个镜像目录image_spark, 下载Spark压缩包和解压后的安装包放到image_spark目录下,编写构建命令,保存到build.sh:

Docker image build -t cluster_spark:1.0 .

spark解压包更名为spark, 在spark/conf/目录下找到文件spark-env.sh.template改名为spark-env.sh,并打开文件,在末尾追加一行:

export SPARK_DIST_CLASSPATH=$(${HADOOP_HOME}/bin/hadoop classpath)

这样,spark才能共享hadoop的hdfs等组件。
在spark/conf/目录下找到文件slaves.template改名为slaves,并编辑:

slave1
slave2
slave3
slave4

接下来编写Docker文件:

#继承之前的镜像
FROM cluster_hive:1.0
#复制spark文件到镜像/opt目录下
ADD spark-2.4.6-bin-hadoop2.7.tgz /opt
#修改镜像spark目录名称
RUN mv /opt/spark-2.4.6-bin-hadoop2.7/ /opt/spark/
#将本地的配置文件复制到镜像中并覆盖对应的文件
COPY spark/conf/spark-env.sh /opt/spark/conf/spark-env.sh
#声明环境变量
ENV SPARK_HOME /opt/spark
ENV PATH ${SPARK_HOME}/bin:$PATH
WORKDIR /opt
#运行容器,启动SSH服务
CMD ["sh","-c","service ssh start; bash"]

执行build.sh构建镜像。

配置集群网络
输入以下命令可以查看当前docker的网络:

docker network ls

返回结果如下:

NETWORK ID     NAME      DRIVER    SCOPE
d0b83392d44a   bridge    bridge    local
a7ee8fd045f8   host      host      local
1c9ccc5dc18a   none      null      local

如果不做任何网络配置的情况下,容器默认使用bridge方式连接网络,这样容器每次重启后,IP都会发生变动。
我们先查看一下默认bridge这个网络的信息:

docker network inspect d0b83392d44a

可以看到返回一段信息:

......

"IPAM": {
            "Driver": "default",
            "Options": null,
            "Config": [
                {
                    "Subnet": "172.17.0.0/16",
                    "Gateway": "172.17.0.1"
                }
            ]
        },

......

可以看到docker默认使用的是一个B类段段子网IP,接下来我们配置一个名为hadoop_network的子网,给它分配一个C类段的子网:

docker network create --subnet=172.22.0.0/24 hadoop_network

启动集群
接下来编写一个启动集群的脚本start.sh:

#!/usr/bin/env bash
#自定义网络名称
NETWORK_NAME=hadoop_network
#自定义镜像网络名称
IMAGE_ID=405d71c96bca

sudo Docker rm -f master &> /dev/null
echo "start master container..."
sudo Docker run -itd --name master --hostname master --net ${NETWORK_NAME} --ip 172.22.0.2 -P -p 50070:50070 -p 8088:8088 -p 7077:7077 --privileged=true ${IMAGE_ID} /usr/sbin/init

i=1
while [ $i -lt 5 ]
do
  sudo Docker rm -f slave$i &> /dev/null
  echo "start slave$i container..."
  sudo Docker run -itd --name slave$i --hostname slave$i --net ${NETWORK_NAME} --ip 172.22.0.$[$i+2] -P --privileged=true ${IMAGE_ID} /usr/sbin/init
  i=$(($i + 1))
done

sudo Docker exec -it master bash

执行以上脚本,创建基于同一份镜像的5个容器后,依次进入5个节点,修改etc/hosts文件配置IP映射:

172.22.0.2 master
172.22.0.3 slave1
172.22.0.4 slave2
172.22.0.5 slave3
172.22.0.6 slave4

接下来,把每个节点的公钥传送给其他节点:

ssh-copy-id -i ~/.ssh/id_rsa.pub master
ssh-copy-id -i ~/.ssh/id_rsa.pub slave1
ssh-copy-id -i ~/.ssh/id_rsa.pub slave2
ssh-copy-id -i ~/.ssh/id_rsa.pub slave3
ssh-copy-id -i ~/.ssh/id_rsa.pub slave4

之后输入以下命令:

start-dfs.sh
start-yarn.sh
mr-jobhistory-daemon.sh start historyserver
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 156,907评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,546评论 1 289
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 106,705评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,624评论 0 203
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 51,940评论 3 285
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,371评论 1 210
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,672评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,396评论 0 195
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,069评论 1 238
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,350评论 2 242
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,876评论 1 256
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,243评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,847评论 3 231
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,004评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,755评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,378评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,266评论 2 259

推荐阅读更多精彩内容