云是未来,未来已来!
容器是云的核心组件,docker是实现容器的事实标准。
hadoop是使用最广的大数据组件,然而其并没有官方镜像。
所以,本文会搭建一个伪分布式版hadoop集群,用于CI测试非常方便。
准备
准备的文件结构如下:
├── dockerfile
├── hadoop
│ ├── core-site.xml
│ ├── hadoop-2.7.7.tar.gz
│ ├── hdfs-site.xml
│ ├── mapred-site.xml
└── start-service.sh
hadoop的安装包下载:https://apache.website-solution.net/hadoop/common/
这几个配置文件从包里拷出来,做好配置修改,再替换。
配置文件内容
core-site.xml
HOSTNAME会在启动服务前替换成镜像的hostname
<configuration>
<property>
<name>fs.defaultFS</name>
<value>hdfs://HOSTNAME:9000</value>
</property>
</configuration>
hdfs-site.xml
因为我们是单机版,所以只需要一个副本
<configuration>
<property>
<name>dfs.replication</name>
<value>1</value>
</property>
</configuration>
mapred-site.xml
使用yarn作为资源管理器
<configuration>
<property>
<name>mapreduce.framework.name</name>
<value>yarn</value>
</property>
</configuration>
构建镜像
dockerfile
先看dockerfile
FROM openjdk:8-jre
ENV BASE_DIR=/usr/local
# 安装hadoop
ENV HADOOP_VERSION=2.7.7
ENV HADOOP_HOME=${BASE_DIR}/hadoop-${HADOOP_VERSION}
ADD ./hadoop/hadoop-${HADOOP_VERSION}.tar.gz ${BASE_DIR}
# 主要有 core/hdfs/yarn/mapred-site.xml
COPY ./hadoop/*-site.xml /tmp/hadoop/
COPY ./start-service.sh ${BASE_DIR}/
ENV JAVA_HOME=/usr/local/openjdk-8
# ssh
RUN apt-key adv --keyserver keyserver.ubuntu.com --recv-keys 3B4FE6ACC0B21F32 \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic main restricted universe multiverse" > /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-updates main restricted universe multiverse" >> /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-backports main restricted universe multiverse" /etc/apt/sources.list \
&& echo "deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ bionic-security main restricted universe multiverse" /etc/apt/sources.list \
&& apt-get update && apt-get upgrade -y \
&& apt-get install -y openssh-server \
&& rm -rf /var/lib/apt/lists/* \
&& cd ${BASE_DIR}/hadoop-${HADOOP_VERSION} \
&& cp -rf /tmp/hadoop/*-site.xml etc/hadoop/ \
&& sed -i 's/${JAVA_HOME}/\/usr\/local\/openjdk-8/' ${HADOOP_HOME}/etc/hadoop/hadoop-env.sh \
&& ssh-keygen -t rsa -P '' -f ~/.ssh/id_rsa \
&& cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys \
&& chmod 0600 ~/.ssh/authorized_keys \
&& echo "StrictHostKeyChecking no" > ~/.ssh/config \
&& bin/hdfs namenode -format
# Hdfs ports
EXPOSE 50010 50020 50070 50075 50090 8020 9000
# Mapred ports
EXPOSE 10020 19888
# Yarn ports
EXPOSE 8030 8031 8032 8033 8040 8042 8088
ENTRYPOINT ${BASE_DIR}/start-service.sh
然后逐一解释下思路:
- 选择基础镜像:openjdk:8-jre,只需要有JDK的linux就行,这个是基于ubuntu
- 拷贝安装包到镜像里,我们安装在
/usr/local
下 - hadoop依赖于ssh,所以需要安装ssh,配置清华镜像比较快,同时要做ssh免密
- hadoop启动时需要配置JAVA_HOME路径,该基础镜像地址为:
/usr/local/openjdk-8
- 最后要格式化HDFS才能使用:
bin/hdfs namenode -format
- 启动入口是一个脚本,后面介绍
start-service.sh
用来启动hadoop,解释如下
# 先起ssh服务
service ssh start
# 替换hostname,在容器里,hostname就是一随机字符串,所以要动态获取
sed -i s/HOSTNAME/$HOSTNAME/ ${HADOOP_HOME}/etc/hadoop/core-site.xml
cd $BASE_DIR
${HADOOP_HOME}/sbin/start-dfs.sh
${HADOOP_HOME}/sbin/start-yarn.sh
# 因为hadoop是后台进程,启动后容器就退出了,所以为了让容器一直运行,做个死循环
while true; do sleep 1000; done
构建与测试
构建镜像
$ docker build -t jimo-hadoop:v1 .
...
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
jimo-hadoop v1 ce2b74913576 2 hours ago 661MB
运行
$ docker run -d --name hadoop -p 9000:9000 jimo-hadoop:v1
$ docker exec -it hadoop bash
/ # cd /usr/local/hadoop-2.7.7
/ # bin/hdfs -ls /