데이터 엔지니어링(Deep Dive)

Simple Serverless Spark submit

직장인B 2025. 11. 29. 15:10

목표

 

👉🏻 docker를 이용하여 serverless 방식의 spark job submit을 해본다. 

 

 

Spark Cluster 준비

 

docker 정의된 호스트명을 사용할 수 있도록 host 파일을 수정해준다. 

127.0.0.1       spark-master spark-worker-1

 

그리고 적절한 spark image를 골라서 로컬에 spark cluster를 구성해준다. cluster는 docker compose로 구성한다. 

version: "3.9"

services:
  spark-master:
    image: spark:3.5.7-scala2.12-java11-python3-r-ubuntu
    container_name: spark-master
    hostname: spark-master
    command:
      [
        "/opt/spark/bin/spark-class",
        "org.apache.spark.deploy.master.Master",
        "--host", "spark-master",
        "--port", "7077",
        "--webui-port", "8080"
      ]
    environment:
      - SPARK_MASTER_PORT=7077
      - SPARK_MASTER_WEBUI_PORT=8080
    ports:
      - "7077:7077"
      - "8080:8080"
    volumes:
      - ./data:/data 
    networks:
      - spark-net

  spark-worker-1:
    image: spark:3.5.7-scala2.12-java11-python3-r-ubuntu
    container_name: spark-worker-1
    hostname: spark-worker-1
    depends_on:
      - spark-master
    command:
      [
        "/opt/spark/bin/spark-class",
        "org.apache.spark.deploy.worker.Worker",
        "spark://spark-master:7077"
      ]
    environment:
      - SPARK_WORKER_CORES=4
      - SPARK_WORKER_MEMORY=8G
      - SPARK_WORKER_PORT=7078
      - SPARK_WORKER_WEBUI_PORT=8081
    ports:
      - "8081:8081"
    volumes:
      - ./data:/data
    networks:
      - spark-net

networks:
  spark-net:
    driver: bridge

 

docker compose를 up 하면 cluster가 생성되고 아래처럼 spark cluster의 history 웹에 접근할 수 있다. master에 하나의 worker가 붙어있는 것을 볼 수 있다. 

 

 

Spark Submit 진행

cluster가 잘 동작하는지는 간단하게 확인할 수 있다. 요렇게 간단한 job 을 실행시켜본다. 

docker run --rm \
  --network serverlesssparksubmit_spark-net \
  spark:3.5.7-scala2.12-java11-python3-r-ubuntu \
  /opt/spark/bin/spark-submit \
    --master spark://spark-master:7077 \
    --deploy-mode client \
    --class org.apache.spark.examples.SparkPi \
    /opt/spark/examples/jars/spark-examples_2.12-3.5.7.jar \
    10

 

아래와 같은 출력이 확인되면 정상 실행된 것이다. 단, 이 경우 client 모드로 실행했으니 출력은 docker run을 실행한 작업 서버 쪽에서 출력이 되어야 한다. 

 

Pi is roughly 3.1418068314180685

 

client 모드의 경우 driver가 작업 서버(client) 쪽에 생겨나고, cluster 모드의 경우 cluster의 노드에 driver가 생긴다. driver는 SparkContext / SparkSession 와 같은 spark 객체를 생성하고 exectuor에 작업을 명령하는 역할을 한다. driver 또한 부하가 발생할 수 있기에 운영환경에서는 cluster 모드가 권장되지만, 작업서버 디스크에 있는 파일을 읽어야 하거나 하는 등의 로컬 작업이 있는 경우에는 client 모드를 사용할 수 있다. 

 

작업이 완료되면 깔끔하게 컨테이너도 사라져야 한다. 작업에 대한 히스토리는 spark cluster의 히스토리 서비스에 남는다. 

 

응용점

 

이러한 serverless 방식은 작업 서버의 환경에 구애받지 않고 docker 만 구비하면 적절한 이미지를 사용해 spark 작업을 할 수 있게 해준다는 점과 지속적인 배치 프로세스를 띄워 리소스를 잡아먹을 필요없다는 점 등의 강점이 있다. 

 

이와 같은 컨테이너 기반의 spark job submit 방식은 다양하게 응용될 수 있다. airflow에서 spark job을 실행시키는 방식도 이와 거의 유사하다.