[K8S-SPARK 1부] spark-on-k8s-operator를 통한 쿠버네티스에서 Spark Job 실행 환경 만들기

NewNewDaddy·2023년 12월 22일
0

SPARK

목록 보기
6/16
post-thumbnail
post-custom-banner

Spark-on-K8S 시리즈 목차

0. INTRO

  • Spark Job을 운영할 수 있는 환경을 쿠버네티스상에 만드는 시도를 조금씩 해왔었다. 유튜브도 보고, 블로그도 참고하고...... 보통 웬만한 도전과제들은 이미 나보다 먼저 해온 사람들이 있었고 이 과정을 감사히 영상이나 글로 남겨주신 분들도 제법 계셔서 큰 어려움 없이 해결을 해왔었던 것 같다.
  • Spark on Kubernetes 역시 그럴 것이라 생각했다. 검색해보면 이미 이와 관련된 블로그 글들도 많았고 유튜브 영상들도 볼만한게 제법 있어 마음만 먹으면 금방 구축해서 내가 원하는 Pyspark 코드를 실행시킬 수 있겠구나 생각했다. 하지만 생각보다 쉽지 않았고 apache spark 압축파일내에 존재하는 기본 샘플 코드인 원주율 구하기(pi.py)만 실행하고 끝나는 영상들이 대부분이었다.
  • 물론 Pyspark를 실행할 수 있는 환경이 만들어진 Jupyter Notebook 이미지를 Deployment, Service, Ingress들과 잘 엮어서 실행하여 Jupyter Notebook 환경에서 Spark Job을 처리할 수 도 있을 것이다. 하지만 그렇게 된다면 이미 떠있는 Pod가 2개면 2개, 4개면 4개의 리소스로 가용 자원이 한정이 되기 때문에 내가 생각하던 그림은 아니었다.
  • 내가 최종적으로 생각한 그림은 이런 것이었다. Spark job 실행시 Driver Pod가 뜨고 그 이후 해당 코드 실행에 필요한 리소스와 비례하게 Executor Pod가 떠서 Spark 작업을 원활히 처리한다.
  • AWS 환경이었다면 EKS 클러스터에서 EMR on EKS이라는 서비스를 어느정도 패키징해서 제공해주고 있기 때문에 그리 어렵지 않게 내가 원하는 방식으로 Spark 작업이 처리되는 환경을 구축할 수 있었을 것이다. 하지만 현재는 NCloud의 NKS 환경에서 EMR on NKS느낌으로 서비스를 구축하여야 했기 때문에 더 많은 노력과 생각과 시간들이 들어갔다.
  • Spark on Kubernetes 환경을 나름대로 구성해나가는 과정을 4부에 걸쳐서 다뤄볼 생각이며 Spark Job의 최종적인 동작 형태 및 기능은 아래와 같도록 하는 것을 목표로 한다.
    1. Kubernetes Native한 Spark 환경을 구축하며 작업 실행시 Driver Pod가 실행되고 Executor Pod가 가변적으로 뜨면서 작업을 처리하고 끝나면 없어진다.
    2. 내가 작성한 Custom한 Pyspark script가 실행되어야 한다.
    3. Pyspark script를 실행하여 NCloud Object Storage 혹은 AWS S3 Bucket에 정제된 Dataframe을 parquet 혹은 csv 파일 형태로 저장될 수 있어야 한다.

1. K8S-Spark 환경 구축

  • 쿠버네티스에 Spark 실행 환경을 구축하기 위한 Helm 차트에는 크게 Bitnami에서 지원해주는 Spark, GCP에서 지원해주는 spark-operator 두 가지가 있다고 생각된다.(물론 더 있을 수 있지만 현재로선 더 찾아보진 않았다.)

    1. Bitnami-Spark
    2. GoogleCloudPlatform의 spark-on-k8s-operator
  • 해당 글에서는 2번의 spark-on-k8s-operator Helm Chart를 사용하여 환경 구성을 해볼것이다.

    
    1. Helm Repo Add
    
      > helm repo add spark-operator https://googlecloudplatform.github.io/spark-on-k8s-operator
    
    2. Helm을 이용한 설치
    
      > helm install spark spark-operator/spark-operator \
        --set webhook.enable=true \
        --set webhook.port=443
    
    3. 설치 확인
       - init pod가 하나 뜨고 Completed되면 spark-operator가 뜨면서 Running 상태로 되면 설치가 잘 된것이다.
    
      > kubectl get all
    
        NAME                                          READY   STATUS      RESTARTS   AGE
        pod/spark-spark-operator-58bf8d4cb-m74fp      1/1     Running     0          27s
        pod/spark-spark-operator-webhook-init-llgbk   0/1     Completed   0          33s
    
        NAME                                   TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
        service/spark-spark-operator-webhook   ClusterIP   198.19.248.177   <none>        443/TCP   27s
    
        NAME                                   READY   UP-TO-DATE   AVAILABLE   AGE
        deployment.apps/spark-spark-operator   1/1     1            1           27s
    
        NAME                                             DESIRED   CURRENT   READY   AGE
        replicaset.apps/spark-spark-operator-58bf8d4cb   1         1         1       27s
    
        NAME                                          COMPLETIONS   DURATION   AGE
        job.batch/spark-spark-operator-webhook-init   1/1           6s         33s
    
  • 위와 같이 spark-operator-webhook-init pod가 Completed 상태이고, spark-operator pod가 Running 상태라면 Helm을 통한 spark-on-k8s-operator 차트가 잘 설치가 되어 Spark 작업을 실행할 수 있는 환경이 구성된 것이다.

2. Sample Pyspark Job 실행

  • spark-on-k8s-operator 환경에서는 Spark 작업을 실행하는 방법이 두 가지가 있다.
    1. Pod 내부에서 spark-summit을 통한 작업 실행
    2. SparkApplication Operator YAML 파일을 통한 작업 실행
  1. spark-summit을 통한 작업 실행

    • spark-operator deployment 내부로 execute하여 spark-submit으로 작업을 실행해보도록 할 것이다.
    • 아래 CLI에서 필요한 control plane 주소service account 이름은 아래 명령어들을 통해 확인할 수 있다.\
      • kubectl cluster-info
      • kubectl get sa
    
    1. exec into spark-operator deployment
    
      > kubectl exec -it deploy/spark-spark-operator -- bash
      
      	root@spark-spark-operator-58bf8d4cb-m74fp:/opt/spark/work-dir# 
        
    
    2. spark-summit cli 실행
       - /opt/spark/examples/src/main/python/pi.py 이 경로에 기본적으로 존재하는 python 스크립트 실행
    	
      > /opt/spark/bin/spark-submit \
            --master k8s://[Cluster control plane 도메인] \
            --deploy-mode cluster \
            --driver-cores 1 \
            --driver-memory 512m \
            --num-executors 1 \
            --executor-cores 1 \
            --executor-memory 512m \
            --class org.apache.spark.examples.SparkPi \
            --conf spark.kubernetes.namespace=[실행되는 namespace 이름] \
            --conf spark.kubernetes.container.image=apache/spark:latest \
            --conf spark.kubernetes.authenticate.driver.serviceAccountName=[service account 이름] \
            local:///opt/spark/examples/src/main/python/pi.py
    • 아래와 같이 driver pod와 executor pod가 뜨면서 작업이 처리되고 있는 것을 확인 할 수 있다.
  2. SparkApplication Operator를 통한 작업 실행

  • SparkApplication Kind를 가진 YAML 파일로 작업을 실행한다.

    • sample-job.yaml
    
    apiVersion: "sparkoperator.k8s.io/v1beta2"
    kind: SparkApplication
    metadata:
      name: pyspark-pi
    spec:
      type: Python
      pythonVersion: "3"
      mode: cluster
      image: apache/spark
      imagePullPolicy: Always
      mainApplicationFile: local:///opt/spark/examples/src/main/python/pi.py
      sparkVersion: "3.5.0"
      driver:
        cores: 1
        coreLimit: "1200m"
        memory: "512m"
        labels:
          version: 3.5.0
        serviceAccount: [service account 이름]
      executor:
        cores: 1
        instances: 1
        memory: "512m"
        labels:
          version: 3.5.0

    kubectl apply -f sample-job.yaml

    • YAML 파일 실행을 하게되면 1번에서 보았던 작업 과정과 동일하게 driver pod와 executor pod가 뜨면서 작업이 처리된 것을 확인할 수 있다.

3. OUTRO

  • 이번 1부 글에서는 쿠버네티스 환경에서 Spark 작업을 처리할 수 있도록 환경을 구성해주는 Helm 패키지인 spark-on-k8s-operator를 통해 환경 구축 후 샘플 작업을 실행하는 과정을 다뤄보았다.
  • 2부에서는 구축된 환경에서 Custom한 Docker Image를 통해 기본적으로 제공되는 스크립트가 아닌, 개별적으로 작성한 Spark 스크립트가 작동될 수 있도록 구성해볼 것이다.
profile
데이터 엔지니어의 작업공간 / #PYTHON #SPARK #AWS #NCLOUD
post-custom-banner

6개의 댓글

comment-user-thumbnail
2024년 5월 7일

안녕하세요. 좋은 글 잘 읽었습니다.
혹시 serviceaccount 어떤거 사용하셨는지 알 수 있을까요?
제가 옛날에 GCP에서 제공할때 했었을때는 sparkoperator-spark로 하면 executor pod를 잘 생성 했었는데
이번에 다시 해보려고 하니까 계속 driver pod까지는 생성이되는데 executor pod가 생성이 안되어서요,,,
보시면 답변 부탁드리겠습니다 ㅜㅜ !!

1개의 답글
comment-user-thumbnail
2024년 6월 3일

안녕하세요. EMR on NKS에 대해 여쭤보고 싶어서 댓글을 답니다. 혹시 구축 하시려는게 드라이버는 nks에서 실행되고 job run을 EMR에서 실행하려고 하시는 건가요? 현재 해당 설정이 가능한지에 대해 찾아보다가 글을 발견해서 댓글을 답니다

1개의 답글