最近同同事 们一起在学习Spark,为了方便同事们的使用,也为了减少不必要的安装spark的坑,特意做了一个自启动SSH服务的单机版本的Spark集群,供大家学习和使用。
如果只想看如何使用,可以跳到第三节直接运行。
从官网可以看到,spark 已经为大家提供好了很多的命令进程的启动脚本,我们就选用最简单的 ${SPARK_HOME}/sbin/start-all.sh
脚本
基础镜像
为了今后更加方便的扩展,特意的先做了一个基础的spark镜像,下载和配置了各种spark所需要的运行环境(Java 版本、Scala版本、Python3版本)。
废话不多少,先上基本的spark docker 文件 base.dockerfile 代码:
FROM openjdk:8u212-jdk-alpine3.9
# Installing IPython
ENV DAEMON_RUN=true
ENV SPARK_VERSION=2.4.5
ENV HADOOP_VERSION=2.7
ENV SCALA_VERSION=2.12.4
ENV SBT_VERSION=0.13.15
ENV SCALA_HOME=/usr/share/scala
RUN apk add --no-cache --virtual=.build-dependencies wget ca-certificates && \
apk add --no-cache bash curl jq && \
cd "/tmp" && \
wget --no-verbose "https://downloads.typesafe.com/scala/${SCALA_VERSION}/scala-${SCALA_VERSION}.tgz" && \
tar xzf "scala-${SCALA_VERSION}.tgz" && \
mkdir "${SCALA_HOME}" && \
rm "/tmp/scala-${SCALA_VERSION}/bin/"*.bat && \
mv "/tmp/scala-${SCALA_VERSION}/bin" "/tmp/scala-${SCALA_VERSION}/lib" "${SCALA_HOME}" && \
ln -s "${SCALA_HOME}/bin/"* "/usr/bin/" && \
apk del .build-dependencies && \
rm -rf "/tmp/"*
#Scala instalation
RUN export PATH="/usr/local/sbt/bin:$PATH" && apk update && apk add ca-certificates wget tar && mkdir -p "/usr/local/sbt" && wget -qO - --no-check-certificate "http://dl.bintray.com/sbt/native-packages/sbt/$SBT_VERSION/sbt-$SBT_VERSION.tgz" | tar xz -C /usr/local/sbt --strip-components=1 && sbt sbtVersion
# Python instalation
RUN apk add --no-cache python3 && ln -s $(command -v python3) /usr/bin/python
# Note: this is needed when you use Python 3.3 or greater
ENV PYTHONHASHSEED 1
RUN wget --no-verbose https://mirrors.tuna.tsinghua.edu.cn/apache/spark/spark-${SPARK_VERSION}/spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz && tar -xvzf spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz \
&& mv spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION} spark \
&& rm spark-${SPARK_VERSION}-bin-hadoop${HADOOP_VERSION}.tgz
ENV SPARK_HOME /spark
构建好的 Tag 为 5200710/spark:spark-base-2.4.5
.
spark-standalone 镜像
然后在构建好的基础镜像上,安装启动ssh服务和spark的start-all.sh 脚本所需要的环境。
这里比较坑的点在于 docker 镜像内部,不可以直接的通过 rc-update之类的系统服务启动,网上试了很多种启动sshd服务的方法,发现还是
/usr/sbin/sshd -D &
能靠谱的在docker容器启动的时候启动ssh服务。
因为通过 start-all 脚本启动,必定需要先启动ssh服务,然后配置 root@localhost
的免密验证。所以 standalone.dockerfile 相对于前面提到的spark的基础只是增加了部分安装openssh 服务的依赖和启动start-all
脚本的所需要的执行依赖。
FROM 5200710/spark:spark-base-2.4.5
ENV SPARK_MASTER_PORT 7077
ENV SPARK_MASTER_WEBUI_PORT 8080
ENV SPARK_WORKER_WEBUI_PORT 8081
RUN apk --no-cache add procps coreutils openssh
RUN mkdir -p /root/.ssh && \
chmod 700 /root/.ssh/ && \
ssh-keygen -A
EXPOSE 8080 7077 6066
ENV PYSPARK_PYTHON python3
COPY ./entrypoint.sh /entrypoint.sh
ENTRYPOINT [ "/entrypoint.sh" ]
CMD [ "-d" ]
procps 和 coreutils 等依赖是由于后续的start-all.sh 脚本中有些命令需要依赖这两个包执行。
ssh-keygen -A
命令是为了预先生成启动 ssh服务所需要的所有 host_key.
对于挂载点运行的启动脚本 entrypoint.sh
内容如下:
#!/usr/bin/env bash
# Exit immediately if a command exits with a non-zero exit status.
set -e
# Install custom python package if requirements.txt is present
[ -e "/requirements.txt" ] && ${command-v pip3} install --user -r /requirements.txt
# you can login with publishkey if don't change the password(confuse)
echo "root:${ROOT_PASSWORD:=admin}" | chpasswd
sed -i "s/#PermitRootLogin.*/PermitRootLogin yes/g" /etc/ssh/sshd_config
# generate the publishkey and privatekey for passwordless login
[ ! -e ~/.ssh/id_rsa ] && ssh-keygen -t rsa -N "" -f ~/.ssh/id_rsa
cat ~/.ssh/id_rsa.pub >~/.ssh/authorized_keys
# deamon start sshd service
/usr/sbin/sshd -D &
# 指定一个Slave和Java变量
echo "localhost" >${SPARK_HOME}/conf/slaves
echo "JAVA_HOME=${JAVA_HOME}" >${SPARK_HOME}/conf/spark-env.sh
${SPARK_HOME}/sbin/start-all.sh
if [[ $1 == "-d" ]]; then
tail -f ${SPARK_HOME}/logs/*.out
# while true; do sleep 1000; done
fi
exec "$@"
对entrypoint.sh
中的部分语句做下解释:
- 脚本的第一部分,是提供一个方式用于便于在容器运行的时候,能够增加额外的python依赖
- 第二部分在于改变容器内的root用户密码(一定要做 !!!)。因为如果不修改默认的alpine的root密码的话,后续就算你提供了正确的PublicKey,仍然无法免密登录。(我也不填清楚 为啥??)可以通过传入
ROOT_PASSWORD
环境变量来自定义root用户密码(默认为admin)。 - 第三部分对于公钥存在的检查,目的在于提供一个方式,便于自己提供对应的公钥和私钥给容器
后面的就是根据spark官网指定下worker的列表,这里只启动一个,所以写了一次 localhost
. 主动的声明下JAVA_HOME 路径
镜像运行方式
有需要的可以根据前面的教程重新自定义编排一个。当然也可以直接使用我已经编译好的镜像。
命令行的使用方式:
docker run --rm -it -e ROOT_PASSWORD='admin' -p 8080:8080 -p 8081:8081 -p 7077:7077 -p 2222:22 5200710/spark:spark-standalone-2.4.5 bash
docker-compse 的方式
version: "3.7"
services:
spark-standalone:
image: 5200710/spark:spark-standalone-2.4.5
ports:
- "8080:8080"
- "8081:8081"
- "7077:7077"
- "2222:22"
# environment:
# - "ROOT_PASSWORD=admin"
下载文件之后,在所在文件的目录下通过 docker-compose up -d
方式启动。
启动成功之后,可以通过 http://localhost:8080 访问单机版本 spark集群的UI界面。
更多镜像的细节可以访问 这里 。
如果觉得对你有帮助,实不相瞒想要个赞👍