DistCp 는 MapReduce 잡이다. 그래서 실행 환경에 MapReduce 라이브러리가 제대로 잡혀 있어야 하고, 그 라이브러리가 한 벌만 있어야 한다. Invalid HADOOP_MAPRED_HOME 은 한 벌도 못 찾은 경우이고, 클래스 캐스팅 오류는 두 벌 이상이 섞인 경우다.
HADOOP_MAPRED_HOME 은 MapReduce 프레임워크의 설치 경로를 가리킨다. 값이 비었거나, 가리키는 디렉터리 아래에 share/hadoop/mapreduce 또는 클라이언트 jar 이 없으면 이 오류가 난다.
먼저 실제 경로를 찾는다.
find /opt/cloudera/parcels -maxdepth 4 -type d -name "hadoop-mapreduce*" 2>/dev/null
ls -d /usr/lib/hadoop-mapreduce
Cloudera parcel 배포에서는 보통 다음 경로다.
export HADOOP_MAPRED_HOME=/opt/cloudera/parcels/CDH/lib/hadoop-mapreduce
export HADOOP_COMMON_HOME=/opt/cloudera/parcels/CDH/lib/hadoop
export HADOOP_HDFS_HOME=/opt/cloudera/parcels/CDH/lib/hadoop-hdfs
설정한 뒤에는 디렉터리 내용이 보이는지 확인한다.
ls $HADOOP_MAPRED_HOME | head
hadoop-mapreduce-client-core*.jar 과 lib/ 이 보이면 맞다.
주의할 점은 어느 프로세스의 환경에 넣느냐다. 셸에서 직접 돌린다면 ~/.bashrc 로 충분하지만, NiFi · Oozie · systemd 서비스에서 DistCp 를 부른다면 그 프로세스의 환경에 들어가야 한다. CM 관리 서비스라면 해당 역할의 환경 Advanced Configuration Snippet(Safety Valve) 에 넣는다.
cannot cast to class com.cloudera.enterprise.distcp.acllib.copy.ListingFileStatus
Cloudera 의 BDR 용 DistCp 는 upstream Apache DistCp 와 클래스가 다르다. 두 구현의 jar 이 같은 클래스패스에 함께 들어가면, 한쪽이 만든 객체를 다른 쪽 클래스로 캐스팅하려다 이 오류가 난다.
확인은 클래스패스에 distcp 관련 jar 이 몇 개나 들어 있는지 세어 보는 것으로 시작한다.
hadoop classpath | tr ':' '\n' | grep -i distcp
두 개 이상, 특히 버전이 다른 것이 같이 나오면 그것이 원인이다. 손댈 곳은 셋이다.
첫째, 직접 넣은 jar 을 뺀다. 사용자 잡의 --libjars, NiFi 프로세서의 추가 리소스, HADOOP_CLASSPATH 에 수동으로 넣은 경로를 먼저 의심한다.
둘째, Apache 배포와 Cloudera 배포를 섞지 않는다. parcel 로 배포된 클러스터에서 별도로 내려받은 Apache Hadoop tarball 의 jar 을 끌어 쓰면 반드시 어긋난다.
셋째, 업그레이드 잔재를 정리한다. parcel 을 올린 뒤 이전 버전 경로가 alternatives 나 심볼릭 링크로 남아 있으면 옛 jar 이 계속 딸려 온다.
BDR 복제 정책이 도는 중이라면 이 오류는 보통 클러스터 사이 버전 차이에서 온다. 원본과 대상 클러스터의 CDH/CDP 버전과 CM 버전이 지원되는 조합인지 확인한다.