목록으로

Programming Notes

Smart Pipelines Orchestration: 공유 Spark에서 예측 가능한 데이터 플랫폼 설계

서론 성숙한 데이터 플랫폼에서는 컴퓨팅 확장이 주요 과제인 경우는 드뭅니다. 공유되고 탄력적인 Spark 풀은 이미 대부분의 워크로드에 충분한 처리 용량을 제공합니다. 더 어려운 문제는 여러 파이프라인이 동일한 리소스를 놓고 경쟁할 때 예측 가능한 실행 을 달성하는 것입니다....

서론

성숙한 데이터 플랫폼에서는 컴퓨팅 확장이 주요 과제인 경우는 드뭅니다. 공유되고 탄력적인 Spark 풀은 이미 대부분의 워크로드에 충분한 처리 용량을 제공합니다. 더 어려운 문제는 여러 파이프라인이 동일한 리소스를 놓고 경쟁할 때 예측 가능한 실행을 달성하는 것입니다.

Azure Synapse에서 Spark 풀은 비용 및 활용도를 최적화하기 위해 파이프라인 간에 일반적으로 공유됩니다. 이 모델은 효율적이지만, 실행 순서가 비즈니스 우선순위가 아닌 스케줄링 동작에 의해 결정된다는 주요 제약을 도입합니다.

이 게시물은 우선순위를 명시적으로 만들어, 공유 Spark 컴퓨팅에서 중요한 워크로드가 Spark 코드, 구성 또는 클러스터 용량을 수정하지 않고도 예측 가능하게 실행되도록 하는 오케스트레이션 패턴을 설명합니다.

목표

이 작업은 Spark 성능을 최적화하는 것을 목표로 하지 않습니다. 그 목표는 파이프라인이 Spark 풀을 공유할 때 다음을 보장하는 것입니다.

  • 지연 시간에 민감한 워크로드가 먼저 실행됩니다.
  • 무거운 백필이 중요한 파이프라인을 지연시키지 않습니다.
  • 경합 상황에서 실행 순서가 결정적입니다.

이 모든 것은 Spark 구성, 노트북 로직 또는 클러스터 크기 변경 없이 달성되어야 했습니다.

이 문제가 발생하는 이유

단순한 오케스트레이션 모델에서는 파이프라인이 병렬로 트리거됩니다. Spark 관점에서 보면 다음과 같습니다.

  • 모든 작업이 동등합니다.
  • 모든 작업이 동시에 실행기를 획득하려고 시도합니다.
  • 스케줄링 결정은 가용성과 타이밍에 기반합니다.

그 결과, 우선순위는 암묵적이며 종종 잘못됩니다. 무거운 워크로드가 가볍지만 중요한 워크로드보다 단순히 더 일찍 더 많은 리소스를 요청했기 때문에 실행기를 획득할 수 있습니다.

이러한 동작은 Spark에서 예상되는 것입니다. 문제는 컴퓨팅이 아니라 오케스트레이션에 있습니다.

핵심 개념: 실행 순서로서의 우선순위

공유 Spark 플랫폼에서 우선순위는 컴퓨팅 튜닝이 아닌 실행 순서를 통해 적용됩니다.

오케스트레이션 계층은 워크로드가 공유 컴퓨팅에 언제 허용될지 제어합니다. 일단 실행이 시작되면 Spark는 각 워크로드를 정상적으로 처리합니다.

이는 Spark의 실행 모델을 보존하면서 결정론적 워크로드 순서 지정을 제공합니다.

1단계: 워크로드 분류

이 블로그에서 소개하는 데모에서는 비즈니스 영향에 따라 구성 중에 워크로드가 분류됩니다.

카테고리 설명 우선순위 예시
Light (Critical) SLA에 민감한 대시보드 및 다운스트림 소비자 높은 우선순위, 낮은 리소스 가중치(데이터 볼륨)
Medium (High) 핵심 보고 워크로드 중간 우선순위
Heavy(Best Effort) 백필 및 이력 계산 낮은 우선순위, 높은 리소스 가중치(데이터 볼륨)

이 분류는 Spark 외부 및 코드 외부에 있습니다. 이는 구현이 아닌 비즈니스 의도를 나타냅니다.

향후 단계에서는 분류를 자동화할 수 있습니다. 예를 들어, 에이전트가 관찰된 실패율 또는 실행 안정성을 기반으로 우선순위를 조정할 수 있습니다. 워크로드 분류는 오케스트레이션 메타데이터로 표현됩니다. 예를 들어:

[
  {"name":"ExecDashboard","pipeline":"PL_Light_ExecDashboard","weight":1,"tier":"Critical"},
  {"name":"FinanceReporting","pipeline":"PL_Medium_FinanceReporting","weight":3,"tier":"High"},
  {"name":"Backfill","pipeline":"PL_Heavy_Backfill","weight":8,"tier":"BestEffort"}
]

각 워크로드 카테고리에서 실행되는 내용

모든 파이프라인은 동일한 공유 Spark 풀에서 실행되지만, 수행하는 작업은 범위, 데이터 볼륨 및 경합에 대한 민감도가 다릅니다.

Light 워크로드는 SLA에 민감한 대시보드와 다운스트림 소비자를 지원합니다. 해당 노트북은 강력한 필터링, 제한된 조인 및 작은 집계를 사용하여 대상 읽기를 수행합니다. 실행 시간은 짧으며, 전체 파이프라인 기간은 계산보다는 실행기 가용성에 의해 지배됩니다.

Medium 워크로드는 핵심 보고 및 분석 로직을 나타냅니다. 이 노트북은 더 큰 데이터 세트를 처리하고, 여러 소스에서 조인을 수행하며, Light 워크로드보다 비용이 많이 들지만 여전히 시간 제한이 있고 비즈니스에 중요한 집계를 적용합니다.

Heavy 워크로드는 백필 및 이력 재계산과 같은 최선 노력 파이프라인입니다. 해당 노트북은 대량의 데이터를 스캔하고, 비용이 많이 드는 변환을 적용하며, 응답성보다는 처리량에 최적화되어 있습니다. 이러한 워크로드는 지연을 허용하지만, 동시에 허용될 경우 공유 컴퓨팅에 상당한 부담을 줍니다.

모든 워크로드는 동일한 Spark 풀, 실행기 구성 및 런타임을 사용합니다. 이 구분은 Spark 튜닝이 아닌 비즈니스 의도와 실행 특성을 반영합니다.

각 카테고리에 대한 예제 노트북은 첨부된 GitHub 저장소에서 확인할 수 있습니다.

2단계: 단순한 오케스트레이션 (기준선)

다음 파이프라인 실행은 모든 워크로드가 공유 Spark 풀에 대해 병렬로 트리거될 때의 기준선 동작을 보여줍니다.

모든 Light, Medium 및 Heavy 파이프라인이 동시에 허용됩니다. 실행기 획득 및 실행 순서는 비즈니스 우선순위보다는 타이밍에 따라 달라지므로, 경합 상황에서 비결정적인 동작을 초래합니다.

Light 워크로드는 최소한의 컴퓨팅을 요구함에도 불구하고, Medium 및 Heavy 파이프라인이 동시에 Spark 풀에 진입하여 발생하는 실행기 경합으로 인해 지연됩니다.

3단계: 스마트 오케스트레이션 (우선순위 인식)

오케스트레이션 모델

동일한 자식 파이프라인과 노트북이 재사용됩니다. 부모 파이프라인은 진입 순서를 강제합니다.

  1. Light (Critical)
  2. Medium (High)
  3. Heavy (Best Effort)

종속성은 Spark 풀에 대한 진입을 제어합니다. 병렬 처리는 우선순위 클래스 내에서 유지됩니다.

공유 Spark에 미치는 영향

  • Light 워크로드는 경합 없이 Spark 풀에 진입합니다.
  • Medium 워크로드는 Light가 완료된 후 실행됩니다.
  • Heavy 워크로드는 의도적으로 지연됩니다.
  • 실행기 획득은 비즈니스 우선순위에 맞춰집니다.

Light 파이프라인은 먼저 실행되고 Medium 파이프라인이 진입하기 전에 완료됩니다. Heavy 워크로드는 설계상 마지막에 실행됩니다. Spark 구성 변경은 도입되지 않습니다.

Spark 풀, 노트북 및 실행기 구성은 단순한 실행과 동일합니다. 오케스트레이션 그래프만 다릅니다.

4단계: Light 워크로드에 미치는 영향

Light 워크로드는 런타임이 계산이 아닌 대기열 시간에 의해 지배되기 때문에 오케스트레이션에 특히 민감합니다.

단순한 실행과 우선순위 인식 실행을 비교하면 Spark 실행 시간은 변함이 없지만, Spark 풀에 더 일찍 진입하고 즉시 실행기에 접근하여 파이프라인 기간이 개선되었음을 알 수 있습니다.

단순한 실행

  • Spark 실행 시간: 짧고 변경 없음
  • 파이프라인 기간: 경합 시 수 분
  • 실행기 비가용성으로 인한 지연

스마트 실행

  • Spark 실행 시간: 변경 없음
  • 파이프라인 기간: 컴퓨팅 시간과 거의 일치
  • 실행기에 즉시 접근

이러한 개선은 리소스 증가가 아닌 진입 경합 제거에서 비롯됩니다.

결과 및 성능

단순한 오케스트레이션과 비교하여, 우선순위 인식 오케스트레이션은 Light 워크로드가 경합 상황에서 수십 분이 아닌 수 분 안에 완료되도록 보장하며, Spark 실행 시간 자체는 변함이 없습니다. Heavy 워크로드는 더 이상 지연 시간에 민감한 파이프라인을 지연시키지 않으며, 실행 순서는 모든 실행에서 결정적입니다. 이러한 개선은 Spark 구성, 노트북 로직 또는 클러스터 용량을 수정하지 않고 오직 공유 Spark 풀에 대한 진입 제어를 통해 달성됩니다.

다음 단계:

1. Heavy 워크로드 최적화

Heavy 워크로드가 우선순위에 따라 분리되면 독립적으로 최적화할 수 있습니다.

  • 백오프를 사용한 재시도
  • 일시적 오류에 대한 내성
  • 증가된 실행기 수 또는 더 큰 풀

진입 제어가 없으면 이러한 최적화는 경합을 증가시키지만, 스마트 오케스트레이션을 사용하면 중요한 파이프라인에 영향을 미치지 않습니다.

2. 정적 분류를 넘어

이 구현에서 워크로드 분류는 정적이며 구성 기반으로, 안정화에는 충분합니다.

다음 단계는 적응형 분류입니다.

  • 실행 메트릭 및 실패율 수집
  • 불안정한 파이프라인 감지
  • 임계값을 초과하는 파이프라인 재분류 (예: 롤링 기간 동안 20% 이상의 실패)

이는 불안정한 워크로드가 중요한 실행 경로에 영향을 미치는 것을 방지하고 최소한의 유지 보수로 파이프라인을 안정적으로 만듭니다.

3. 코파일럿 에이전트를 통한 분류 지원

대규모 환경에서는 우선순위 결정이 자동화의 이점을 얻습니다. 코파일럿 스타일 에이전트는 이력 실행 데이터를 사용하여 분류 변경을 권장할 수 있으며, 관찰된 동작에 기반하여 의사 결정을 지원하면서도 엔지니어가 통제권을 유지하도록 합니다.

예시: 워크로드 분류를 Light에서 Medium으로 변경

SLA에 민감한 대시보드를 지원하고 일반적으로 최소한의 리소스 사용으로 빠르게 실행되기 때문에 처음에는 Light로 분류된 파이프라인을 고려해 보세요.

시간이 지남에 따라 실행 원격 측정 데이터는 동작의 변화를 보여줍니다.

  • 파이프라인이 일시적인 Spark 오류로 인해 지난 10번의 실행 중 4번 실패했습니다.
  • 평균 실행 시간이 조기 진입했음에도 불구하고 3배 증가했습니다.
  • 재시도 시도가 다른 Light 워크로드에 대한 경합을 증폭시킵니다.

이러한 신호에 따라 자동화된 에이전트는 워크로드를 불안정하다고 표시하고, Light에서 Medium으로 재분류할 것을 권장합니다.

재분류 후:

  • 파이프라인은 Light 워크로드 후에, 하지만 Heavy 워크로드 전에 허용됩니다.
  • 재시도가 발생하더라도 더 이상 지연 시간에 중요한 경로를 차단하지 않습니다.
  • 불안정성은 중요한 워크로드로부터 격리되면서 실행은 예측 가능하게 유지됩니다.

노트북 로직과 Spark 구성은 변경되지 않으며, 오직 워크로드의 진입 우선순위만 오케스트레이션 메타데이터를 통해 업데이트됩니다.

이 접근 방식은 플랫폼이 변화하는 워크로드 특성에 적응하면서도 중요한 파이프라인에 대한 결정론적 실행을 보존할 수 있도록 합니다.

결론

병렬 실행은 기본값이지만 전략은 아닙니다. 공유 환경에서 오케스트레이션은 스케줄러 동작에 의존하기보다는 비즈니스 의도를 명시적으로 인코딩해야 합니다.

오케스트레이션 계층에서 우선순위를 강제하면 효율성을 희생하지 않고 예측 가능성을 회복하며, 플랫폼이 발전함에 따라 적응적이고 정책 기반의 실행을 위한 기반을 제공합니다.

링크

  1. Azure Data Factory에서 데이터 이동 및 변환 오케스트레이션 - 학습 | Microsoft Learn
  2. Spark 작업 성능을 최대화하는 방법: 완전 가이드
  3. 노트북 참조를 위한 GitHub 리포지토리: sallydabbahmsft/Smart-pipelines-orchestration
  4. 피드백: Sally Dabbah | LinkedIn