本文csdn地址

项目地址

docker-centos

背景

在完成几个开源中间件的容器化一键部署之后,和一个同事聊到了关于如何在本地部署 hadoop 集群,方便进行大数据任务相关的测试

后面我们一起搜了一些资料,在知乎[1]上找到有人弄好了一套镜像[2], 功能应该是比较完善的,只是稍微有一点不足是没有支持 arm 版本

所以之后那位同事还是用虚拟机的方式,手动部署 Hadoop 搭建好了本地测试集群,省不了的是一些手动配置的操作,虽然也不会太复杂

而自己的想法是: 既然已经接触了除了 hdfs 之外的上层应用,比如 knox、ranger 等,是否可以按照之前部署 zk 集群的思路[3],把 hadoop 基础集群也写到 docker compose 里面呢?

于是,接近两个月的各种踩坑和实践开始了

效果

服务部署

两种部署方式: 从头开始搭建镜像 再启动服务 or 直接从 dockerhub 拉取镜像并启动服务,通过前者有助于你了解镜像结构,但是如果是想快速部署服务建议参考后者

【建议】直接拉取镜像:
为了方便使用,我已经将镜像提交到 dockerhub (mzsmieli/centos_hdfs_full),直接拉取并启动即可

1
2
3
4
5
6
# 下载镜像
docker pull mzsmieli/centos_hdfs_full:v1.0.0
docker pull mzsmieli/centos_mysql:v1.0.0

# 运行hdfs集群
REPO=mzsmieli make run_hdfs_cluster

构建镜像:
下载工程 docker-centos 后,需要依次准备以下镜像:

  • centos_base
    • centos 基础环境镜像
  • centos_java
    • java 基础镜像
  • centos_hdfs
    • hdfs 基础镜像,包含 hadoop 服务,依赖 java 镜像
  • centos_hive
    • hive 基础镜像,包含 hadoop、hive 服务,依赖 hdfs 镜像
  • centos_knox
    • knox 镜像,依赖 java 镜像
  • centos_hdfs_full
    • 完整 hadoop 镜像,在 hdfs+hive+knox 基础上提供 flink、spark
  • centos_minimal
    • centos 部署服务最小镜像
  • centos_mysql
    • mysql 镜像,依赖 minimal

镜像整体架构图:
hdfs_image

概括来说就是 centos 基础镜像 -> 各语言开发镜像 -> 服务镜像

完整指令:

1
2
3
4
5
# 构建镜像(首次构建所有镜像大约需要半个小时)
make build_hdfs_cluster

# 运行hdfs集群
make run_hdfs_cluster

端口和地址说明:

hdfs

hdfs_hdfs_datanode

yarn

hdfs_yarn_total

flink、spark

提交任务这块做了简单的提交验证

提交 flink 任务:

1
2
cd /opt/modules/flink-1.15.0
./bin/flink run -m yarn-cluster ./examples/batch/WordCount.jar

hdfs_flink_web

提交 spark 任务:

1
/opt/modules/spark/bin/spark-submit --master yarn --deploy-mode cluster --class org.apache.spark.examples.SparkPi /opt/modules/spark/examples/jars/spark-examples_2.12-3.2.2.jar 100

hdfs_spark_yarn

hive

hive 可通过 开源数据库客户端工具,dbeaver[4] 直接连接,注意需要填用户名,否则可能会因为权限问题无法执行 SQL

hdfs_hive_connect

实现

组件版本

hdfs - 3.3.2
knox - 1.6.1
hive - 3.1.2
flink - 1.15
spark - 3.2

其中 knox[5] 是大数据组件通用的网关服务,可以用于配置统一代理、身份认证、单点登录等,一般是刚搭建大数据集群的时候需要装,后续就不需要怎么管了。其他服务比较核心

hadoop

基本的安装和配置,参考网上的教程[6]做就行。为了能在一个镜像中同时支持单点和集群启动,dockerfile 中做了通过识别容器启动环境参数,进行不同的初始化和服务启动的功能:在容器的启动参数中指定 -e HDFS_START=hdfsstart / hdfsstartall,即可区分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
# Dockerfiles/emr/hdfs/scripts/hdfs-start.sh
# 单点启动 hdfs 服务脚本

## 服务启动指令(本地启动 namenode、datanode、resourcemanager)
./sbin/start-dfs.sh
./sbin/start-yarn.sh

# Dockerfiles/emr/hdfs/scripts/hdfs-start-all.sh
# 启动 hdfs 集群脚本

## 配置: /etc/hadoop/conf/workers
hadoop2
hadoop3

## 服务启动指令(主节点启动 namenode、resourcemanager,worker 节点启动 datanode、nodemanager)
./sbin/start-all.sh

knox

knox 主要是配置需要留意,大体分为 knox 本身的服务配置、网关配置 和 代理的服务配置

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
34
35
36
37
# knox配置
## /opt/modules/knox/conf/gateway-site.xml
### 禁用 ssl 和 身份认证,方便调试
<property>
<name>ssl.enabled</name>
<value>false</value>
</property>

<provider>
<role>identity-assertion</role>
<name>Default</name>
<enabled>disable</enabled>
</provider>

# 网关配置
## /opt/modules/knox/conf/topologies/sandbox.xml
### hdfs 和 yarn 地址,因为 namenode 和 knox 都部署在主节点,所以这里配的都是 localhost
<service>
<role>HDFSUI</role>
<url>http://localhost:50070</url>
<version>2.7.0</version>
</service>

<service>
<role>YARNUI</role>
<url>http://localhost:8088</url>
</service>

# 代理服务配置
## /opt/modules/knox/data/services/hdfsui/2.7.0/rewrite.xml
### 这里需要加个规则: 因为 hdfs 的 index.html 页面实际是一个 跳转页面(<a> 元素),而直接访问
### 这个地址会被链接到容器环境内部域名(hadoop1),而不是外部域名(localhost:8443)导致在外部访问跳转失败
### 因此一个最直接的解决方式就是将 index.html 直接链接到 dfshealth.html 让 knox 帮我们做这个跳转,保持外部域名(gateway.url)

<rule dir="OUT" name="HDFSUI/redirect" pattern="/index.html">
<rewrite template="{gateway.url}/hdfs/dfshealth.html"/>
</rule>

hive

hive 服务启动前,需要做初始化 mysql 的操作,涉及到两个细节:hive 初始化脚本 init-hive.sh 中,需要执行 schematool 进行元数据初始化;compose 文件中也要定义 主节点,也是 hive 启动的节点,需要依赖 mysql 容器(depends_on)

compose

各个组件都准备完成后,对 compose 配置文件的编写主要就是设置容器启动的环境变量了

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
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
version: "3.9"
services:
hadoop1:
image: ${HDFS_FULL_IMAGE}
hostname: hadoop1
environment:
# hdfs 主节点配置
- DEFAULTFS=hdfs://hadoop1:8020 # 主节点地址: 即 hadoop1 地址
- DFS_REPLICATION=2 # 两个 worker 节点
- RESOURCEMANAGER_HOSTNAME=hadoop1 # rm 节点: 依然是 hadoop1
- WORKERS=hadoop2,hadoop3 # worker 节点具体域名,会在 init-hdfs.sh 脚本中解析
- HDFS_START=hdfsstartall # hadoop 启动方式: 集群模式
# knox 配置
- KNOX_START=knoxstart # 是否启动
# hive 配置
- HIVE_START=hivestart # 是否启动
- mysql_host=mysql # mysql 配置,用于存储元数据
- mysql_port=3306
- mysql_db=hive
- mysql_user=root
- mysql_pwd=root_HADOOP_123
ports:
# 主节点需要开放各主要节点的端口
- "8443:8443"
- "8088:8088"
- "50070:50070"
- "10000:10000"
depends_on:
- hadoop2
- hadoop3
- mysql
hadoop2:
image: ${HDFS_FULL_IMAGE}
hostname: hadoop2
environment:
# hdfs worker 节点配置
- DEFAULTFS=hdfs://hadoop1:8020 # 主节点地址
- DFS_REPLICATION=2
- RESOURCEMANAGER_HOSTNAME=hadoop1
- WORKERS=hadoop2,hadoop3
- HDFS_START=hdfsnotstart # worker 节点不主动启动 hdfs,由主节点触发
hadoop3:
image: ${HDFS_FULL_IMAGE}
hostname: hadoop3
environment:
- DEFAULTFS=hdfs://hadoop1:8020
- DFS_REPLICATION=2
- RESOURCEMANAGER_HOSTNAME=hadoop1
- WORKERS=hadoop2,hadoop3
- HDFS_START=hdfsnotstart
mysql:
image: ${MYSQL_IMAGE}
ports:
- "33306:3306"
# mysql 节点配置
environment:
- ROOT_PASSWORD=root_HADOOP_123 # root 账号密码

提交镜像

在实践的过程中发现 基于 Dockerfile 在分享上也不是特别方便,比如新来的同学想使用 dev_full 完整开发镜像,他还需要在自己的电脑上先重新构建一次镜像。更好的方法还是通过镜像仓库直接分享镜像
因此后面把自己的镜像都提交到了 dockerhub 中,包括之前做的 easyconnect[7] 代理镜像、dev_full[8] 包含多种开发语言的开发镜像
构建方式: 通过 buildx[9] 工具构建

1
2
# 示例: 构建并提交 base 镜像,同时构建 arm 和 amd 版本
docker buildx build --platform linux/arm64,linux/amd64 --no-cache -f ./Dockerfiles/system/centos_base.Dockerfile -t dockerhub账号名/centos_base:v1.0 ./Dockerfiles/system --push

在 dockerhub 查看刚提交的镜像:
hdfs_dockerhub

扩展: 运行 easyconnect 镜像

1
2
3
4
5
6
7
8
# 使用 easyconnect 镜像
REPO=mzsmieli make run_rc
# 将下载 mzsmieli/centos_easyconnect:v1.0.0

# 完整指令
docker pull mzsmieli/centos_easyconnect:v1.0.0
docker run -it -d --privileged=true --platform linux/amd64 --hostname test_ec --name dev_ec -p 3389:3389 -p 7881:7881 mzsmieli/centos_easyconnect:v1.0.0 /usr/sbin/init
# vnc 默认密码: root/root_123

后言

坚信搞好属于自己的一套开发环境是学习任何新技术的基础,工欲善其事,必先利其器

这篇博客也仅仅是将个人习惯的开发环境 分享一下,每个人肯定都有自己的习惯,不存在谁比谁更好,只要能达到自己想要的学习效果,都是好方法。开发镜像也是,IDE 也是,开发语言也是。总是陷入对 世界上最好语言的争论,真的没必要

当然,在自己整完这些东西之后,再次感觉到 应该喘口气,思考自己想做的下个东西是什么了

资料

[1] 使用 Docker 快速部署 Spark + Hadoop 大数据集群

[2] git-spark-hadoop-docker

[3] 通过 Docker Compose 本地启动 zk 集群

[4] dbeaver

[5] knox官方文档

[6] Hadoop集群的部署(二)

[7] EasyConnect 代理工具容器化运行

[8] dev_full image

[9] docker buildx