pile·
인프라 / DevOps·토스 SLASH토스 SLASH·

Spark Connect on Kubernetes #1: 견고한 Spark Connect 만들기

토스증권 Data Infra팀이 Spark Connect를 Kubernetes 위에서 멀티테넌트 서비스로 운영하며 맞닥뜨린 구조적 문제 3가지(Driver SPOF, 리소스 경합, 고정 스케일)와 그 해결책을 다룬다. 단일 SparkContext를 공유하는 구조에서 한 사용자의 OOM 쿼리가 전체 세션을 종료하는 문제를, Executor 실패 카운터 재설계와 멀티 Replica 아키텍처로 극복했다.

핵심 포인트
  • Spark Connect는 Driver를 미리 띄운 gRPC 서버로 전환해 클라이언트를 경량화하지만, 모든 세션이 SparkContext를 공유해 단일 장애점이 생긴다.
  • spark.executor.maxNumFailures는 글로벌 카운터라 한 사용자의 실패가 타 세션까지 종료시킨다 — failuresValidityInterval과 쌍으로 설정해 범위를 쿼리 단위로 좁혔다.
  • 멀티 Replica로 장애 범위를 한 대로 제한하고, 자체 Gateway가 EWMA 기반 부하 점수로 새 세션을 배분한다.
  • Istio consistent hash는 새 세션이 바쁜 서버에 계속 배치되는 문제가 있어 상태 인식 Gateway를 직접 개발했다.
  • Control Plane(Kubernetes Operator)과 Data Plane(Gateway)을 Redis를 통해 분리해 Operator 장애 시에도 라우팅이 계속된다.
상세 정리
  • Spark Connect 개념: Spark 3.4에 포함된 gRPC 기반 아키텍처로, 클라이언트는 DataFrame 연산을 Unresolved Logical Plan → Protocol Buffer로 인코딩해 보내고, 서버가 분석·실행 후 Arrow 형식으로 결과를 스트리밍한다.
  • SPOF 문제 원인: ExecutorPodsLifecycleManager가 numFailedExecutors > maxNumFailures 조건 충족 시 sys.exit(11) 호출 — 기본값은 max(3, 2×executor수)이고 시간 경과에도 자동 초기화되지 않는다.
  • SPOF 해결: spark.executor.maxNumFailures를 사실상 무한대로 올리고, failuresValidityInterval로 누적 실패 기록을 주기 초기화하며, spark.task.maxFailures와 spark.stage.maxConsecutiveAttempts로 개별 쿼리를 빠르게 종료시킨다.
  • Fair Scheduler 한계: Spark Connect에서는 spark.scheduler.pool이 thread-local로 설정되지만 클라이언트-서버 분리 탓에 서버 실행 스레드에 전파되지 않아 Pool 격리가 무력화된다.
  • 메모리 경합: spark.driver.maxResultSize(기본 1GB)가 쿼리 단위로 적용되므로 동시 쿼리가 많으면 Driver 메모리가 누적 압박받는다 — 동시 쿼리 수를 감안해 보수적으로 낮춰야 한다.
  • 멀티 Replica 설계: 각 Replica는 독립 SparkContext·Driver·Executor를 보유하고, Dynamic Resource Allocation과 결합해 유휴 Replica는 Driver만 유지한다.
  • Gateway 부하 점수: REST API 폴링으로 active(실행 중 Task), pending(대기 Task), maxTasks(전체 슬롯)를 수집해 0.9×utilization + 0.1×min(active_session수/cap, 1) 공식으로 산출하며, utilization은 EWMA로 순간 스파이크를 제외한다.
  • 세션 라우팅 규칙: 새 세션은 점수 최저 서버로, 기존 세션은 Driver 메모리에 상태가 있으므로 원래 서버로 고정한다.
  • Istio를 버린 이유: DestinationRule consistent hash는 동일 세션 고정은 되지만 새 세션 배치 시 서버 부하를 무시해 바쁜 서버에 계속 쏠리는 문제가 있었다.
  • Control/Data Plane 분리: Kubernetes Operator가 K8S watch로 서버 상태를 감지해 Redis에 TTL 포함 Publish하고, Gateway는 Redis만 폴링해 ServerPool을 캐시한다 — Operator 장애 시에도 라우팅이 유지된다.
  • 시리즈 예고: 2편에서 고정 스케일 해결(Control Plane, 무중단 교체), 3편에서 인증·인가 기반 사용자 식별과 데이터 접근 제어를 다룰 예정이다.
왜 읽나Spark Connect를 단순 실습이 아닌 멀티테넌트 프로덕션으로 안정 운영하려는 데이터 엔지니어·인프라팀에게 실전 설정값과 Gateway 아키텍처 레퍼런스.
토스 SLASH
토스 SLASH 블로그
원문은 여기서 이어서 읽을 수 있어요
원문 읽기
읽음 (0)

이 글과 비슷한

  1. 인프라 / DevOps·AWS KoreaAWS Korea Tech·

    엔터프라이즈 보안 요구사항을 충족하는 프라이빗 Amazon Bedrock AgentCore 구축하기

    Amazon Bedrock AgentCore의 VPC egress 기능(2026년 4월 추가)을 활용해 온프레미스 LLM·사내 IdP·사내 MCP 서버에 인터넷 노출 없이 연결하는 방법을 다룬다. 규제 산업 엔터프라이즈가 기존 사내 자산을 그대로 유지하면서 Bedrock AgentCore를 안전하게 구축하기 위한 구성 가이드다.

    요약 이어보기
    #mcp#amazon-bedrock#vpc+2
  2. 인프라 / DevOps·gitlab-engGitLab Blog·

    OpenTofu와 Argo CD로 구성하는 GitLab 기반 AWS 제어 플레인

    GitLab을 단일 제어 플레인으로 삼아 OpenTofu로 AWS 인프라를 프로비저닝하고, Argo CD로 GitOps 기반 애플리케이션 배포까지 자동화하는 엔드투엔드 튜토리얼이다. VPC·EKS 클러스터 구성부터 Helm 기반 툴 설치, 샘플 앱 배포까지 모든 과정이 GitLab CI/CD 파이프라인으로 연결된다.

    요약 이어보기
    #kubernetes#aws-eks#gitops+2
  3. 인프라 / DevOps·AWS KoreaAWS Korea Tech·

    Amazon Bedrock 기반 사내 LLM, 키 발급부터 비용 차단까지: F&F의 LiteLLM 게이트웨이 운영 사례

    패션 기업 F&F가 Amazon Bedrock과 LiteLLM 프록시를 결합해 구축한 사내 LLM 플랫폼 운영 사례다. API 키 셀프서비스 발급, 모델별 접근 승인 워크플로, 사용자·프로젝트별 예산 자동 차단까지 전 과정을 직접 구현한 아키텍처 결정과 운영 교훈을 공유한다.

    요약 이어보기
    #kubernetes#amazon-bedrock#litellm+2