使用 Docker 搭建 Hadoop + Hive + Spark 集群

本文探讨了使用 Docker 搭建 Hadoop + Hive + Spark 集群的方法,项目地址在此。在阅读本文前,建议先对 Docker 以及 Docker Compose 有基本的了解。

准备工作

本项目基于 Docker 和 Docker Compose,搭建的集群包含以下部分:

  • Hadoop
  • Hive
  • Spark

本项目参考了 Big Data Europe 的一些工作。项目中所使用的 Docker 镜像可能会被更新,可以参看他们的 Docker Hub 以获取最新镜像。

本项目所依赖的版本号如下:

1
2
3
4
5
6
Client:
 Version:           20.10.2
Server: Docker Engine - Community
 Engine:
  Version:          20.10.6
docker-compose version 1.29.1, build c34c88b2

快速开始

直接克隆我的项目并运行集群:

1
2
3
git clone https://gitee.com/horysk/docker-hadoop-workbench.git
cd docker-hadoop-workbench
./start_demo.sh

也可以使用 docker-compose-v2.yml,该集群包含我简单修改的 spark-master 镜像,以及额外添加的 spark-history-server 镜像。

1
./start_demo_v2.sh

使用 ./stop_demo.sh 或 ./stop_demo_v2.sh 关闭集群。你可以修改 start_demo.sh 与 stop_demo.sh 文件里的 DOCKER_COMPOSE_FILE 变量以使用其他版本的 YAML 文件。

集群内容

本集群包含以下 Container:

  • namenode
  • datanode
  • resourcemanager
  • nodemanager
  • historyserver
  • hive-server
  • hive-metastore
  • hive-metastore-postgresql
  • presto-coordinator
  • spark-master
  • spark-worker
  • spark-history-server (使用 v2 版本)

同时本集群需要用到名为 hadoop 的 network,以及以下 volume:

  • hadoop_namenode
  • hadoop_datanode
  • hadoop_historyserver
  • hive_metastore

这些都需要特别注意以避免冲突。

可交互的端口列表

综述

  • namenode: 9000, 9870
  • datanode: 9864
  • resourcemanager: 8088
  • nodemanager: 8042
  • historyserver: 8188
  • hive-server: 10000, 10002
  • hive-metastore: 9083
  • presto-coordinator: 8090
  • spark-master: 4040, 7077, 8080, 18080 (v2 版本 18080 接口由 spark-history-server 提供)
  • spark-worker: 8081

如有冲突,可以在 docker-compose.yml 里更改暴露的端口。

UI 列表

  • Namenode: http://localhost:9870/dfshealth.html#tab-overview
  • Datanode: http://localhost:9864/
  • ResourceManager: http://localhost:8088/cluster
  • NodeManager: http://localhost:8042/node
  • HistoryServer: http://localhost:8188/applicationhistory
  • HiveServer2: http://localhost:10002/
  • Spark Master: http://localhost:8080/
  • Spark Worker: http://localhost:8081/
  • Spark Job WebUI: http://localhost:4040/ (当 Spark 任务在 spark-master 运行时才可访问)
  • Presto WebUI: http://localhost:8090/
  • Spark History Server:http://localhost:18080/

HDFS

可以使用 hdfs dfs 连接到 hdfs://localhost:9000/ (请先在本机安装 Hadoop):

1
hdfs dfs -ls hdfs://localhost:9000/

Hive

可以使用 Beeline 连接到 HiveServer2 (请先在本机安装 Hive):

1
beeline -u jdbc:hive2://localhost:10000/default -n hive -p hive

Spark

可以使用 spark-shell 通过 thrift 协议连接到 Hive Metastore (请先在本机安装 Spark):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$ spark-shell

Welcome to
      ____              __
     / __/__  ___ _____/ /__
    _\ \/ _ \/ _ `/ __/  '_/
   /___/ .__/\_,_/_/ /_/\_\   version 3.1.2
      /_/

Using Scala version 2.12.10 (OpenJDK 64-Bit Server VM, Java 11.0.11)

scala> :paste
// Entering paste mode (ctrl-D to finish)

import org.apache.spark.sql.SparkSession

val spark = SparkSession.builder.master("local")
              .config("hive.metastore.uris", "thrift://localhost:9083")
              .enableHiveSupport.appName("thrift-test").getOrCreate

spark.sql("show databases").show


// Exiting paste mode, now interpreting.

+---------+
|namespace|
+---------+
|  default|
+---------+

import org.apache.spark.sql.SparkSession
spark: org.apache.spark.sql.SparkSession = org.apache.spark.sql.SparkSession@1223467f

Presto

可以使用 Presto CLI 连接 Presto 并且读取 Hive 的数据:

1
2
3
4
wget https://repo1.maven.org/maven2/com/facebook/presto/presto-cli/0.255/presto-cli-0.255-executable.jar
mv presto-cli-0.255-executable.jar presto
chmod +x presto
./presto --server localhost:8090 --catalog hive --schema default

设置列表

以下列举了容器内部的一些设置所在的位置。后面的以 CONF 结尾的是它们在 hadoop.env 中的代号。你可以参考 hadoop.env 文件做额外的设置。

  • namenode:
    • /etc/hadoop/core-site.xml CORE_CONF
    • /etc/hadoop/hdfs-site.xml HDFS_CONF
    • /etc/hadoop/yarn-site.xml YARN_CONF
    • /etc/hadoop/httpfs-site.xml HTTPFS_CONF
    • /etc/hadoop/kms-site.xml KMS_CONF
    • /etc/hadoop/mapred-site.xml MAPRED_CONF
  • hive-server:
    • /opt/hive/hive-site.xml HIVE_CONF

很可惜 Spark 的设置不在这个列表里。在 spark-master 的 /spark/conf 文件夹下可以存放 Spark 的设置,我准备了 scripts/spark-defaults.conf 与 scripts/spark-hive-site.xml 两个文件,它们已经在启动脚本里自动上传。

运行示例任务

运行 MapReduce WordCount

这部分基于 Big Data Europe’s Hadoop Docker 的项目里的运行示例。

首先我们运行一个辅助容器 hadoop-base

1
docker run -d --network hadoop --env-file hadoop.env --name hadoop-base bde2020/hadoop-base:2.0.0-hadoop3.2.1-java8 tail -f /dev/null

接下来运行以下命令以准备数据并启动 MapReduce 任务:

1
2
3
4
5
6
docker exec -it hadoop-base hdfs dfs -mkdir -p /input/
docker exec -it hadoop-base hdfs dfs -copyFromLocal -f /opt/hadoop-3.2.1/README.txt /input/
docker exec -it hadoop-base mkdir jars
docker cp jars/WordCount.jar hadoop-base:jars/WordCount.jar
docker exec -it hadoop-base /bin/bash 
hadoop jar jars/WordCount.jar WordCount /input /output

接下来,你可以通过以下链接看到任务状态:

  • http://localhost:8088/cluster/apps
  • http://localhost:8188/applicationhistory (运行结束后)

当任务运行完成,运行以下命令查看结果:

1
hdfs dfs -cat /output/*

最后你可以使用 exit 退出该容器。

运行 Hive 任务

请首先确定 hadoop-base 正在运行中。关于如何启动此辅助容器,请参看上一节。接下来准备数据:

1
2
3
4
5
6
7
docker exec -it hadoop-base hdfs dfs -mkdir -p /test/
docker exec -it hadoop-base mkdir test
docker cp data hadoop-base:test/data
docker exec -it hadoop-base /bin/bash
hdfs dfs -put test/data/* /test/
hdfs dfs -ls /test
exit

然后新建 Hive 表:

1
2
3
4
5
docker cp scripts/hive-beers.q hive-server:hive-beers.q
docker exec -it hive-server /bin/bash
cd /
hive -f hive-beers.q
exit

接下来你就可以使用 Beeline 访问到这些数据了:

1
2
3
beeline -u jdbc:hive2://localhost:10000/test -n hive -p hive

0: jdbc:hive2://localhost:10000/test> select count(*) from beers;

同样,你可以通过以下链接看到任务状态:

  • http://localhost:8088/cluster/apps
  • http://localhost:8188/applicationhistory (运行结束后)

运行 Spark Shell

在进行这一步前,请先参看前面两个章节以准备 Hive 数据并创建表格。然后运行以下命令:

1
docker exec -it spark-master spark/bin/spark-shell

进入 Spark Shell 后,你可以直接通过先前创建的 Hive 表进行操作:

1
2
3
4
5
6
7
8
9
10
11
12
13
scala> spark.sql("show databases").show
+---------+
|namespace|
+---------+
|  default|
|     test|
+---------+

scala> val df = spark.sql("select * from test.beers")
df: org.apache.spark.sql.DataFrame = [id: int, brewery_id: int ... 11 more fields]

scala> df.count
res0: Long = 7822

你可以在以下两个地址看到你的 Spark Shell 会话:

  • http://localhost:8080/
  • http://localhost:4040/jobs/ (运行时)

如果你在运行 spark-shell 的时候遇到了以下警告:

1
WARN TaskSchedulerImpl: Initial job has not accepted any resources; check your cluster UI to ensure that workers are registered and have sufficient resources

该警告显示没有资源可以去运行你的任务,并提醒你去检查 worker 是否都已经被注册,而且拥有足够多的资源。此时你需要使用 docker logs -f spark-master 检查一下 spark-master 的日志。不出意外的话,你会看到下面的内容:

1
WARN Master: Got heartbeat from unregistered worker worker-20210622022950-xxx.xx.xx.xx-xxxxx. This worker was never registered, so ignoring the heartbeat.

这是在提示你有一个 worker 没有被注册,所以忽略了它的心跳。该 worker 没有被注册的原因很多,很可能是之前电脑被休眠过,导致 worker 掉线。这时你可以使用 docker-compose restart spark-worker 重启 spark-worker,重启完成后,该 worker 就会被自动注册。

同样,如果要运行 spark-sql,可以使用这个命令:docker exec -it spark-master spark/bin/spark-sql

运行 Spark Submit 任务

我们直接运行 Spark 内置的示例任务 Spark Pi:

1
docker exec -it spark-master /spark/bin/spark-submit --class org.apache.spark.examples.SparkPi /spark/examples/jars/spark-examples_2.12-3.1.1.jar 100

你可以在以下两个地址看到你的 Spark Pi 任务:

  • http://localhost:8080/
  • http://localhost:4040/jobs/ (运行时)

本教程的集群搭建与使用方法就介绍到这里。以后可能会增加一些别的组件,会另外写文章来说明。

使用Docker搭建Hadoop + Hive + Spark集群(下) | Bambrow's Blog

你可能感兴趣的:(k8s,hadoop,spark,hadoop,docker)