Docker上的Hadoop大数据平台搭建与测试
摘要:Docker是一个开源的应用容器,它可以让开发者将应用及其所需的依赖包打包到一个可移植的镜像中,可实现虚拟化。Hadoop是一开源的分布式系统基础架构,用于分布式计算,它可以给用户提供集群的高速运算和存储。本文简要介绍了Docker和Hadoop的发展史,Docker的架构,Hadoop的模块组件。并最终一步步搭建了Docker和Hadoop集群,并进行了测试。
大数据有四大特点(4V),分为别为:Volume(大量)、Variety(多样)、Velocity(高速)、Veracity(准确性)。新的特点需要使用新的技术,传统的HPC计算已经难以应付4V的挑战,相应而生的分布式计算架构很好地应对了问题。Hadoop便是其中之一的分布式架构平台,它有高可靠、高扩展、高效、高容错、低成本等优点,越来越受到关注与应用。
本文首先简述了容器和Docker与Hadoop的发展史,其次概述了Docker与Hadoop的架构模块,然后详细描述如何在真机上搭建环境并测试,最后进行总结和展望。
1. 简介与原理
1.1 Docker介绍
Docker 是一种运行于 Linux 和 Windows 上的软件,用于创建、管理和编排容器。是在 GitHub 上开发的 Moby 开源项目的一部分。
1.1.1 容器
容器(Coninter)是一种在单个系统上提供多个隔离的系统环境的技术。
1.1.1.1 容器历史
容器最早提出于1979年的Unix chroot。它是一个 UNIX 操作系统上的系统调用,用于将一个进程及其子进程的根目录改变到文件系统中的一个新位置,让这些进程只能访问到该目录。这个功能的想法是为每个进程提供独立的磁盘空间。
随后有2000 — FreeBSD Jails、2001 — Linux VServer、2004 — Solaris Containers、2005 — OpenVZ、2006 — Process Containers、2007 — Control Groups、2008 — LXC、2011 — Warden、2013 — LMCTFY、2013 — Docker、2014 — Rocket、2016 — Windows Containers。
1.1.1.2 容器原理
Linux上的容器是一个可以在单个Linux主机上提供多个相互隔离的操作系统级虚拟技术。与虚拟机技术(Virtual Machine)相比,容器(Container)不需要运行专门的访客(Guest)操作系统,也不需要模拟指令集。容器共享宿主机(Host)的操作系统内核,并使用访客操作系统的系统库来提供所需的功能。因此容器常常要比虚拟机快很多,且更加灵活和低消耗。
容器借助 Linux 内核的 Namespaces、Apparmor、SELinux 情景模式(profile)、chroot 和
CGroup 等功能来提供类似于虚拟机的隔离环境。Linux
的安全模块可以确保正确地控制容器对宿主机和内核的访问,从而避免各种入侵活动。此外,在宿主机上可以运行不同的 Linux
发行版,只要它们运行在同样的 CPU 架构下。
简单来说,容器提供的是一种基于各种 Linux 发行版创建容器镜像的方法、一套管理容器生命周期的 API、与该 API
交互的客户端工具、保存快照的功能、在宿主机之间迁移容器实例的能力,等等。
1.1.2 Docker
1.1.2.1 Docker历史
2013年,dotCloud为寻求新的突破,更名为Docker,并发布了开源的容器Docker。Docker 引入了一整套容器管理的生态系统,包括分层的镜像模型,容器注册库,友好的 Rest API等。
2016 年微软也在 Windows 上提供了容器的支持,Docker 可以以原生方式运行在 Windows 上,而不是需要使用 Linux 虚拟机。
1.1.2.2 Docker原理
核心技术有:
namespace:隔离其运行环境,使得容器中的进程看起来就像一个独立环境中运行一样。
cgroup:为系统中所运行任务(进程)的用户定义组群分配资源。可以监控管理员配置的 cgroup,拒绝 cgroup 访问某些资源,甚至在运行的系统中动态配置 cgroup。主要功能包括了:限制资源使用、优先级控制、审计计费、 挂起和恢复进程
守护进程:直接与主操作系统进行通信、为各个Docker容器分配资源、将容器与主操作系统隔离,并将各个容器互相隔离。
Docker的基础结构有(从底层到上层)
基础设施:即各种硬件设施和配套的底层软件
主操作系统:有Linux、Windows、MacOS等。用于支持Docker运行
各种依赖:打包在Docker镜像(Image)之中,容器(Container)依赖于镜像创建
应用:应用的源代码与依赖项打包在Docker镜像中,不同的应用需要不同的Docker镜像。不同镜像之间相互隔离。
1.2 Hadoop简介
Hadoop更注重代码向数据迁移,有高容错性的特点,并且设计用来部署在低廉的(low-cost)硬件上,且它提供高吞吐量(high throughput)。
1.2.1 Hadoop历史
2003-2004年,Google公布了部分GFS和MapReduce思想的细节,受此启发的Doug Cutting等人用2年的业余时间实现了DFS和MapReduce机制。
2005年,Hadoop作为Lucene的子项目Nutch的一部分正式引入Apache基金会。
2006年2月被分离出来,成为一套完整独立的软件,起名为Hadoop。
2008年4月— 赢得世界最快1TB数据排序在900个节点上用时209秒。
2011年12月27日–1.0.0版本释出。标志着Hadoop已经初具生产规模。
1.2.2 Hadoop架构
Hadoop分为两个模块,一个是文件系统核心模块(HDFS),另一个是数据计算核心模块(MapReduce)。
1.2.2.1 Hadoop的文件系统核心模块
HDFS采用主从架构(master/slaves)。一个HDFS集群由一个主节点(Namenode)和一定数量的从节点(Datanodes)组成。Namenode是一个中心服务器,负责管理文件系统的名字空间(namespace)以及客户端对文件的访问。Datanode是一个节点一个,负责节点上的存储。
从内部看,一个文件其实被分成一个或多个数据块,这些块存储在一组Datanode上。Namenode执行文件系统的名字空间操作。Datanode负责处理文件系统客户端的读写请求,在Namenode的统一调度下进行数据块的创建、删除和复制。
secondaryNameNode用于hadoop当中元数据信息的辅助管理。
1.2.2.2 Hadoop的数据计算核心模块
Map/Reduce是一个使用简易的软件框架,基于它写出来的应用程序能够运行在由上千个商用机器组成的大型集群上,并以一种可靠容错的方式并行处理上T级别的数据集。
一个作业将数据集分割为独立的数据块,由Map任务以并行的方式处理数据。
MapReduce框架由一个单独的主作业控制(master JobTracker )和每个集群节点一个从任务控制(slave TaskTracke)共同组成。master负责调度构成一个作业的所有任务,这些任务分布在不同的slave上,master监控它们的执行,重新执行已经失败的任务。而slave仅负责执行由master指派的任务。
ResourceManager:接收用户的计算请求任务,并负责集群的资源分配,以及计算任务的划分
NodeManager:负责执行主节点ResourceManager分配的任务
1.2.3 Hadoop运行流程
MapReduce分3个阶段执行,分别是映射(Map)阶段、洗牌(Shuffle)阶段、归约(Reduce)阶段。
Shuffle表示数据进行整理(核心机制:对数据进行分区,排序,缓存)即拉取partition,merge,sort,combine
一个MapReduce的工作过程是:
向集群服务器发送Map与Reduce任务。
管理数据传递。
本地计算,减少网络通数据通信。
完成任务后,收集数据,将合适的结果返回给Master服务器
2. 环境搭建
Hadoop有三种模式(单机模式,伪分布模式,全分布模式)。本文选用全分布模式搭建集群。
2.1 本机环境
2.2 物料说明
宿主机:Ubuntu18.04
Docker
JDK
Hadoop
Spark
操作路径为/home/
2.3 安装基本环境
安装Docker容器
# 删除可能有的旧版本
sudo apt-get remove docker docker-engine docker.io containerd runc
# 更新apt
sudo apt-get update
# 让apt支持https
sudo apt-get install apt-transport-https ca-certificates curl gnupg-agent software-properties-common
# 安装官方GPG密钥
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -
sudo add-apt-repository "deb [arch=amd64] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable"
// 阿里云
// curl -fsSL http://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add -
// sudo add-apt-repository "deb [arch=amd64] http://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable"
# 安装docker-ce
sudo apt-get update
sudo apt-get install docker-ce
sudo apt-get install docker-ce-cli
sudo apt-get install containerd.io
在Docker中拉取Ubuntu18.04镜像并创建容器
# 拉取ubuntu 18.04镜像
sudo docker pull ubuntu:18.04
# 查找拉取的镜像id
sudo docker images
# 启动一个master容器
sudo docker run -dit -h master
# 查找创建的容器id
sudo docker ps
# 进入容器
sudo docker exec -it /bin/bash
注:和需要换成对应的id,及生成的hash,如不清楚,可以查看附录1中查看Docker中image、container的命令。
绑定端口
sudo docker run -dit -h master -p 9870:9870 -p 8080:8080 -p 4040:4040 -p 8088:8088 -p 8099:8099
配置master容器
首先要确认自己已经进入到master容器中
正确的应该是上面第二行呈现的样子。如果不正确,请检测前面运行是否正确,找不到问题,就"sudo docker ps -a"查看已创建的Container,然后"sudo docker start ",最后"sudo docker exec -it /bin/bash"
确认完后,开始配置master容器
# 更新apt
apt-get update
apt-get pagrade
# 安装net-tools
apt-get install net-tools
# 安装vim
apt-get install vim
# 安装ssh,配置无密码登录
apt-get install openssh-server
ssh-keygen -t rsa -P ''
回车
cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
# 查询是否开启ssh
/etc/init.d/ssh status
# 开启ssh
/etc/init.d/ssh start
# 配置开机启动
vim /etc/rc.local
# 在exit 0语句前加入
/etc/init.d/ssh start
安装java
这里使用wget下载java,如果本文给出的url无法正确获取到java文件,请自行查找最新的url予以替换,或直接使用“apt install default-jre”安装开源版本。
#安装wget库
apt install wget
#进入usr/local/src目录下
cd /usr/local/src
#获取JDK1.8包
wget --no-check-certificate --no-cookies --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz
#解压jdk-8u161-linux-x64.tar.gz
tar -zxvf jdk-8u131-linux-x64.tar.gz
#重命名为JDK8
mv jdk1.8.0_131 jdk8
#配置环境变量
vim ~/.bashrc #打开环境变量配置文件
#增加下面内容到该文件最后
export JAVA_HOME=/usr/local/src/jdk8
export PATH=$JAVA_HOME/bin:$PATH
export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar
#使环境生效
source ~/.bashrc
安装Hadoop
# 安装hadoop
wget http://mirrors.hust.edu.cn/apache/hadoop/common/hadoop-3.2.0/hadoop-3.2.0.tar.gz
# 解压
tar -zxvf hadoop-3.2.0.tar.gz
# 重命名
mv hadoop-3.2.0 hadoop
# 添加环境变量
sudo vim ~/.bashrc
# 添加以下代码
# hadoop
export HADOOP_HOME=/home/hadoop
export CLASSPATH=$($HADOOP_HOME/bin/hadoop classpath):$CLASSPATH
export HADOOP_COMMON_LIB_NATIVE_DIR=$HADOOP_HOME/lib/native
export PATH=$PATH:$HADOOP_HOME/bin:$HADOOP_HOME/sbin
# 生效
sudo source ~/.bashrc
配置分布式hadoop
# 当前路径为/home/hadoop/
# 创建三个文件夹备用
mkdir -p hdfs/{data,name,tmp}
修改配置
cd /home/hadoop/etc/hadoop
以下修改XXX,均使用“vim XXX”方式进行编写,不再赘述
修改hadoop-env.sh
# 在文中只改这一行
export JAVA_HOME=/home/bigdata/jdk1.8
修改core-site.xml
fs.defaultFS
hdfs://master:9000
hadoop.tmp.dir
/home/bigdata/hdfs/tmp
修改hdfs-site.xml
dfs.namenode.name.dir
/home/bigdata/hadoop/hdfs/name
dfs.http.address
0.0.0.0:50070
dfs.datanode.data.dir
/home/bigdata/hdfs/data
dfs.replication
2
修改mapred-site.xml,注意这里的目录一定要和上面定义的目录相统一,否则DataNode会崩溃,无法集群
mapreduce.framework.name
yarn
yarn.app.mapreduce.am.env
HADOOP_MAPRED_HOME=/home/hadoop
mapreduce.map.env
HADOOP_MAPRED_HOME=/home/hadoop
mapreduce.reduce.env
HADOOP_MAPRED_HOME=/home/hadoop
修改yarn-site.xml
yarn.nodemanager.aux-services
mapreduce_shuffle
yarn.resourcemanager.hostname
master
创建workers文件(Hadoop3将slaves文件改名为workers了)
touch workers
vim workers
# 添加:
master
slave01
slave02
格式化HDFS,这里只需要运行一次,如果运行多了需要删除工作目录下HDFS文件,然后重新格式化,详情自行搜索
cd /home/hadoop/bin
# 该命令只需运行一次
hdfs namenode -format
修改运行文件
cd /home/hadoop/sbin
# 在start-dfs.sh,stop-dfs.sh文件顶部加入以下配置
#!/usr/bin/env bash
HDFS_DATANODE_USER=root
HADOOP_SECURE_SECURE_USER=hdfs
HDFS_NAMENODE_USER=root
HDFS_SECONDARYNAMENODE_USER=root
# 在start-yarn.sh,stop-yarn.sh文件顶部加入以下配置
#!/usr/bin/env bash
YARN_RESOURCEMANAGER_USER=root
HADOOP_SECURE_DN_USER=yarn
YARN_NODEMANAGER_USER=root
安装Scala
wget https://downloads.lightbend.com/scala/2.11.8/scala-2.11.8.tgz
tar -zxvf scala-2.11.8.tgz
mv scala-2.11.8 scala
# 添加环境变量
vim ~/.bashrc
# 添加以下代码
# scala
export SCALA_HOME=/home/scala
export PATH=$PATH:$SCALA_HOME/bin
# 生效
source ~/.bashrc
安装Spark
wget http://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-2.4.3/spark-2.4.3-bin-hadoop2.7.tgz
tar -zxvf spark-2.4.3-bin-hadoop2.7.tgz
mv spark-2.4.3-bin-hadoop2.7 spark
# 添加环境变量
vim ~/.bashrc
# 添加以下代码
# spark
export SPARK_HOME=/home/spark
export PATH=$PATH:$SPARK_HOME/bin
export PATH=$PATH:$SPARK_HOME/sbin
# 生效
source ~/.bashrc
配置文件
cd /home/spark/conf
cp spark-env.sh.template spark-env.sh
# spark-env.sh添加以下代码
export JAVA_HOME=/home/jdk1.8
export HADOOP_HOME=/home/hadoop
export HADOOP_CONF_DIR=/home/hadoop/etc/hadoop
export SCALA_HOME=/home/scala
export SPARK_HOME=/home/spark
export SPARK_MASTER_HOST=master
export SPARK_MASTER_PORT=7077
export SPARK_MASTER_WEBUI_PORT=8099
export SPARK_WORKER_CORES=3
export SPARK_WORKER_INSTANCES=1
export SPARK_WORKER_MEMORY=5G
export SPARK_WORKER_WEBUI_PORT=8081
export SPARK_EXECUTOR_CORES=1
export SPARK_EXECUTOR_MEMORY=1G
export LD_LIBRARY_PATH=${LD_LIBRARY_PATH}:$HADOOP_HOME/lib/native
cp slaves.template slaves
# slaves添加以下代码
master
slave01
slave02
提交master并克隆出slaves
# 退出容器
exit
# 提交容器更改
sudo docker commit ubuntu-hadoop-spark:1.0
# 用刚刚提交的ubuntu-hadoop-spark:1.0创建两个slave
sudo docker run -dit -h slave01
sudo docker run -dit -h slave02
# 运行两个slave
sudo docker exec -it slave01 /bin/bash
sudo docker exec -it slave02 /bin/bash
到这里之后就配置好一个master两个worker了
13. hosts配置
分别进入master、slave01和slave02,用ifconfig命令找出相应的ip,并分别修改hosts文件
vim /etc/hosts
# 添加
xxx.xxx.xxx.xx1 master
xxx.xxx.xxx.xx2 slave01
xxx.xxx.xxx.xx3 slave02
启动
分别进入三个容器,启动命令相同
# 启动hadoop
cd /home/hadoop/sbin
./start-dfs.sh
./start-yarn.sh
# 启动spark
cd /home/spark/sbin
./start-all/sh
使用 JPS检测启动
如果集群不成功,检测路径等问题,NameNode一会就消失是format的问题,需要重新格式化
两个管理网页
http://(master ip):8088/
http://(master ip):50070/
2.4 测试环境
首先查看是否运行成功
这里是start-all.sh的样子,也可以分别启动hdfs和yern
这样是启动成功了的
创建目录
hadoop fs -mkdir /input
然后就能看见创建的目录了
3. 放入文件
我这里就用hadoop中的LICENSE文件做count了
hadoop fs -put /home/hadoop/LICENSE.txt /input
放入wordcount程序
hadoop jar /home/hadoop/share/hadoop/mapreduce/hadoop-mapreduce-examples-3.2.0.jar
注意与自己的路径相符和文件名,我这里是3.2.0.你那里可能版本不一样
4. 运行wordcount
wordcount /input /output
结果:
6. 将结果下载下来
这里的ip请填master对应ip,在下载时会自动跳到slave上,请修改成正确的ip
3. 总结
Docker是一个非常好用的开源容器,它节约了开发、维护、测试时对环境的配置问题,并且很好的解决了虚拟机效率不高的问题。本文主要对它的历史和架构做了简单描述,通过在Docker上创建一个Image,并在上搭建了全分布式Hadoop。Hadoop是运用广泛的开源分布式计算平台,本文主要介绍了它的历史和架构,并通过搭建它的环境和用一个例子来简要概述了它的流程。为我们进一步研究分布式并行算法和处理分析大数据提供了平台。
附录1 Docker常用命令
# 重启docker服务
sudo service docker restart
# 关闭docker服务
sudo service docker stop
# 开启docker服务
sudo service docker start
# 拉取ubuntu 18.04镜像
sudo docker pull ubuntu:18.04
# docker create 命令为指定的镜像(image)添加了一个可读写层,构成了一个新的容器。注意,这个容器并没有运行。
sudo docker create
# docker run = docker create + docker start
sudo docker run -p 宿主机端口:docker端口
# 后台运行
sudo docker run -dit
# 运行直接进入bash,退出后后台不运行
sudo docker run -it /bin/bash
# 查看本地镜像
sudo docker images
# 删除镜像
sudo docker rmi
# docker start命令为容器文件系统创建了一个进程隔离空间。注意,每一个容器只能够有一个进程隔离空间。
docker start
# 查看当前运行的容器
docker ps
# 查询存在的容器
docker ps -a
# 删除容器
docker rm
# 强制删除容器
docker rm -f
# 不能够删除一个正在运行的容器,会报错。需要先停止容器。
# 进入容器内部
sudo docker exec -it (container name or id) /bin/bash
# 退出容器
exit
# 容器重命名
docker container rename newname
# 提交
docker commit
注:文中所给、都要用对应的id进行替换,不要直接照抄。
附页2 Hadoop常见命令
1、启动hadoop所有进程
start-all.sh等价于start-dfs.sh + start-yarn.sh
但是一般不推荐使用start-all.sh(因为开源框架中内部命令启动有很多问题)。
2、单进程启动。
sbin/start-dfs.sh
---------------
sbin/hadoop-daemons.sh --config .. --hostname .. start namenode ...
sbin/hadoop-daemons.sh --config .. --hostname .. start datanode ...
sbin/hadoop-daemons.sh --config .. --hostname .. start sescondarynamenode ...
sbin/hadoop-daemons.sh --config .. --hostname .. start zkfc ... //
sbin/start-yarn.sh
--------------
libexec/yarn-config.sh
sbin/yarn-daemon.sh --config $YARN_CONF_DIR start resourcemanager
sbin/yarn-daemons.sh --config $YARN_CONF_DIR start nodemanager
3、常用命令
1、查看指定目录下内容
hdfs dfs –ls [文件目录]
hdfs dfs -ls -R / //显式目录结构
eg: hdfs dfs –ls /user/wangkai.pt
2、打开某个已存在文件
hdfs dfs –cat [file_path]
eg:hdfs dfs -cat /user/wangkai.pt/data.txt
3、将本地文件存储至hadoop
hdfs dfs –put [本地地址] [hadoop目录]
hdfs dfs –put /home/t/file.txt /user/t
4、将本地文件夹存储至hadoop
hdfs dfs –put [本地目录] [hadoop目录]
hdfs dfs –put /home/t/dir_name /user/t
(dir_name是文件夹名)
5、将hadoop上某个文件down至本地已有目录下
hadoop dfs -get [文件目录] [本地目录]
hadoop dfs –get /user/t/ok.txt /home/t
6、删除hadoop上指定文件
hdfs dfs –rm [文件地址]
hdfs dfs –rm /user/t/ok.txt
7、删除hadoop上指定文件夹(包含子目录等)
hdfs dfs –rm [目录地址]
hdfs dfs –rmr /user/t
8、在hadoop指定目录内创建新目录
hdfs dfs –mkdir /user/t
hdfs dfs -mkdir - p /user/centos/hadoop
9、在hadoop指定目录下新建一个空文件
使用touchz命令:
hdfs dfs -touchz /user/new.txt
10、将hadoop上某个文件重命名
使用mv命令:
hdfs dfs –mv /user/test.txt /user/ok.txt (将test.txt重命名为ok.txt)
11、将hadoop指定目录下所有内容保存为一个文件,同时down至本地
hdfs dfs –getmerge /user /home/t
12、将正在运行的hadoop作业kill掉
hadoop job –kill [job-id]
13.查看帮助
hdfs dfs -help