웹 UI
웹 UI (Web UI)
Apache Spark가 제공하는 웹 사용자 인터페이스(UI) 모음을 정리한 문서예요. Web UI의 각 탭(Jobs, Stages, Storage, Environment, Executors, SQL, Structured Streaming, Streaming(DStreams), JDBC/ODBC Server)이 무엇을 보여주는지 알아볼게요. 실행 중인 Spark 클러스터의 상태와 리소스 소비를 모니터링하는 데 사용해요.
출처: 문서
본문
Apache Spark는 Spark 클러스터의 상태와 리소스 소비를 모니터링할 수 있는 웹 사용자 인터페이스(UI) 모음을 제공해요.
개요 (Overview)
Web UI는 모든 Spark 애플리케이션에 내장돼 있어요. 애플리케이션이 실행되는 동안, 그 안에서 무슨 일이 일어나고 있는지 검사할 수 있는 일련의 웹 페이지를 제공해요. 전형적인 용도로는 실행 중인 작업 모니터링, 실패 진단, 느린 SQL 쿼리의 실행 계획 분석, 메모리와 태스크가 executor들에 어떻게 분산되어 있는지 확인하는 것 등이 있어요.
기본적으로 Web UI는 http://<driver-host>:4040에서 사용할 수 있어요. 그 포트가 이미 사용 중일 때(예: 여러 Spark 애플리케이션이 같은 호스트에서 실행될 때), Spark는 사용 가능한 포트를 찾을 때까지 4041, 4042 등을 시도하고 시작 시 선택된 포트를 기록해요. spark.ui.port로 기본 포트를 재정의할 수 있으며, Configuration 레퍼런스에 문서화된 spark.ui.* 속성으로 다른 UI 동작도 조정할 수 있어요.
Web UI는 애플리케이션의 수명과 연결돼 있어요. 애플리케이션이 종료되면 UI에 더 이상 접근할 수 없어요. 애플리케이션이 끝난 후에 검사하려면 이벤트 로깅을 활성화하고 Spark History Server를 실행하세요. 이 서버는 영속된 이벤트 로그에서 동등한 UI를 재구성해요. 설정 방법은 Monitoring and Instrumentation을 참고하세요.
나머지 섹션에서는 Web UI 상단 탐색 막대의 각 탭을 살펴볼게요.
Jobs 탭 (Jobs Tab)
Jobs 탭은 Spark 애플리케이션의 모든 작업 요약 페이지와 각 작업의 상세 페이지를 표시해요. 요약 페이지는 상태, 기간, 모든 작업의 진행 상황, 전체 이벤트 타임라인 같은 상위 수준 정보를 보여줘요. 요약 페이지에서 작업을 클릭하면 해당 작업의 상세 페이지가 보여요. 상세 페이지는 이벤트 타임라인, DAG 시각화, 작업의 모든 스테이지를 추가로 보여줘요.
페이지 상단에 표시되는 정보는 다음과 같아요:
- 스케줄링 모드 (Scheduling mode): job scheduling 참고
- 상태별 작업 수: Active, Completed, Failed
- 이벤트 타임라인: executor와 관련된 이벤트(추가, 제거)와 작업을 시간순으로 표시
- 상태별로 그룹화된 작업 상세: Job ID, 설명(상세 작업 페이지 링크 포함), 제출 시간, 기간, 스테이지 요약, 태스크 진행 막대를 포함한 작업의 상세 정보
현재 사용자, 애플리케이션 시작 시간, 총 가동 시간(uptime)은 모든 페이지 하단의 푸터에 표시돼요.
Jobs 상세 (Jobs detail)
이 페이지는 job ID로 식별되는 특정 작업의 상세 내용을 표시해요.
- 작업 상태: (running, succeeded, failed)
- 상태별 스테이지 수 (active, pending, completed, skipped, failed)
- 연관 SQL 쿼리: 이 작업의 SQL 탭 링크
- 이벤트 타임라인: executor와 관련된 이벤트(추가, 제거)와 작업의 스테이지를 시간순으로 표시
- DAG 시각화: 정점이 RDD 또는 DataFrame을, 간선이 RDD에 적용될 연산을 나타내는 이 작업의 방향성 비순환 그래프(directed acyclic graph)의 시각적 표현
- 스테이지 목록 (active, pending, completed, skipped, failed 상태로 그룹화): Stage ID, 설명, 제출 타임스탬프, 기간, 태스크 진행 막대, Input(스토리지에서 읽은 바이트), Output(스토리지에 쓴 바이트), Shuffle read(로컬 및 원격 executor에서 읽은 총 shuffle 바이트와 레코드), Shuffle write(향후 shuffle을 위해 디스크에 쓴 바이트와 레코드) 컬럼 포함
Stages 탭 (Stages Tab)
Stages 탭은 Spark 애플리케이션의 모든 작업의 모든 스테이지 현재 상태를 보여주는 요약 페이지를 표시해요.
페이지 상단에는 상태(active, pending, completed, skipped, failed)별 모든 스테이지의 개수를 합산한 요약이 있어요. Fair 스케줄링 모드에서는 풀(pool) 속성 표도 보여줘요.
요약 아래에는 스테이지들이 상태별로 그룹화되어 (active, pending, completed, skipped, failed) 있게 돼요. 활성(active) 스테이지는 설명 옆에 작은 (kill) 링크를 보여주며, 클릭하면 Spark에 해당 스테이지 취소를 요청해요. 실패한 스테이지만 실패 원인을 보여줘요. 스테이지의 설명을 클릭하면 해당 스테이지의 상세 페이지가 열려요.
Stage 상세 (Stage detail)
스테이지 상세 페이지는 모든 태스크에 걸친 총 시간, 지역성 수준 요약(Locality level summary), Shuffle Read Size / Records, 연관 Job IDs 같은 정보로 시작해요.
또한 이 스테이지의 방향성 비순환 그래프(DAG)의 시각적 표현을 보여줘요. 여기서 정점은 RDD 또는 DataFrame을, 간선은 적용될 연산을 나타내요. 노드는 DAG 시각화에서 연산 범위(operation scope)별로 그룹화되고 연산 범위 이름(BatchScan, WholeStageCodegen, Exchange 등)으로 라벨링돼요. 특히 whole-stage 코드 생성 연산은 코드 생성 id로도 주석이 달려 있어요. Spark DataFrame 또는 SQL 실행에 속하는 스테이지의 경우, 이를 통해 스테이지 실행 상세를 SQL 탭의 관련 쿼리와 상호 참조할 수 있어요.
모든 태스크에 대한 요약 지표는 표와 타임라인으로 표현돼요:
- 태스크 역직렬화 시간 (Task deserialization time): 실행되기 전에 executor에서 태스크 클로저를 역직렬화하는 데 소요된 시간
- 태스크 기간 (Duration of tasks)
- GC 시간 (GC time): 총 JVM 가비지 컬렉션 시간
- 결과 직렬화 시간 (Result serialization time): 드라이버로 다시 보내기 전에 executor에서 태스크 결과를 직렬화하는 데 소요된 시간
- 결과 가져오기 시간 (Getting result time): 드라이버가 워커에서 태스크 결과를 가져오는 데 소요하는 시간
- 스케줄러 지연 (Scheduler delay): 태스크가 실행되도록 스케줄링되기를 기다리는 시간
- 최고 실행 메모리 (Peak execution memory): shuffle, 집계, 조인 중 생성된 내부 데이터 구조가 사용한 최대 메모리
- Shuffle Read Size / Records: 읽은 총 shuffle 바이트로, 로컬에서 읽은 데이터와 원격 executor에서 읽은 데이터를 모두 포함
- Shuffle Read Fetch Wait Time: 태스크가 원격 머신에서 shuffle 데이터가 읽히기를 차단된 채 기다리는 데 소요된 시간
- Shuffle Remote Reads: 원격 executor에서 읽은 총 shuffle 바이트
- Shuffle Write Time: 태스크가 shuffle 데이터를 쓰는 데 소요된 시간
- Shuffle spill (memory): 메모리에서 shuffle된 데이터의 역직렬화된 형태의 크기
- Shuffle spill (disk): 디스크에 있는 데이터의 직렬화된 형태의 크기
같은 지표가 executor별로 집계되어도 보여요. Accumulators는 변환 안에서 갱신될 수 있는 공유 변수예요. 여기에는 이름이 지정된 accumulator만 표시돼요. 마지막으로 태스크 테이블은 태스크별로 나눈 같은 정보를 보여주며, executor 로그와 실패에 대한 태스크 시도 번호에 대한 링크를 제공해요.
Storage 탭 (Storage Tab)
Storage 탭은 애플리케이션에서 (있을 경우) 영속화된 RDD와 DataFrame을 표시해요. 요약 페이지는 모든 RDD의 스토리지 레벨, 크기, 파티션을 보여주고, 상세 페이지는 RDD 또는 DataFrame의 모든 파티션의 크기와 사용 중인 executor를 보여줘요.
scala> import org.apache.spark.storage.StorageLevel._
import org.apache.spark.storage.StorageLevel._
scala> val rdd = sc.range(0, 100, 1, 5).setName("rdd")
rdd: org.apache.spark.rdd.RDD[Long] = rdd MapPartitionsRDD[1] at range at <console>:27
scala> rdd.persist(MEMORY_ONLY_SER)
res0: rdd.type = rdd MapPartitionsRDD[1] at range at <console>:27
scala> rdd.count
res1: Long = 100
scala> val df = Seq((1, "andy"), (2, "bob"), (2, "andy")).toDF("count", "name")
df: org.apache.spark.sql.DataFrame = [count: int, name: string]
scala> df.persist(DISK_ONLY)
res2: df.type = [count: int, name: string]
scala> df.count
res3: Long = 3
위 예제를 실행하면 Storage 탭에 두 개의 RDD가 나열된 것을 확인할 수 있어요. 스토리지 레벨, 파티션 수, 메모리 오버헤드 같은 기본 정보가 제공돼요. 참고로 새로 영속화된 RDD나 DataFrame은 구체화(materialize)되기 전에는 탭에 표시되지 않아요. 특정 RDD나 DataFrame을 모니터링하려면 action 연산이 트리거되었는지 확인하세요.
RDD 이름 'rdd'를 클릭하면 클러스터의 데이터 분포와 같은 데이터 영속화의 상세 내용을 얻을 수 있어요.
Environment 탭 (Environment Tab)
Environment 탭은 Spark 애플리케이션이 기대하는 구성으로 실행되고 있는지 확인하는 곳이에요. 환경과 구성 정보를 페이지 왼쪽을 따라 있는 하위 탭 집합으로 그룹화하며, 하나를 클릭하면 오른쪽 패널이 전환돼요.
하위 탭은 다음과 같아요:
- Runtime Information — 드라이버의 JVM, Scala 및 기타 런타임 속성
- Spark Properties — 유효한 애플리케이션 속성 (예:
spark.app.name,spark.driver.memory). 참고로spark.hadoop.*속성은 Hadoop Properties가 아니라 여기에 나열돼요. - Resource Profiles — 사용 중인 각 리소스 프로파일에 대한 CPU, 메모리, 가속기 리소스 요청
- Hadoop Properties — Hadoop 및 YARN 구성 파일에서 로드된 값
- System Properties — 기본 JVM 시스템 속성
- Metrics Properties — 메트릭 시스템을 위해 로드된 구성
- Classpath Entries — 드라이버에 로드된 클래스들을 소스별로 나눈 것. 클래스 충돌을 추적할 때 유용해요.
Executors 탭 (Executors Tab)
Executors 탭은 드라이버를 포함해 애플리케이션에 할당된 모든 executor를 나열해요. 각 행은 리소스 사용량(메모리, 디스크, 코어), 캐시된 데이터를 위해 예약된 스토리지 메모리, 태스크 수, shuffle 합계, GC 시간 같은 성능 신호를 보여줘요.
각 행은 Thread Dump, Heap Histogram, Flame Graph 같은 상세 링크 집합을 지니며, 이는 페이지를 벗어나지 않고 측면 패널에서 해당 executor의 해당 실시간(live) 데이터를 엽니다. 패널은 왼쪽 가장자리를 끌어 크기를 조정할 수 있어요. stderr와 stdout 링크는 새 뷰에서 executor의 로그 파일을 열어요. 해당 로그의 정확한 위치는 클러스터 매니저에 따라 달라요 (자세한 내용은 Monitoring and Instrumentation 참고).
SQL 탭 (SQL Tab)
쿼리 목록 (Query Listing)
SQL 탭은 Spark 애플리케이션에 제출된 모든 SQL 및 DataFrame 쿼리를 나열해요. 실행을 트리거하는 모든 DataFrame action(count, show, write 등)이 여기에 나타나며, SQL 문자열로 작성된 쿼리뿐만이에요. 몇 개의 항목을 생성하는 짧은 예제는 다음과 같아요:
df = spark.createDataFrame([(1, "andy"), (2, "bob"), (2, "andy")], ["count", "name"])
df.count()
df.createOrReplaceTempView("df")
spark.sql("SELECT name, SUM(count) FROM df GROUP BY name").show()
목록은 컬럼별 정렬, 검색, 상태별 필터링, 페이지네이션을 지원하므로, 오래 실행되는 애플리케이션에서 특정 쿼리를 쉽게 찾을 수 있어요.
SQL 계획 시각화 (SQL Plan Visualization)
목록의 각 쿼리는 연산자의 그래프 뷰를 가져요. 각 노드는 연산자 이름과 함께 지표를 인라인으로 보여주고, 간선은 데이터 흐름을 따라가요. 그래프를 패닝(pan)·줌해 큰 계획을 탐색하고, 이름으로 노드를 검색하며, 노드를 클릭해 전체 상세 내용이 담긴 측면 패널을 열 수 있어요.
실행 상세 페이지 (Execution Detail Page)
쿼리 목록의 행의 ID 또는 Description 링크를 클릭해 여는 실행 상세 페이지는, 단일 쿼리에 대해 기록된 모든 것을 모아 보여줘요. 헤더는 쿼리의 제출 시간, 기간, 상태, 설명, 그리고 그와 연관된 작업과 스테이지를 나열해요. SQL Plan Visualization은 연산자 그래프를 보여줘요. 페이지 하단의 "Details" 링크는 파싱·분석·최적화된 논리 계획과 물리 계획의 전체 텍스트를 펼쳐 보여줘요. 계획 중에 Spark가 쿼리를 어떻게 변환했는지 보고 싶을 때 유용해요.
SQL 지표 (SQL metrics)
SQL Plan Visualization의 각 노드는 자체 지표를 인라인으로 지녀요. 이 지표들은 각 연산자의 실행 상세에 들어가고 싶을 때 유용해요. 예를 들어 number of output rows는 Filter 연산자를 통과하는 행 수를 보여주고, Exchange의 shuffle bytes written은 shuffle이 쓴 데이터 양을 보여줘요.
SQL 지표 목록은 다음과 같아요:
| SQL 지표 | 의미 | 연산자 |
|---|---|---|
number of output rows |
연산자의 출력 행 수 | Aggregate 연산자, Join 연산자, Sample, Range, Scan 연산자, Filter 등 |
data size |
연산자의 broadcast/shuffled/collected 데이터 크기 | BroadcastExchange, ShuffleExchange, Subquery |
time to collect |
데이터 수집에 소요된 시간 | BroadcastExchange, Subquery |
scan time |
데이터 스캔에 소요된 시간 | ColumnarBatchScan, FileSourceScan |
metadata time |
파티션 수, 파일 수 같은 메타데이터를 얻는 데 소요된 시간 | FileSourceScan |
shuffle bytes written |
쓴 바이트 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
shuffle records written |
쓴 레코드 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
shuffle write time |
shuffle 쓰기에 소요된 시간 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
remote blocks read |
원격으로 읽은 블록 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
remote bytes read |
원격으로 읽은 바이트 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
remote bytes read to disk |
원격에서 로컬 디스크로 읽은 바이트 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
local blocks read |
로컬로 읽은 블록 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
local bytes read |
로컬로 읽은 바이트 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
fetch wait time |
데이터 가져오기에 소요된 시간 (로컬 및 원격) | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
records read |
읽은 레코드 수 | CollectLimit, TakeOrderedAndProject, ShuffleExchange |
sort time |
정렬에 소요된 시간 | Sort |
peak memory |
연산자의 최고 메모리 사용량 | Sort, HashAggregate |
spill size |
연산자가 메모리에서 디스크로 스필(spill)한 바이트 수 | Sort, HashAggregate |
time in aggregation build |
집계에 소요된 시간 | HashAggregate, ObjectHashAggregate |
avg hash probe bucket list iters |
집계 중 조회당 평균 버킷 리스트 반복 횟수 | HashAggregate |
data size of build side |
빌드된 해시 맵의 크기 | ShuffledHashJoin |
time to build hash map |
해시 맵 빌드에 소요된 시간 | ShuffledHashJoin |
task commit time |
쓰기가 성공한 후 태스크 출력 커밋에 소요된 시간 | 파일 기반 테이블에 대한 모든 쓰기 연산 |
job commit time |
쓰기가 성공한 후 작업 출력 커밋에 소요된 시간 | 파일 기반 테이블에 대한 모든 쓰기 연산 |
data sent to Python workers |
Python 워커로 보낸 직렬화된 데이터의 바이트 수 | Python UDFs, Pandas UDFs, Pandas Functions API 및 Python Data Source |
data returned from Python workers |
Python 워커에서 다시 받은 직렬화된 데이터의 바이트 수 | Python UDFs, Pandas UDFS, Pandas Functions API 및 Python Data Source |
Structured Streaming 탭 (Structured Streaming Tab)
Structured Streaming 작업을 마이크로 배치(micro-batch) 모드로 실행할 때, Web UI에서 Structured Streaming 탭을 사용할 수 있어요. 개요 페이지는 실행 중이고 완료된 쿼리에 대한 몇 가지 간단한 통계를 표시해요. 또한 실패한 쿼리의 최신 예외를 확인할 수 있어요. 자세한 통계는 테이블에서 "run id"를 클릭하세요.
통계 페이지는 스트리밍 쿼리 상태에 대한 통찰을 위한 유용한 지표 몇 가지를 표시해요. 현재는 다음 지표가 포함돼 있어요.
- Input Rate. (모든 소스에 걸친) 도착하는 데이터의 총 비율
- Process Rate. Spark가 데이터를 처리하는 (모든 소스에 걸친) 총 비율
- Input Rows. 트리거에서 처리된 (모든 소스에 걸친) 총 레코드 수
- Batch Duration. 각 배치의 처리 기간
- Operation Duration. 다양한 연산을 수행하는 데 걸린 시간(밀리초). 추적되는 연산은 다음과 같아요.
- addBatch: 소스에서 마이크로 배치의 입력 데이터를 읽고, 처리하고, 배치의 출력을 싱크에 쓰는 데 걸린 시간. 마이크로 배치 시간의 대부분을 차지해야 해요.
- getBatch: 소스에서 현재 마이크로 배치의 입력을 읽을 논리 쿼리를 준비하는 데 걸린 시간
- latestOffset & getOffset: 이 소스의 최대 사용 가능 오프셋을 조회하는 데 걸린 시간
- queryPlanning: 실행 계획을 생성하는 데 걸린 시간
- walCommit: 오프셋을 메타데이터 로그에 쓰는 데 걸린 시간
- Global Watermark Gap. 배치의 배치 타임스탬프와 글로벌 워터마크 사이의 간격
- Aggregated Number Of Total State Rows. 총 상태 행의 집계 수
- Aggregated Number Of Updated State Rows. 갱신된 상태 행의 집계 수
- Aggregated State Memory Used In Bytes. 사용된 상태 메모리의 집계 바이트 수
- Aggregated Number Of State Rows Dropped By Watermark. 워터마크에 의해 버려진 상태 행의 집계 수
조기 릴리스 버전으로서 통계 페이지는 아직 개발 중이며 향후 릴리스에서 개선될 예정이에요.
Streaming (DStreams) 탭 (Streaming (DStreams) Tab)
애플리케이션이 DStream API로 Spark Streaming을 사용하면 웹 UI에 Streaming 탭이 포함돼요. 이 탭은 데이터 스트림의 각 마이크로 배치에 대한 스케줄링 지연과 처리 시간을 표시하며, 스트리밍 애플리케이션을 문제 해결하는 데 유용할 수 있어요.
JDBC/ODBC Server 탭 (JDBC/ODBC Server Tab)
Spark가 분산 SQL 엔진으로 실행될 때 이 탭을 볼 수 있어요. 세션과 제출된 SQL 연산에 대한 정보를 보여줘요.
페이지의 첫 번째 섹션은 JDBC/ODBC 서버에 대한 일반 정보, 즉 시작 시간과 가동 시간을 표시해요.
두 번째 섹션은 활성 및 완료된 세션에 대한 정보를 포함해요.
- 연결의 사용자와 IP
- 세션 정보에 접근하는 session id 링크
- 세션의 시작 시간, 완료 시간, 기간
- Total execute는 이 세션에서 제출된 연산 수
세 번째 섹션은 제출된 연산의 SQL 통계를 가져요.
- 연산을 제출한 사용자
- jobs 탭으로 가는 job id 링크
- 모든 작업을 함께 그룹화하는 쿼리의 group id. 애플리케이션은 이 group id를 사용해 실행 중인 모든 작업을 취소할 수 있어요.
- 연산의 시작 시간
- 결과를 가져오기 전 실행의 완료 시간
- 결과를 가져온 후 연산의 종료(close) 시간
- Execution time은 완료 시간과 시작 시간의 차이
- Duration time은 종료 시간과 시작 시간의 차이
- Statement는 실행 중인 연산
- 프로세스의 상태
- Started: 프로세스가 시작될 때의 첫 상태
- Compiled: 실행 계획이 생성됨
- Failed: 실행이 실패하거나 오류로 끝났을 때의 최종 상태
- Canceled: 실행이 취소되었을 때의 최종 상태
- Finished processing and waiting to fetch results: 처리가 끝나고 결과를 가져오기를 기다림
- Closed: 클라이언트가 statement를 닫았을 때의 최종 상태
- 파싱된 논리 계획, 분석된 논리 계획, 최적화된 논리 계획, 물리 계획 또는 SQL 문의 오류를 포함한 실행 계획 상세
더 알아보기 (Learn more)
- 아파치 스파크 웹 UI (원문)
- Monitoring and Instrumentation — Spark 모니터링·계측 가이드
- Configuration — Spark 구성 레퍼런스