이번에는 Spark Cluster를 하나의 머신에서 간편하게 구축하는 과정을 기록하려 합니다.
아래 표는 사용 환경입니다.
하지만 docker 와 docker-compose 그리고 os 버젼은 컨테이너화 과정이기 때문에 큰 영향은 없을 것입니다.
type | version |
OS | Ubuntu 20.04 |
docker | Docker version 23.0.1 |
docker-compose | version 1.27.4 |
앞서 언급했듯이 docker-compose를 통하여 간편히 하나의 머신에서 spark master와 worker 두개를 띄울 것입니다.
이 환경은 production, 즉 운영에서 쓰이기에는 무리가 있습니다.
spark의 concept부터가 여러 대의 머신의 memory를 사용하여 대용량의 데이터를 처리하는 것이기 때문에, 하나의 머신에서 spark를 운영하는 것은 의미가 없기 때문이죠...
하지만 개발 버젼으로써의 테스트 환경을 구축한다는 점!
그리고 spark에 대해 좀 더 알아가기 위해서는 이보다 더 좋은 기본 실습은 없는 것 같습니다 🧐
또한 아래와 같이 cluster image, spark base image 등등 만들 필요 없이 bitnami 이미지를 활용한다면 더욱 더 쉽게 spark 환경을 구축할 수 있지만 이 또한 공부 차원에서 어떻게 docker 이미지를 만들고, spark architecture 구성에 대해 이해하는데 도움이 될것입니다.
자, 그럼 시작해 보겠습니다!
1. Dockerfile 작성
1-1. Cluster base image (cluster-base.Dockerfile)
가장 기본이 되는 cluster-base 이미지 입니다.
이 이미지를 활용하여 단순히 shared_workspace를 docker volume으로 공유를 하여 이 위에 spark 이미지들과 jupyter 이미지를 띄울 것입니다. 마치 실제 운영환경에서의 HDFS 위에 spark를 올리듯이 구성을 하는 예제입니다. 🤔
cluster의 base image는 8-jre-slim 입니다. spark 가 jvm 환경에서 돌아가며, java 를 linux os 이미지에서 설치하는 것보다 조금이라도 간편하게 docker 공식 사이트에서 배포되는 java runtime environment 이미지를 씁니다.
ARG debian_buster_image_tag=8-jre-slim
FROM openjdk:${debian_buster_image_tag}
ARG shared_workspace=/opt/workspace
RUN mkdir -p ${shared_workspace} && \
apt-get update -y && \
apt-get install -y python3 && \
ln -s /usr/bin/python3 /usr/bin/python && \
rm -rf /var/lib/apt/lists/*
ENV SHARED_WORKSPACE=${shared_workspace}
# -- Runtime
VOLUME ${shared_workspace}
CMD ["bash"]
1-2. Spark base image (spark-base.Dockerfile)
위 cluster base image를 기반으로 spark를 다운받고, 압축을 해제하고, 환경변수를 셋팅합니다.
이미 위 cluster-base가 jre를 기반으로 한 이미지이기 때문에 jvm설치가 필요없겠죠!!!! 😃
FROM cluster-base
ARG spark_version # will be passed through the command line in bash
ARG hadoop_version # will be passed through the command line in bash
RUN apt-get update -y && \
apt-get install -y curl && \
curl https://archive.apache.org/dist/spark/spark-${spark_version}/spark-${spark_version}-bin-hadoop${hadoop_version}.tgz -o spark.tgz && \
tar -xf spark.tgz && \
mv spark-${spark_version}-bin-hadoop${hadoop_version} /usr/bin/ && \
mkdir /usr/bin/spark-${spark_version}-bin-hadoop${hadoop_version}/logs && \
rm spark.tgz
ENV SPARK_HOME /usr/bin/spark-${spark_version}-bin-hadoop${hadoop_version}
ENV SPARK_MASTER_HOST spark-master
ENV SPARK_MASTER_PORT 7077
ENV PYSPARK_PYTHON python3
# -- Runtime
WORKDIR ${SPARK_HOME}
1-3. Spark master image (spark-master.Dockerfile)
Dockerfile에서의 expose는 이 이미지가 해당 포트를 외부에 개방을 할 것이다 라는 뜻이다.
이 이미지에서 port를 expose 하였다고 단순히 컨테이너를 실행할 때 호스트랑 연결이 되지 않는다.
필히 docker run -p ${host_port}:${container_port} 를 통하여 이미지에서 개방한 포트와 host_port를 연결해 주어야 한다!
(dockerfile가 아직 익숙하지 않은 분들을 위해 😗)
spark_master_web_ui 는 spark에서 제공해주는 마스터의 web monitoring 페이지를 보기 위하여 띄어주는 것이다.
FROM spark-base
# -- Runtime
ARG spark_master_web_ui=8080
EXPOSE ${spark_master_web_ui}
EXPOSE ${SPARK_MASTER_PORT} # spark base 이미지에서 SPARK_MASTER_PORT 환경변수를 셋팅해주었다.
CMD bin/spark-class org.apache.spark.deploy.master.Master >> logs/spark-master.out
1-4. Spark worker image (spark-worker.Dockerfile)
FROM spark-base
# -- Runtime
ARG spark_worker_web_ui=8081
EXPOSE ${spark_worker_web_ui}
CMD bin/spark-class org.apache.spark.deploy.worker.Worker spark://${SPARK_MASTER_HOST}:${SPARK_MASTER_PORT} >> logs/spark-worker.out
1-5. Jupyter lab image (jupyterlab.Dockerfile)
간단히 코드를 작성하기 위한 jupyter lab 이미지이다. 물론 jupyter lab image가 필수인 것은 아니다. master container 안에 들어가 spark-submit 명령어를 실행하여도 되고, 컨테이너 밖에서 cluster 또는 clinet 모드로 spark-job을 실행할 수 있지만, 여간 까다로운게 아니다.
FROM cluster-base
ARG spark_version
ARG jupyterlab_version
RUN apt-get update -y && \
apt-get install -y python3-pip && \
pip3 install wget pyspark==${spark_version} jupyterlab==${jupyterlab_version}
# -- Runtime
EXPOSE 8888
WORKDIR ${SHARED_WORKSPACE}
CMD jupyter lab --ip=0.0.0.0 --port=8888 --no-browser --allow-root --NotebookApp.token=
2. Docker images 빌드
2-1. build.sh
# -- Software Stack Version
SPARK_VERSION="3.0.0"
HADOOP_VERSION="2.7"
JUPYTERLAB_VERSION="2.1.5"
# -- Building the Images
echo "############################################# building cluster-base #############################################"
docker build \
-f cluster-base.Dockerfile \
-t cluster-base .
echo "############################################# building spark-base #############################################"
docker build \
--build-arg spark_version="${SPARK_VERSION}" \
--build-arg hadoop_version="${HADOOP_VERSION}" \
-f spark-base.Dockerfile \
-t spark-base .
echo "############################################# building spark-master #############################################"
docker build \
-f spark-master.Dockerfile \
-t spark-master .
echo "############################################# building spark-worker #############################################"
docker build \
-f spark-worker.Dockerfile \
-t spark-worker .
echo "############################################# building jupyter #############################################"
docker build \
--build-arg spark_version="${SPARK_VERSION}" \
--build-arg jupyterlab_version="${JUPYTERLAB_VERSION}" \
-f jupyterlab.Dockerfile \
-t jupyterlab .
2. docker-compose 작성 및 실행
3-1. Create docker-compose.yml
(docker-compose의 포트 개념이 아직 익숙하지 않은 분들을 위해...🥲)
앞에 spark master image에서 docker run -p 를 통하여 이미지에서 명시한 port를 연결시켜주어 한다고 하였다.
docker-compsoe에서는 아래의 ports 섹션을 통하여 쉽게 연결시킬 수 있다.
version: "3.6"
volumes:
shared-workspace:
name: "hadoop-distributed-file-system"
driver: local
services:
jupyterlab:
image: jupyterlab
container_name: jupyterlab
ports:
- 8888:8888
volumes:
- shared-workspace:/opt/workspace
spark-master:
image: spark-master
container_name: spark-master
ports:
- 4040:8080
- 7077:7077
volumes:
- shared-workspace:/opt/workspace
spark-worker-1:
image: spark-worker
container_name: spark-worker-1
environment:
- SPARK_WORKER_CORES=1
- SPARK_WORKER_MEMORY=512m
ports:
- 4041:8081
volumes:
- shared-workspace:/opt/workspace
depends_on:
- spark-master
spark-worker-2:
image: spark-worker
container_name: spark-worker-2
environment:
- SPARK_WORKER_CORES=1
- SPARK_WORKER_MEMORY=512m
ports:
- 4042:8081
volumes:
- shared-workspace:/opt/workspace
depends_on:
- spark-master
3-2. docker-compose up
먼저 build.sh 에 execution 권한을 주고 이미지를 한번에 build합니다.
그리고 만들어진 이미지로 docker-compose up을 통하여 실행합니다.
chmod +x ./build.sh
./build.sh
docker-compose up
3-3. spark test
밑 링크를 통해서 jupyterlab 과 열어놓은 spark web ui 들을 볼 수 있으며,
spark master 웹 UI 를 보면 worker 들이 잘 등록 되어있는 것을 확인할 수 있다.
jupyterlab: http://localhost:8888
마스터 노드: http://localhost:4040
워커 노드 1: http://localhost:4041
워커 노드 2: http://localhost:4042
스파크가 잘 작동하는지 스파크 프로그래밍 예제를 jupyterlab에서 실행해보자
from pyspark.sql import SparkSession
spark = SparkSession.\
builder.\
appName("pyspark-notebook").\
master("spark://spark-master:7077").\
config("spark.executor.memory", "512m").\
getOrCreate()
import wget
url = "https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data"
wget.download(url)
data = spark.read.csv("iris.data")
data.show(n=5)
'Data Engineer > spark' 카테고리의 다른 글
[Spark] 클러스터 구축 docker swarm, standalone (3/5) (0) | 2023.08.27 |
---|---|
[Spark] 로컬에서 돌려보기, standalone (1/5) (0) | 2022.12.27 |