안녕하세요, 박민재입니다. 아마 2년 전 즈음에 Spark on Kubernetes 관련 내용을 다뤘었는데요 (이 글 또한, 개정판을 작성 해 볼게요), 이번에는 Spark Job을 Kubernetes Cluster에 편리하게 제출할 수 있게 하는 Spark Operator에 대해 알아 보도록 하겠습니다.
그렇다고, 이 글에서 아예 설명 하지 않고 넘어가는 것은 아닌 것 같아, Spark on Kubernetes를 사용하는 이유를 세 줄로 요약 하면 다음과 같습니다.
먼저 Kubernetes에 존재하는 Operator Pattern에 대해서 알아 보도록하겠습니다. Kubernetes의 Operator 패턴은 Kubernetes 클러스터에서 사용자가 Custom Resource Definition(CRD) 를 이용 하여, Pod, Service, Deployment, ConfigMap 등의 여러 개의 Resource를 하나의 개념으로 묶어 배포 및 관리를 할 수 있게 하는 패턴입니다. 복잡한 어플리케이션을 하나의 Resource 개념으로 캡슐화 하고, 이를 관리 하는 Controller 구현체를 추가 작성하여, Upgrade, HA, Networking을 일괄적으로 관리 하는 형식으로 이용 할 수가 있는거죠.
아래는 SparkApplication을 제출하는 YAML 파일의 예시 입니다. 이렇게 간단한 코드로 Pod, Ingress 등 여러 Kubernetes Resource를 손쉽게 일괄 배포 할 수 있습니다.
apiVersion: sparkoperator.k8s.io/v1beta2
kind: SparkApplication
metadata:
name: spark-pi
namespace: default
spec:
type: Scala
mode: cluster
image: spark:3.5.1
mainClass: org.apache.spark.examples.SparkPi
mainApplicationFile: local:///opt/spark/examples/jars/spark-examples_2.12-3.5.1.jar
오늘 설명할 Spark Operator도 Kubernetes의 Operator Pattern으로 Spark Job을 쉽게 Kubernetes Cluster로 제출 할 수 있게 도와줍니다. 현재 Open Source로 지원 되고 있는 Spark Operator 같은 경우에는 크게 2개가 있습니다.
Spark Operator 관련 Star, PR 수가 압도적으로 Kubeflow Spark Operator가 더 높습니다. 커뮤니티가 더 활발하다는 이야기죠. 따라서 오늘은 Kubeflow Spark Operator로 설명을 진행 합니다.
여담이지만, Apache Spark 4.0.0-preview가 README.md에 있는 것 보면, Apache Spark Maintainer 들이 Spark 4 버전을 목표로 이를 개발하고 있는 걸지도 모르겠군요.
공식 Doc에 있는 내용을 통해 구조를 살펴보면 다음과 같습니다.
SparkApplication Controller
를 이용하여 SparkApplication Resource를 관리 합니다.submisstion runner
를 사용합니다.Spark Pod Monitor
를 사용 합니다.Mutating Admission Webhook
이 있습니다.
kubectl
을 이용하여, SparkApplication
객체를 생성 합니다.submission runner
로 전송 합니다.submission runner
에서는 spark-submit
을 수행 하며 Driver Pod을 생성 하고, Driver Pod에서는 Executor Pod을 생성 합니다.Spark Pod Monitor
는 여기서 생성된 Driver Pod과 Executor Pod을 모니터링 합니다.SparkApplication Controller는 Kubernetes 클러스터 내의 SparkApplication Object의 생성, 업데이트, 삭제 Event를 감시합니다. 새로운 SparkApplication 객체가 추가되면, 이를 Queue에 삽입하여, Submission Runner 단에서 이를 K8S Cluster 내에 제출합니다.
SparkApplication Object가 Update되면, Controller는 Application Spec이 변경되었을 시에는 Application을 중단 하고 새로운 Spec으로 다시 Application을 제출 합니다.
Controller는 Spark Pod Monitor를 통해 SparkApplication Object의 상태를 관리 합니다. Spark Pod Monitor는 Spark Pod의 생성, 업데이트, 삭제 이벤트를 감시하고, 상태 업데이트 메시지를 Controller에 보냅니다.
애플리케이션의 최종 상태는 Driver Pod의 종료 상태에 따라 결정됩니다. 드라이버 Pod가 완료되면 COMPLETED
, 실패하면 FAILED
로 설정됩니다. 제출이 실패하면 FAILED_SUBMISSION
으로 설정됩니다.
Controller는 새로운 SparkApplication Object를 준비하면서 Driver Pod 혹은 Executor Pod에 특정 Annotation을 추가합니다. 이 Annotation은 Mutating Admission Webhook에서 사용 되는데요, Mutating Admission Webhook에서 Annotation을 읽어 Pod이 실행되기 전 추가적으로 필요한 구성을 적용합니다. 예를 들어, 특정 ConfigMap을 Pod에 마운트해야 하는 경우, 해당 ConfigMap의 이름을 지정하는 Annotation을 추가합니다.
이런 식으로 Spark Operator의 Component들은 SparkApplication Object들을 관리합니다.
Spark Operator에서는 재시작 관련 정책이 존재 하는데요, Operator는 Driver Pod의 상태에 Application Status와 기반한 Restart Policy에 따라서, 어플리케이션 재수행 여부를 결정합니다.
Never
: Task 성공 / 실패 여부와 관계 없이, 이를 실패 시킵니다.Always
: Task 성공 / 실패 여부와 관계 없이, 이를 무조건 재시작 시킵니다.OnFailure
: Task가 실패 하고, 설정 하였던 재시작 반복 횟수를 넘기지 않았다면, 이를 재시작 합니다.Operator 단에서 Application을 재시작 하게 되면, 이전에 종료된 Application과 관련된 Kubernetes Resource를 정리하고, 해당하는 SparkApplication Object를 Queue에 삽입 합니다.
이렇게 Spark Operator 관련 Overview를 마쳤습니다. 다음 시간에는 Spark Operator를 설치하고, 간단한 SparkApplication을 제출 하는 글로 찾아뵙겠습니다.