data engineering

make simple spark docker image

qkqhxla1 2020. 10. 9. 22:30

이전 글에서 spark관련 etl을 만들었다. 하루마다 돌려야 하는 배치잡인데 내가 스파크를 설치한 서버에서 크론탭을 걸어서 돌리면 나한테는 가장 편하겠지만 이러면서버에 너무 종속적이다. 스파크가 설치된 idc서버가 교체가 일어난다던지, 하면 스파크를 다시 새로 깔고 jar들을 다운받고 세팅을 다시 처음부터 끝까지 다시 해야 한다. 

 

어쨌든 요즘은 쿠버네티스로 자원 컨트롤링을 하고 도커 쓰는건 대부분 기본인 시대이기에 도커 이미지로 만들어보기로 했다.

 

처음에 이미 만들어진 도커 이미지를 사용할까 생각했는데 ex) https://hub.docker.com/r/bitnami/spark/

저번에도 적었지만 스파크 3버전에 하둡 3.2버전을 동시에 충족하는 이미 만들어진 스파크 도커 이미지가 없는것같아서 그냥 처음부터 새로 만들었다.

 

내가 만든 도커 이미지의 프로젝트 구조는 아래와 같다,

build.sh 에는 도커 이미지 빌드를 위한 내용 말고는 다른 내용이 없다. 아래와 같다.

#! /bin/bash

REPOSITORY="도커_허브_주소/spark-backup"
TAG="v0.1"

docker build -t $REPOSITORY:$TAG .
docker push $REPOSITORY:$TAG

docker build -t $REPOSITORY:latest .
docker push $REPOSITORY:latest

Dockerfile은 아래와 같다.

FROM ubuntu:18.04  # 우분투에 설치할거다.
MAINTAINER qkqhxla1

RUN mkdir -p /pang  # 도커의 우분투 이미지 안에 /pang디렉터리를 만든다.
COPY spark /pang/spark  # 위 사진 보면 알겠지만 내가 jar들을 다운받은 스파크는 통째로 spark폴더 안에 있는데, 이걸 /pang/spark로 복사해준다.

RUN apt-get update && \
    apt-get install libsasl2-modules libsasl2-dev python python-pip openjdk-8-jdk -y  # spark구동을 위해 필요한 것들, jdk라던지, pip라던지 등등을 설치해준다.

RUN pip install -r /pang/spark/requirements.txt  # pip로 필요한 모듈을 설치해준다.

CMD /pang/spark/mongo_backup.sh  # mongo_backup.sh를 실행시킨다.

mongo_backup.py와 mongo_backup.sh는 전 글과 같다.

 

내 환경을 간단하게 다시 적자면 x.x.x.x서버 한대에 master와 worker가 한대씩 standalone으로 돌고 있다. 그리고 나는 y.y.y.y에서 x.x.x.x로 접속하는 상황인데 문제는 y.y.y.y에서 spark-submit을 직접 실행시키면 제대로 동작한다. 근데 한번 도커로 말아서 y.y.y.y에서 실행하면 동작을 안한다. 

대충 이런 상황인데.. 계속 executor가 스파크 서버에서 생겼다가 죽었다가 하는데 히스토리 서버에서 에러 코드를 보면 

Caused by: java.io.IOException: Failed to connect to 0c08d09a1e49:38001

요런 에러가 뜨고 이것저것 찾아보니 아래 글이 나왔다.

https://stackoverflow.com/questions/52122942/why-do-my-spark-executors-continuously-start-and-exit

 

에러코드 중간의 0c08d09a1e49는 내가 만든 도커 이미지 이름이고 스파크 서버에서 다시 내 도커로 들어오는게 문제가 있다는 소리이다. 그리고 스택오버플로우 링크를 읽어보면 포트 포워딩 문제같은데.. 일단 conf에 저기 나온대로 3개의 포트를 내가 원하는 포트로 나가게끔 설정했다.

 

spark-defaults.conf

-----------------------------------

spark.blockManager.port    38000

spark.driver.port          38001

spark.ui.port              38002

-----------------------------------

 

이러고 도커 실행시 포트 38000,38001,38002 포트들을 오픈해도 안되었는데(계속 위와 같은 에러가 뜸) 단순하게 Dockerfile말고 좀더 세부적인 도커 네트워크 설정이 필요한것 같다. 왜냐하면 단순하게 도커 실행시 클라이언트의 네트워크를 사용하도록. docker run --network host b7f9f4cb7865 처럼 옵션을 주니 해결이 되긴 했기 때문이다. 

 

https://serverfault.com/questions/752433/how-to-configure-spark-client-running-in-a-docker-container-for-two-way-communic 

얘를 읽어보면 내가 생각한것처럼 도커가 있음으로서 네트워크 레이어가 몇개가 중간에 더 끼게 되는데 이게 스파크에서 잘 resolving이 안되는것 같다.

 

도커로 스파크 클러스터들을 구성하는 글 : https://towardsdatascience.com/diy-apache-spark-docker-bb4f11c10d24 을 읽어보고(유용했음) 다른 글들도 읽어봤는데 뭔가 완벽하게 이해하고 해결한 느낌이 아닌데 추가로 더 알게되면 글 내용을 추가함.

성공 : qkqhxla1.tistory.com/1138