2021년 1월 25일 월요일

Spark Read Parquet - Timestamp and Timezone Confusion

Spark 배치에서 Parquet File을 데이터를 읽을 때 timestamp가 +0900시간이 되는 문제가 발생했다. timezone 문제인데 처음에는 win server to linux 마이그레이션 문제인 줄 알았는데 그게 아니었다. (txt로 저장하면 이런 문제가 없다.)

Spark 버전은 2.4.7 이다.

서버에서 timedatectl을 쳐보면 다음과 같다.


Time Zone이 Asia/Seoul (KST, +0900)으로 되어있다.
따라서 Spark에서 Parquet을 읽을 때 KST로 변환해서 읽는 것 같다. 

그럼 간단하게 생각하면.. UTC로 읽으면 해결될 문제이고 분산환경이기 driver, excuter 모두 해결되어야 할 문제 같은데 이 부분이 조금 찝찝하다.


어쨌든 방법 중에 한가지는 Spark Submit을 할 때 아래 옵션을 준다.

--conf spark.sql.session.timeZone='UTC' \
--conf spark.driver.extraJavaOptions='-Duser.timezone=UTC' \
--conf spark.executor.extraJavaOptions='-Duser.timezone=UTC' \

그럼 해결된다.

또 다른 방법은 코드 상에서 spark session을 생성할 때 옵션을 주고 해결이 가능하다.
.config("spark.sql.session.timeZone", "UTC") 
.config("spark.driver.extraJavaOptions", "-Duser.timezone=UTC") 
.config("spark.executor.extraJavaOptions", "-Duser.timezone=UTC")

아래는 공식문서에서 발췌한 내용이다.
Spark internally stores timestamps as UTC values, and timestamp data that is brought in without a specified time zone is converted as local time to UTC with microsecond resolution. When timestamp data is exported or displayed in Spark, the session time zone is used to localize the timestamp values. The session time zone is set with the configuration 'spark.sql.session.timeZone' and will default to the JVM system local time zone if not set.


분산환경이기도 하고 deploy mode에 따라 옵션들이 어떻게 동작하는지는 테스트해볼 필요가 있겠다.

--20210321 추가
송희진님께서 모든 스파크 배치에 일괄적용을 위해 spark_submit에 아래처럼 추가
exec "${SPARK_HOME}"/bin/spark-class org.apache.spark.deploy.SparkSubmit 
--conf spark.sql.session.timeZone='UTC' \
--conf spark.driver.extraJavaOptions='-Duser.timezone=UTC' \
--conf spark.executor.extraJavaOptions='-Duser.timezone=UTC' \
"$@"

2021년 1월 14일 목요일

HA hadoop+Spark 조합으로 namespace 사용할 때 발생할 수 있는 에러(UnknownHostException)

현재 HA hadoop + Spark + mesos + azkaban 조합으로 배치를 구성하고 있는데 서버에 직접 들어가서 shell script를 수행하면 정상적으로 동작을 한다.

scala source에서는 hadoop url을 namespace로 접근한다.

그러나 아즈카반에서 수행을 하면 에러를 뱉는다.

Exception in thread "main" java.lang.IllegalArgumentException: java.net.UnknownHostException: hadoop-cluster-bdnode
....
at org.apache.spark.deploy.SparkSubmit.main(SparkSubmit.scala)
Caused by: java.net.UnknownHostException: hadoop-cluster-bdnode
... 40 more
....
java.lang.RuntimeException: azkaban.jobExecutor.utils.process.ProcessFailureException: Process exited with code 1
...
Caused by: azkaban.jobExecutor.utils.process.ProcessFailureException: Process exited with code 1
at azkaban.jobExecutor.utils.process.AzkabanProcess.run(AzkabanProcess.java:125)
at azkaban.jobExecutor.ProcessJob.run(ProcessJob.java:304)


shell script에서는 동작할 때에는 hadoop conf(hdfs-site.xml, core-site.xml) 정보를 알고 있다. bashrc에 hadoop_conf_dir을 해놨기 때문이다. 하지만 스케쥴러 azkaban에서 수행하려고 하면 해당 구성을 다시 shell script에 export 해주거나 spark-submit file안에서 알려줘야 한다. 배치를 수행하는 command shell을 모두 바꿀 수가 없어서 그냥 후자로 적용했다.
export HADOOP_HOME=/data01/sw/hadoop
export HADOOP_CONF_DIR=$HADOOP_HOME/etc/hadoop


이제 잘 동작한다.




2022년 회고

 올해는 블로그 포스팅을 열심히 못했다. 개인적으로 지금까지 경험했던 내용들을 리마인드하자는 마인드로 한해를 보낸 것 같다.  대부분의 시간을 MLOps pipeline 구축하고 대부분을 최적화 하는데 시간을 많이 할애했다. 결국에는 MLops도 데이...