Spark 애플리케이션은 드라이버 하나와 여러 익스큐터로 구성된다. 익스큐터는 어느 모드에서나 클러스터 안에서 실행되고, 달라지는 것은 드라이버가 어디서 도는가 뿐이다.
| 항목 | client 모드 | cluster 모드 |
|---|---|---|
| 드라이버 위치 | spark-submit 을 실행한 머신 |
클러스터가 배정한 컨테이너 (YARN 이면 ApplicationMaster) |
| 제출 셸과의 관계 | 셸이 끊기면 애플리케이션도 끝난다 | 제출 후 셸을 닫아도 계속 실행된다 |
| 표준 출력·로그 | 제출한 터미널에 바로 나온다 | yarn logs 나 웹 UI 로 확인 |
| 드라이버 자원 | 제출 머신의 CPU·메모리를 쓴다 | 클러스터 자원 풀에서 할당 |
| 네트워크 요구 | 익스큐터가 제출 머신의 드라이버 포트로 붙어야 한다 | 클러스터 내부 통신만 필요 |
spark-submit --master yarn --deploy-mode client --class com.example.Job job.jar
spark-submit --master yarn --deploy-mode cluster --class com.example.Job job.jar
대화형 도구는 client 모드만 가능하다. spark-shell · pyspark · Jupyter · Livy 세션처럼 드라이버가 사용자 입력을 받아야 하는 구조는 드라이버가 손이 닿는 곳에 있어야 한다.
정기 배치는 cluster 모드가 맞다. 제출 노드가 재부팅되거나 세션이 끊겨도 작업이 살아 있고, 드라이버 자원도 클러스터에서 관리된다. 드라이버가 실패하면 YARN 이 재시도할 수도 있다.
엣지 노드 한 대에서 client 모드 작업을 여러 개 돌리는 구성이 흔히 문제를 만든다. 드라이버가 전부 그 노드에 몰려 메모리가 부족해지고, 한 노드의 장애가 모든 작업에 영향을 준다.
client 모드에서는 드라이버가 이미 떠 있는 상태에서 설정이 적용되므로, 드라이버 관련 옵션 일부를 spark-submit 인자로만 줄 수 있다.
spark-submit --master yarn --deploy-mode client \
--driver-memory 4g \
--conf spark.driver.maxResultSize=2g \
...
코드 안에서 spark.driver.memory 를 설정해도 client 모드에서는 반영되지 않는다. cluster 모드에서는 드라이버도 새로 뜨므로 설정이 적용된다.
파일 경로 해석도 다르다. cluster 모드에서는 드라이버가 임의의 노드에서 뜨므로 로컬 경로가 존재하지 않을 수 있다. 의존 파일은 --files · --jars · --py-files 로 배포하거나 HDFS 경로를 쓴다.
spark-submit --master yarn --deploy-mode cluster \
--files hdfs:///conf/app.properties \
--py-files hdfs:///lib/mylib.zip \
main.py
yarn application -list -appStates RUNNING
yarn logs -applicationId application_1758000000000_0001 | less
yarn logs -applicationId application_1758000000000_0001 -am 1
cluster 모드에서 드라이버 로그를 보려면 ApplicationMaster 로그를 본다. 로그 집계가 켜져 있어야 종료 후에도 조회된다.
--master local[*] 에는 deploy mode 개념이 없다. 드라이버와 익스큐터가 한 JVM 안에서 돈다.spark.driver.host · spark.driver.port · spark.driver.bindAddress 를 맞춰야 한다.collect())은 모드와 무관하게 드라이버 메모리를 쓴다. cluster 모드라고 안전한 것이 아니다.