평소 잘 돌던 배치가 가끔 아래 두 메시지와 함께 실패한다.
ExitCodeException exitCode=127:
/usr/bin/env: 'python': No such file or directory
at org.apache.hadoop.util.Shell.runCommand(Shell.java:1008)
WARN [AsyncDispatcher event handler] org.apache.hadoop.net.ScriptBasedMapping:
Exception running /etc/hadoop/conf.cloudera.yarn/topology.py 10.0.0.28
둘은 별개의 로그처럼 보이지만 같은 원인에서 나온다. 셸이 python 이라는 이름을 찾지 못한다.
셸의 종료 코드 127 은 "명령을 찾지 못했다" 이다. 컨테이너 안에서 실행된 스크립트가 존재하지 않거나, 실행 권한이 없거나, PATH 에서 해석되지 않았을 때 나온다. 애플리케이션 로그보다 먼저 NodeManager 쪽 launch script 와 stderr 를 본다.
yarn logs -applicationId ${APP_ID} -log_files stderr,launch_container.sh | head -80
launch_container.sh 에는 컨테이너가 실제로 실행한 명령줄과 환경 변수가 그대로 들어 있다. 어떤 실행 파일을 못 찾았는지가 stderr 첫 줄에 나온다.
python 이 없다RHEL 8 · Rocky 8 부터 시스템에 /usr/bin/python 이 기본으로 존재하지 않는다. python3 만 설치되며, python 이라는 이름은 관리자가 명시적으로 지정해야 생긴다. Hadoop 배포판이 함께 깔아 둔 스크립트 중에는 셔뱅이 #!/usr/bin/env python 인 것이 남아 있어 그대로 실패한다.
Cloudera 의 rack 인식 스크립트 topology.py 가 대표적이다. 이 스크립트가 실패하면 ScriptBasedMapping 이 노드의 rack 을 결정하지 못하고, 해당 노드는 기본 rack 으로 떨어지거나 컨테이너 배치 판단이 지연된다. 간헐적으로만 증상이 보이는 이유는, 이미 매핑이 캐시된 노드에는 스크립트가 다시 실행되지 않기 때문이다. 새 노드나 재시작 직후, 캐시가 비워진 시점에만 드러난다.
ls -l /usr/bin/python /usr/bin/python3
head -1 /etc/hadoop/conf.cloudera.yarn/topology.py
ls -l /etc/hadoop/conf.cloudera.yarn/topology.py /etc/hadoop/conf.cloudera.yarn/topology.map
# 스크립트를 직접 실행해 본다
/etc/hadoop/conf.cloudera.yarn/topology.py 10.0.0.28
정상이면 /default-rack 같은 문자열 한 줄이 나온다. No such file or directory 가 나오면 이 문제다.
alternatives 로 시스템 전역에 python 이름을 만든다. 이 방식은 RPM 이 관리하므로 패키지 갱신 후에도 유지된다.
alternatives --list | grep -i python
alternatives --set python /usr/bin/python3
python --version
RHEL 계열에서 alternatives --set python 은 python3 또는 python2 중 설치된 것을 가리키게 한다. 후보가 등록돼 있지 않으면 dnf install python3 으로 먼저 설치한다. 심볼릭 링크를 손으로 만드는 방법(ln -s /usr/bin/python3 /usr/bin/python)은 동작하지만, 패키지 갱신 때 충돌할 수 있어 권하지 않는다.
클러스터의 모든 노드에 같은 조치를 한다. 한 노드만 빠져 있으면 그 노드에 컨테이너가 배정될 때만 실패하는, 진단하기 까다로운 간헐 장애가 된다.
topology.py 자체가 Python 2 문법(print "...")으로 돼 있으면 python 을 python3 으로 돌린 순간 문법 오류가 난다. 그 경우 스크립트를 Python 3 문법으로 고치거나, 셔뱅을 #!/usr/bin/env python2 로 명시하고 python2 를 설치한다.
#!/usr/bin/env python3
import sys
for arg in sys.argv[1:]:
print("/default-rack")
실행 권한과 소유자도 확인한다. NodeManager 가 도는 계정(보통 yarn)이 읽고 실행할 수 있어야 한다.
chmod 755 /etc/hadoop/conf.cloudera.yarn/topology.py
rack 매핑이 실패하면 즉시 서비스가 멈추지는 않지만 다음이 어긋난다.
ScriptBasedMapping 호출이 매번 실패하면서 ResourceManager 의 이벤트 처리 지연이 누적된다.간헐적이라는 이유로 넘기지 말고 전 노드에서 정리한다.