← 학습 카테고리

Learn

Spark

38개 모듈 · 현재 25번째

Spark 모듈 25/38 spark-learn-25

운영과 배포 (클러스터 매니저·장애 복구·직렬화)

Apache Spark Data Engineering Interview Questions (blog, 50 Q&A) — (블로그, 발행처 미상) spark_ref_01.md Q31-40 (Operations & Deployment)

이 모듈을 다 읽으면

  • 클러스터 매니저별 실무 채택 현황(특히 Mesos의 위상 변화)을 판단할 수 있다
  • Client mode와 Cluster mode의 장애 허용성 차이를 설명할 수 있다
  • lineage 재계산과 checkpoint를 통한 장애 복구 메커니즘의 차이를 설명할 수 있다
  • executor.memoryOverhead의 정확한 기본 계산식(최솟값 포함)을 설명할 수 있다

클러스터 매니저 선택, client/cluster 배포 모드, lineage·checkpoint 기반 장애 복구, spark-submit, Structured Streaming 개요, 직렬화 방식을 다룬다. Mesos의 현재 위상과 memoryOverhead 기본값 계산식을 원문보다 정확하게 보완했다.

클러스터 매니저 — Mesos 위상 변화

Spark는 Standalone, Hadoop YARN, Apache Mesos, Kubernetes 네 가지 클러스터 매니저를 지원한다고 소개되지만, 이 중 Mesos는 Spark 3.2부터 지원이 deprecated(지원 중단 예고) 상태로 전환되었다. 2026년 현재 실무에서 신규로 Mesos를 선택하는 경우는 거의 없으며, 온프레미스에서는 YARN, 클라우드 네이티브 환경에서는 Kubernetes가 사실상 양대 표준이고 Standalone은 소규모/테스트 클러스터에서 주로 쓰인다.

핵심 포인트

  • Mesos는 Spark 3.2부터 deprecated로 전환되어 현재는 거의 쓰이지 않는다.
  • 실무 표준은 온프레미스 YARN, 클라우드 네이티브 Kubernetes 양강 구도다.

Client mode vs Cluster mode

Client mode는 Driver 프로세스가 잡을 제출한 호스트(예: 사용자의 노트북, 게이트웨이 서버)에서 실행된다. Jupyter 노트북 같은 대화형 작업에서 결과를 즉시 볼 수 있어 편리하지만, 제출한 호스트가 네트워크 연결을 잃으면 장기 실행 잡이 중단될 위험이 있다. Cluster mode는 Driver가 클러스터 내부의 워커 노드 중 하나에서 실행되어 제출 클라이언트와 클러스터 사이의 네트워크 문제에 영향을 받지 않으므로, 프로덕션 배치 잡의 표준 방식이다.

핵심 포인트

  • Client mode는 제출 호스트가 Driver를 실행해 연결 끊김에 취약하다.
  • Cluster mode는 Driver가 클러스터 내부에서 실행되어 프로덕션 표준이다.

Lineage Graph와 장애 복구

Lineage Graph(RDD Operator Graph)는 자식 RDD를 만드는 데 사용된 모든 부모 RDD와 연산의 기록이다. RDD가 불변이기 때문에 Spark는 기존 데이터를 변경하지 않고 항상 새 RDD를 만들며, 노드 장애로 파티션이 유실되면 이 lineage를 따라가 원본 데이터 소스부터 해당 연산들을 다시 실행해 유실된 파티션만 복구한다.

lineage가 아주 길어지는 스트리밍/반복 ML 워크로드에서는 재계산 비용과 스택 오버플로 위험이 커지므로 checkpoint()로 RDD 상태를 안정적인 스토리지(S3, HDFS 등)에 저장해 lineage를 끊어준다. cache()/persist()는 lineage를 유지한 채 데이터만 캐싱하는 반면, checkpoint()는 lineage 자체를 완전히 제거한다는 점이 둘의 핵심 차이다.

핵심 포인트

  • lineage를 따라 원본부터 재계산해 유실 파티션을 복구하는 것이 기본 장애 복구 방식이다.
  • checkpoint()는 lineage를 완전히 끊어 재계산 비용과 스택 오버플로 위험을 줄인다(cache/persist는 lineage 유지).
  • 체크포인트 대상은 S3/HDFS 같은 안정적 스토리지여야 한다.

spark-submit

spark-submit은 Spark 애플리케이션을 실행하는 커맨드라인 유틸리티로, master URL(예: yarn), deploy mode(client/cluster), executor 메모리, 코어 수, 외부 jar/파일 등을 옵션으로 지정한다.

핵심 포인트

  • master, deploy-mode, executor-memory, executor-cores 등을 spark-submit 옵션으로 지정한다.

Window Functions

윈도우 함수는 현재 행과 관련된 행 집합(윈도우) 전체를 대상으로 계산을 수행하되, SUM 같은 집계 함수처럼 행을 하나로 접지 않고 원래 행을 그대로 유지한 채 계산 결과를 추가한다. 순위를 매기는 ROW_NUMBER(), RANK(), 앞뒤 행 값을 비교하는 LAG()/LEAD() 등이 대표적이다.

핵심 포인트

  • 집계 함수와 달리 원본 행을 유지한 채 값을 덧붙이는 것이 윈도우 함수의 핵심 특징이다.

Structured Streaming 개요

Structured Streaming은 Spark SQL 엔진 위에 구축된 스트림 처리 엔진으로, 배치 데이터를 다루듯 동일한 방식으로 스트리밍 연산을 표현할 수 있게 해준다. 실시간 데이터 스트림을 계속 추가(append)되는 '무한 테이블(unbounded table)'로 취급하며, 증분 처리와 장애 복구를 Spark가 자동으로 관리한다. 모듈 1에서 짚었듯, 원문 Q2가 언급한 구 DStream 기반 Spark Streaming은 이 Structured Streaming 이전의 레거시 API다.

핵심 포인트

  • 스트림을 계속 append되는 무한 테이블로 모델링하는 것이 핵심 아이디어다.
  • 배치와 동일한 API로 스트리밍을 표현할 수 있다.

Stage — 셔플 경계로 나뉘는 실행 단위

Stage는 잡(Job)을 셔플 경계 기준으로 나눈 물리적 실행 단위다. 네트워크 이동이 필요 없는 narrow 트랜스포메이션들은 하나의 스테이지로 묶이고, wide 트랜스포메이션(예: join)을 만나면 현재 스테이지를 마무리하고 셔플을 수행한 뒤 새 스테이지를 시작한다. 하나의 스테이지는 파티션 수만큼의 태스크로 다시 나뉜다.

핵심 포인트

  • Job → Stage(셔플 경계로 분할) → Task(파티션 단위) 계층 구조다.

spark.executor.memoryOverhead — 정정

이 설정은 executor 프로세스당 JVM 힙 외에 추가로 확보하는 메모리로, VM 오버헤드·인터닝된 문자열·JNI를 통한 네이티브 코드(예: Python/C++ 라이브러리) 사용 등에 쓰인다. 원문은 기본값을 '실행자 메모리의 약 10%'라고만 설명하지만, 실제로는 executorMemory * 0.10과 최소값 384MB 중 더 큰 값이 기본값이다 — 즉 executor 메모리가 작을 때는 10%가 아니라 384MB가 적용된다. PySpark처럼 JVM 밖에서 별도 Python 프로세스를 띄우는 워크로드는 이 오버헤드가 부족해 컨테이너가 클러스터 매니저(YARN/K8s)에 의해 강제 종료되는 경우가 흔해, 이 값을 늘려야 할 때가 많다.

핵심 포인트

  • 기본값은 max(executorMemory * 0.10, 384MB)이며 '10%'만 기억하면 소규모 executor에서는 틀릴 수 있다.
  • PySpark 등 JVM 밖 프로세스를 쓰는 워크로드는 오버헤드 부족으로 컨테이너가 kill되기 쉬워 값을 늘려야 하는 경우가 많다.

직렬화 — Java vs Kryo

Spark는 기본적으로 Java 직렬화를 사용하는데, 유연하지만 느리고 객체 크기가 크다. Kryo 직렬화는 훨씬 빠르고 결과물이 작아 프로덕션에서 강력히 권장되며, 최고 성능을 위해서는 커스텀 클래스를 등록해줘야 한다. Spark는 셔플 시 Int/Long/String 같은 단순 타입에는 별도 설정 없이도 내부적으로 최적화된 직렬화를 일부 적용하지만, spark.serializer를 KryoSerializer로 명시적으로 바꾸는 것이 일반적인 프로덕션 관행이다.

핵심 포인트

  • 기본값은 Java 직렬화이지만 느리고 객체가 크다.
  • Kryo는 빠르고 컴팩트해 프로덕션 권장이며, 최고 성능을 위해 커스텀 클래스 등록이 필요하다.