Spark 는 기본적으로 INFO 부터 찍어서 실제 출력이 로그에 묻힌다. 방법이 세 가지 있고 적용 시점이 다르다.
세션 안에서 즉시 바꾸기. 가장 간단하지만 SparkContext 가 만들어진 뒤라서 기동 과정의 로그는 이미 지나간 뒤다.
spark.sparkContext.setLogLevel("WARN")
sc.setLogLevel("WARN")
설정 파일로 바꾸기. 기동 로그까지 포함해 전부 적용된다. Spark 3.3 부터 로깅 백엔드가 log4j 1.x 에서 log4j2 로 바뀌었으므로 파일 이름과 문법이 다르다.
# Spark 3.3 이상 — $SPARK_HOME/conf/log4j2.properties
rootLogger.level = warn
logger.spark.name = org.apache.spark
logger.spark.level = warn
logger.hive.name = org.apache.hadoop.hive
logger.hive.level = error
# Spark 3.2 이하 — $SPARK_HOME/conf/log4j.properties
log4j.rootCategory=WARN, console
log4j.logger.org.apache.spark=WARN
conf 아래에는 .template 이 붙은 견본이 들어 있으므로 확장자를 떼고 복사해 고친다.
제출할 때만 다른 설정 파일 쓰기. 클러스터 기본 설정을 건드리지 않고 이 작업에만 적용한다. 파일을 --files 로 함께 올려야 실행 노드에서 찾는다.
spark-submit \
--files ./log4j2.properties \
--conf "spark.driver.extraJavaOptions=-Dlog4j.configurationFile=log4j2.properties" \
--conf "spark.executor.extraJavaOptions=-Dlog4j.configurationFile=log4j2.properties" \
job.py
log4j 1.x 시절의 속성 이름은 -Dlog4j.configuration=file:... 이었다. log4j2 는 -Dlog4j.configurationFile=... 이다. 이 차이 때문에 설정이 조용히 무시되는 경우가 많다.
conf = SparkConf().setMaster("local[4]").setAppName("MyApp")
sc = SparkContext.getOrCreate(conf)
print(sc.master) # yarn 이 찍힌다
getOrCreate 는 이름 그대로 이미 있으면 그것을 돌려준다. 그 경우 넘긴 conf 는 버려지고 기존 컨텍스트의 설정이 유지된다. pyspark 셸이나 노트북 커널은 시작할 때 이미 컨텍스트를 만들어 두므로 여기에 걸린다.
기존 컨텍스트를 닫고 새로 만든다.
from pyspark import SparkConf, SparkContext
if SparkContext._active_spark_context is not None:
SparkContext._active_spark_context.stop()
conf = SparkConf().setMaster("local[4]").setAppName("MyApp")
sc = SparkContext(conf=conf)
print(sc.master) # local[4]
SparkSession 을 쓴다면 같은 이유로 spark.stop() 을 먼저 부른다.
from pyspark.sql import SparkSession
SparkSession.builder.getOrCreate().stop()
spark = SparkSession.builder.master("local[4]").appName("MyApp").getOrCreate()
애초에 셸을 local 로 띄우는 편이 확실하다. 코드에서 setMaster 를 부르는 것보다 제출 인자가 우선순위 판단이 쉽다.
pyspark --master 'local[4]'
spark-submit --master 'local[*]' job.py
local[4] 는 스레드 4개, local[*] 는 코어 수만큼, local[4,2] 는 스레드 4개에 태스크 실패 시 재시도 2회를 뜻한다. local 모드에서는 드라이버 JVM 하나가 전부이므로 --executor-memory 는 효과가 없고 --driver-memory 를 조정한다.