麻雀虽小,五脏俱全。
GitHub 项目地址:bigdata-env
引子
我有两台树莓派。
凭借超高颜值,安安静静地摆在那里,就是超绝桌搭。担心没有实用性?有的兄弟,包有的。装上 JupyterLab,它是数据科学工作站;装上 Kali Linux,它是黑客界的瑞士军刀;装上 llama.cpp,它是你的私有 LLM 推理服务器。
你可能不屑一顾,这些事一台树莓派也能搞定,何必弄两台呢?看来只有做一些两台机器才能办到的事,才算物尽其用。因此,我计划部署一个大数据集群。部署大数据集群是个技术活,不要期待一开始就在硬件上部署。可以先在 Docker Compose 上跑通,再尝试硬件部署。
Note: 如果对装机过程感兴趣,可以参考我的博客《树莓派 5 装机指南》
一、集群功能
「大数据集群」是个宽泛的词儿。
装了 Spark 的,可以是大数据集群;装了 Spark + Hadoop 的,也可以是大数据集群。那么到底要装到什么程度呢?这取决于我们的需求。作为常年耕作在数据一线的工程师,我认为基础需求包括:
- 必须能分布式计算
- 必须能分布式存储
- 必须可以建分区表
- 必须能使用分布式机器学习库 pyspark.ml
- 必须有调度工具(当然 crontab 也算)
- 必须有 JupyterLab
我的目标是搭建一个满足这些需求的集群。当然,我们没有必要从零开始搭建,因为前人已经有很优秀的工作。只需要基于前人的工作做一些拓展,就能实现我们想要的功能。s1mplecc 大佬的《使用 Docker 快速部署 Spark + Hadoop 大数据集群》就是一个很棒的基础工作。
大佬已经实现了 Spark + Hadoop 集群,我只需要新增以下内容:
- 沿用一主(Master)二从(Worker)的配置
- 启用 Worker 节点的 DataNode 以支持数据同步
- 安装 Hive 环境
- 安装并初始化 miniconda3
- 安装与 Spark 版本配适的 Python 和 PySpark
- 安装 JupyterLab
主要增加了 Hive、JupyterLab 和 miniconda3。Hive 让我们更轻松地管理分区表;JupyterLab 提供了用于调试开发的浏览器界面;miniconda3 用作 Python 包管理。
二、稍作讲解
Docker Compose 使用 docker-compose.yml 文件定义了容器的环境变量、数据卷、网络、依赖关系等配置。并允许用户使用 Dockerfile 文件制作自定义镜像。这两个文件是本项目的核心,下面我将介绍这两个文件的具体作用。
Note: 完整部署代码见 GitHub 仓库:luochang212/bigdata-env
1)docker-compose.yml 文件
下面是 docker-compose.yml 文件:
services:
mysql:
image: mysql:8.0
# platform: linux/amd64
hostname: mysql
container_name: hive-mysql
networks:
- bigdata-base-network
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_DATABASE=hive_metastore
- MYSQL_USER=hive
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
ports:
- '3306:3306'
command: --default-authentication-plugin=mysql_native_password
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p${MYSQL_ROOT_PASSWORD}"]
timeout: 10s
retries: 3
interval: 10s
start_period: 20s
spark:
build:
context: ./
dockerfile: Dockerfile
image: spark-hadoop-hive:latest
# platform: linux/amd64
hostname: master
container_name: spark-hadoop-hive-master
networks:
- bigdata-base-network
depends_on:
mysql:
condition: service_healthy
environment:
- SPARK_MODE=master
- SPARK_RPC_AUTHENTICATION_ENABLED=no
- SPARK_RPC_ENCRYPTION_ENABLED=no
- SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no
- SPARK_SSL_ENABLED=no
- HIVE_DB_USER=hive
- HIVE_DB_PASSWORD=${HIVE_DB_PASSWORD}
volumes:
- ./share:/opt/share
ports:
- '8080:8080'
- '4040:4040'
- '7077:7077'
- '8088:8088'
- '8042:8042'
- '9870:9870'
- '19888:19888'
- '9083:9083'
- '10000:10000'
- '8888:8888'
command: bash /opt/start-master.sh
spark-worker-1:
image: spark-hadoop-hive:latest
# platform: linux/amd64
hostname: worker1
container_name: spark-hadoop-hive-worker-1
networks:
- bigdata-base-network
depends_on:
- spark
environment:
- SPARK_MODE=worker
- SPARK_MASTER_URL=spark://master:7077
- SPARK_WORKER_MEMORY=1G
- SPARK_WORKER_CORES=1
- SPARK_RPC_AUTHENTICATION_ENABLED=no
- SPARK_RPC_ENCRYPTION_ENABLED=no
- SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no
- SPARK_SSL_ENABLED=no
volumes:
- ./share:/opt/share
ports:
- '8081:8081'
command: bash /opt/start-worker.sh
spark-worker-2:
image: spark-hadoop-hive:latest
# platform: linux/amd64
hostname: worker2
container_name: spark-hadoop-hive-worker-2
networks:
- bigdata-base-network
depends_on:
- spark
environment:
- SPARK_MODE=worker
- SPARK_MASTER_URL=spark://master:7077
- SPARK_WORKER_MEMORY=1G
- SPARK_WORKER_CORES=1
- SPARK_RPC_AUTHENTICATION_ENABLED=no
- SPARK_RPC_ENCRYPTION_ENABLED=no
- SPARK_LOCAL_STORAGE_ENCRYPTION_ENABLED=no
- SPARK_SSL_ENABLED=no
volumes:
- ./share:/opt/share
ports:
- '8082:8081'
command: bash /opt/start-worker.sh
networks:
bigdata-base-network:
driver: bridge
volumes:
mysql_data:
该文件创建了四个容器、一个网络、一个数据卷。
- 容器:
mysql:用于存储 Hive 表的元数据spark:主节点spark-worker-1:工作节点 1 号spark-worker-2:工作节点 2 号
- 网络:
bigdata-base-network:启用桥接(bridge)模式
- 数据卷:
mysql_data:mysql容器挂载的数据卷
2)Dockerfile 文件
下面是 Dockerfile 文件:
FROM --platform=$BUILDPLATFORM docker.io/bitnami/spark:3
LABEL maintainer="luochang212"
LABEL description="Docker image with Spark (3.3.0) and Hadoop (3.3.2), based on bitnami/spark:3. \
For more information, please visit https://github.com/luochang212/bigdata-env."
USER root
ENV HADOOP_HOME="/opt/hadoop"
ENV HADOOP_CONF_DIR="$HADOOP_HOME/etc/hadoop"
ENV HADOOP_LOG_DIR="/var/log/hadoop"
ENV HIVE_HOME="/opt/hive"
ENV HIVE_CONF_DIR="$HIVE_HOME/conf"
ENV MINICONDA_HOME="/opt/miniconda3"
ENV PATH="$MINICONDA_HOME/bin:$HADOOP_HOME/sbin:$HADOOP_HOME/bin:$HIVE_HOME/bin:$PATH"
WORKDIR /opt
RUN apt-get update && apt-get install -y openssh-server
# Create spark user for Spark services
RUN useradd -r -m -s /bin/bash spark && \
usermod -aG sudo spark
RUN ssh-keygen -t rsa -f /root/.ssh/id_rsa -P '' && \
cat /root/.ssh/id_rsa.pub >> /root/.ssh/authorized_keys
# RUN curl -OL https://archive.apache.org/dist/hadoop/common/hadoop-3.3.2/hadoop-3.3.2.tar.gz
RUN curl -OL https://mirrors.huaweicloud.com/apache/hadoop/common/hadoop-3.3.2/hadoop-3.3.2.tar.gz
RUN tar -xzvf hadoop-3.3.2.tar.gz && \
mv hadoop-3.3.2 hadoop && \
rm -rf hadoop-3.3.2.tar.gz && \
mkdir /var/log/hadoop
# Install Hive
RUN curl -OL https://mirrors.huaweicloud.com/apache/hive/hive-3.1.3/apache-hive-3.1.3-bin.tar.gz
RUN tar -xzvf apache-hive-3.1.3-bin.tar.gz && \
mv apache-hive-3.1.3-bin hive && \
rm -rf apache-hive-3.1.3-bin.tar.gz
# Install Miniconda
RUN curl -OL https://repo.anaconda.com/miniconda/Miniconda3-latest-Linux-x86_64.sh && \
bash Miniconda3-latest-Linux-x86_64.sh -b -p $MINICONDA_HOME && \
rm -rf Miniconda3-latest-Linux-x86_64.sh && \
. $MINICONDA_HOME/bin/activate && \
conda init --all
# conda config --set auto_activate_base false
# Install JupyterLab and common data science packages
RUN /bin/bash -c "source $MINICONDA_HOME/bin/activate && \
conda config --set channel_priority flexible && \
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/main && \
conda tos accept --override-channels --channel https://repo.anaconda.com/pkgs/r && \
conda install -n base -y python=3.9 jupyterlab ipykernel && \
pip install --no-cache-dir pyspark==3.3.0 && \
conda clean -a -y"
# Install MySQL connector for Hive metastore
RUN curl -OL https://repo1.maven.org/maven2/com/mysql/mysql-connector-j/8.0.33/mysql-connector-j-8.0.33.jar && \
mv mysql-connector-j-8.0.33.jar $HIVE_HOME/lib/mysql-connector-java.jar
RUN mkdir -p /root/hdfs/namenode && \
mkdir -p /root/hdfs/datanode
COPY config/* /tmp/
RUN mv /tmp/ssh_config /root/.ssh/config && \
mv /tmp/hadoop-env.sh $HADOOP_CONF_DIR/hadoop-env.sh && \
mv /tmp/hdfs-site.xml $HADOOP_CONF_DIR/hdfs-site.xml && \
mv /tmp/core-site.xml $HADOOP_CONF_DIR/core-site.xml && \
mv /tmp/mapred-site.xml $HADOOP_CONF_DIR/mapred-site.xml && \
mv /tmp/yarn-site.xml $HADOOP_CONF_DIR/yarn-site.xml && \
mv /tmp/workers $HADOOP_CONF_DIR/workers && \
mv /tmp/hive-site.xml $HIVE_CONF_DIR/hive-site.xml
COPY start-master.sh /opt/start-master.sh
COPY start-worker.sh /opt/start-worker.sh
COPY set-conda-env.sh /opt/set-conda-env.sh
COPY set-jupyter-env.sh /opt/set-jupyter-env.sh
COPY jupyter_server_config.py /opt/jupyter_server_config.py
RUN chmod +x /opt/start-master.sh && \
chmod +x /opt/start-worker.sh && \
chmod +x $HADOOP_HOME/sbin/start-dfs.sh && \
chmod +x $HADOOP_HOME/sbin/start-yarn.sh && \
chmod +x /opt/set-conda-env.sh && \
chmod +x /opt/set-jupyter-env.sh && \
chmod +x /opt/jupyter_server_config.py
RUN hdfs namenode -format
RUN sed -i "1 a /etc/init.d/ssh start > /dev/null &" /opt/bitnami/scripts/spark/entrypoint.sh
ENTRYPOINT [ "/opt/bitnami/scripts/spark/entrypoint.sh" ]
CMD [ "/opt/bitnami/scripts/spark/run.sh" ]
使用 Dockerfile 文件可以制作自定义镜像,从而创建自定义容器。从 docker-compose.yml 文件可以看出 spark、spark-worker-1、spark-worker-2 三个容器共用一个 Dockerfile 文件。也就是说,这三个容器的镜像是相同的,只是环境变量和启动命令有所不同。
本
Dockerfile的主要工作是软件安装,它在bitnami/spark:3镜像的基础上安装了 Hadoop、Hive、miniconda3、JupyterLab 等软件。
三、本地运行
如果你希望在本地运行本文创建的大数据集群,请参考以下步骤。
1)克隆仓库
git clone https://github.com/luochang212/bigdata-env.git
cd bigdata-env
2)配置 .env 文件
以 .env.example 为模板,创建你的 .env 文件:
cp .env.example .env
编辑 .env 文件,改成你的密码(可选):
MYSQL_ROOT_PASSWORD=[your-mysql-root-password]
MYSQL_PASSWORD=[your-mysql-password]
HIVE_DB_PASSWORD=[your-hive-db-password]
⚠️ 注意:
- 若修改
.env中MYSQL_PASSWORD的密码,需要将hive-site.xml中javax.jdo.option.ConnectionPassword的密码同步修改为你的新密码- 由于
hive-site.xml无法使用.env配置环境变量,因此该文件中依然包含明文密码。请注意不要在上传hive-site.xml文件时泄漏密码
3)启动 docker 服务
启动服务之前,请确保已经安装并启动了 docker 服务。中国大陆地区需要额外配置一下镜像源,否则无法正常下载镜像文件。配置镜像源的方法在 《耶是 ClickHouse!我们有救了!!》 一文中有详细介绍。
⚠️ 注意:
为避免脚本在 docker 中运行出错,Windows 用户 请先运行以下脚本:
.\convert.ps1此脚本 将项目下 Windows 风格的换行符转换为 Unix 风格的换行符。
构建镜像:
docker compose build --no-cache
启动所有服务:
docker compose up -d
完全启动大约需要 30 秒,如果觉得等待无聊,可以打印实时日志:
docker compose logs -f
4)打开 JupyterLab
在浏览器打开 JupyterLab:http://localhost:8888/lab
这里需要输入 token 以获得访问权限,执行以下命令获取 token:
docker compose exec -it spark jupyter lab list
进入 JupyterLab 后,使用 JupyterLab 的终端即可访问大数据环境。
# 验证 Hive 服务可用
hive -e 'SHOW DATABASES;'
# 确认 Spark 服务可用
pyspark
# 也可启动 Spark 交互式命令行
spark-shell
