Cloudera AI 에서 커스텀 런타임 이미지를 쓰거나 런타임 애드온을 붙일 때 겪는 네 가지 문제를 정리한다. job 의 런타임 이미지가 바뀌지 않는 문제, 애드온과 이미지의 OS 버전 불일치, 세션은 떴는데 화면이 열리지 않는 문제, 커스텀 이미지가 커널을 찾지 못하는 문제다.
UI 에서 job 설정을 바꿔 저장해도 실제로 반영되지 않는 알려진 이슈가 있다. 내부적으로 job accelerator label ID 타입 오류가 나면서 편집이 실패하는데, 화면에는 저장된 것처럼 보인다. 값은 반영됐는데 편집 화면에만 이전 값이 표시되는 별개의 표시 버그도 있으므로, get_job 으로 실제 값을 확인해 둘을 구분한다.
해결은 UI 대신 API 로 필요한 필드만 부분 업데이트하는 것이다.
import cmlapi
client = cmlapi.default_client() # 세션 환경변수를 사용, 키를 코드에 넣지 않는다
project_id = "<project_id>"
job_id = "<job_id>"
for rt in client.list_runtimes().runtimes:
print(rt.image_identifier)
update_body = cmlapi.Job(runtime_identifier="<new_runtime_identifier>")
client.update_job(update_body, project_id, job_id)
print(client.get_job(project_id, job_id).runtime_identifier)
job 딕셔너리를 통째로 보내면 schedule 이 비어 있을 때 parent_id 가 유실되는 식으로 업데이트가 꼬인다. 전체를 보내야 하는 구조라면 보내기 전에 schedule 키를 제거한다. 지정하려는 런타임이 해당 프로젝트의 allowlist 에 있는지도 확인한다.
세션에서 hdfs 같은 명령이 ld.so 로더 오류로 실행되지 않으면 런타임 애드온의 JDK 가 요구하는 GLIBC 버전이 런타임 이미지의 GLIBC 보다 높은 경우다. JVM 이 시작조차 못 하므로 core-site.xml 설정은 읽히지도 않는다.
ldd --version | head -1
readlink -f $(which java)
ls /usr/lib/jvm/ /runtime-addons/
echo $JAVA_HOME
/usr/lib/jvm 아래에 애드온이 아닌 베이스 이미지의 JDK 가 따로 있으면 JAVA_HOME 과 PATH 를 그쪽으로 돌려 임시로 우회할 수 있다. 정식 해결은 Administration 의 Runtime Add-ons 에서 현재 런타임 이미지의 OS 와 맞는 Hadoop CLI 애드온 버전을 선택하는 것이다. 업그레이드된 배포판에는 호환성을 위해 여러 버전의 애드온이 남아 있다.
hadoop.security.lib.native.load 라는 프로퍼티는 존재하지 않는다. native 라이브러리 비활성화 옵션은 io.native.lib.available 이다.
파드가 Running 이고 로그에 Pod is ready 와 등록 성공이 찍혔다면 백엔드는 정상이고 접속 경로 문제다.
Cloudera AI 는 세션마다 tty-<session-id>.<namespace>.apps.<base-domain> 형태의 하위 서브도메인을 동적으로 만든다. 따라서 DNS 에 해당 와일드카드 레코드가 있어야 하고, 인증서가 그 깊이를 커버해야 한다. *.apps.<base-domain> 인증서는 tty-xxx.<namespace>.apps.<base-domain> 같은 2단계 하위를 커버하지 못한다. 이것이 실무에서 가장 흔한 원인이다.
nslookup tty-<session-id>.<ns>.apps.<base-domain>
openssl s_client -connect tty-<session-id>.<ns>.apps.<base-domain>:443 \
-servername tty-<session-id>.<ns>.apps.<base-domain> </dev/null 2>/dev/null \
| openssl x509 -noout -text | grep -A2 "Subject Alternative Name"
브라우저 개발자 도구의 Network 탭에서 웹소켓 연결이 101 Switching Protocols 로 올라가는지 본다. 계속 pending 이거나 실패하면 로드밸런서나 프록시가 웹소켓 업그레이드를 막는 것이고, 인증서나 이름 오류면 위의 DNS·SAN 문제다. HTTPS 로 접속했는데 UI 설정이 HTTP 로 되어 있으면 ws:// 로 붙으려다 Mixed Content 로 차단된다.
kubectl -n <ns> describe pod <session-pod>
kubectl -n <ns> logs <session-pod> --all-containers --tail=200
kubectl -n <ns> logs deploy/web --tail=200
kubectl -n <ns> logs deploy/livelog --tail=200
kubectl -n <ns> get ingress
로그에 kinit 타임아웃과 TGT does not exist yet 이 보이면 해당 사용자에게 keytab 또는 principal 이 등록되지 않은 상태다. 세션 기동은 되지만 Spark 나 HDFS 접근에서 실패하므로 User Settings 에서 등록한다.
CRIT EngineInit.Cdsw — Runtime executable not found: /usr/local/bin/ml-runtime-kernel
"isPBJRuntime": false
Workbench 커널 실행 파일이 없는 베이스로 이미지를 빌드했는데 엔진이 일반 Workbench 런타임으로 인식해 커널을 찾다가 실패한 것이다. 이미지와 메타데이터 라벨이 맞지 않는 문제다.
Workbench 런타임으로 가려면 Dockerfile 의 FROM 을 Cloudera 가 배포하는 ML Runtime Workbench 베이스 이미지로 지정한다. 순수 python 이나 ubi 이미지에서 시작하면 커널 바이너리가 없다.
PBJ Workbench 로 가려면 PBJ 베이스 이미지를 쓰고 라벨을 명시한다.
LABEL com.cloudera.ml.runtime.editor="PBJ Workbench"
LABEL com.cloudera.ml.runtime.runtime-metadata-version="2"
repo assembly YAML 에도 editor: "PBJ Workbench" 와 runtime_metadata_version: 2 를 같게 넣는다.
확인 항목은 다음과 같다. 필수 라벨(editor, kernel, edition, version, full-version)과 메타데이터 버전이 모두 있는지, 재빌드 시 태그를 바꿔 push 했는지(같은 태그는 기존 등록분이 그대로 쓰일 수 있다), Runtime Catalog 에서 기존 등록을 지우고 다시 등록한 뒤 세션에서 런타임을 다시 선택했는지 본다.
docker run --rm <image> ls -l /usr/local/bin/