NVIDIA NIM 모델(gpt-oss, Nemotron, EmbedQA/RerankQA 등)을 Cloudera AI 1.5.5 SP3 폐쇄망에 반입하려면 Hugging Face 와 달리 NGC CLI · NIM CLI(nimcli) · Cloudera 가 배포하는 NGC 스펙 파일 · NGC API 키가 추가로 필요하다. 다운로드는 import_to_airgap.py -rt ngc 가 내부적으로 nimcli download 를 호출하는 구조이고, 업로드는 HF 와 같은 S3 업로드다. 이 문서는 H100 2장 기준으로 프로파일을 고르고 수십 GB 모델을 안정적으로 받는 절차를 정리한 것이다. 버킷 준비와 업로드·등록은 Cloudera AI 폐쇄망 모델 반입 — Hugging Face와 같다.
# NGC CLI — https://org.ngc.nvidia.com/setup/installers/cli 에서 리눅스용 zip
unzip ngccli_linux.zip -d /opt && export PATH=$PATH:/opt/ngc-cli
ngc config set # API key, org, 출력 형식(ascii 기본)
# NIM CLI — early access 승인 후 NGC 로 설치 파일을 받는다
ngc registry resource download-version nvidia/nim-tools/nimtools_installer:0.0.8
cd nimtools_installer_v0.0.8
python3 nimtools_installer.py --ngc-api-key "$NGC_API_KEY" # --nimcli-only 를 빼야 nimlib 까지 설치된다
nimcli --version && python -c "import nimlib"
# 스펙 파일과 매니페스트 — GitHub 웹페이지가 아니라 raw 또는 git clone 으로 받는다
git clone https://github.com/cloudera/Model-Hub.git
ls Model-Hub/models/airgapped/private/ # 예: 1.56.0-h3000_concatenated.yaml (h3000 = 1.5.5 SP3 빌드)
nimcli 는 Python 3.10.12 이상 3.11 미만을 요구한다. 매니페스트 폴더(Model-Hub/manifests/)는 스펙 파일과 같은 디렉터리 기준으로 ./manifests/<버전>/nim/... 경로로 찾으므로 import_to_airgap.py 를 실행하는 디렉터리에 두어야 한다. --nimcli-only 로 설치하면 ModuleNotFoundError: No module named 'nimlib' 로 다운로드가 조용히 실패한다.
SPEC=./1.56.0-h3000_concatenated.yaml
python import_to_airgap.py -ns $SPEC --list-all
python import_to_airgap.py -ns $SPEC -m "GPT-OSS" --list-variants
python import_to_airgap.py -ns $SPEC -m "GPT-OSS" -vid "GPT-OSS 20B" --list-profiles
# → nim/openai/gpt-oss-20b:hf-d666cf3-nim, ...-tp2, ...-tp4, ...-tp8
# 매니페스트에서 정밀도·TP·최소 VRAM 대조
grep -E "^- id:|llm_engine|precision:|tp:|min_vram" manifests/1.17.0/nim/nvidia/nemotron-3-nano.yaml | paste - - - - -
tp 는 tensor parallel, 곧 필요한 GPU 장수다. H100(Hopper) 은 FP8 을 지원하므로 fp8 프로파일을 우선하고, nvfp4 는 Blackwell 네이티브 포맷이라 H100 에서 돌지 않을 수 있다. min_vram_per_device_gb 가 GPU 메모리를 넘는 프로파일(gpt-oss-120b 는 243GB)은 받아도 배포되지 않는다. 같은 사양에 해시가 둘이면 llm_engine(vllm / tensorrt_llm) 이 다른 것이다. 스펙 파일이 YAML 로 파싱되지 않고 CSS 가 보이면 GitHub HTML 페이지를 저장한 것이다.
#!/usr/bin/env bash
# 사용: export NGC_API_KEY='nvapi-...'; nohup ./model_download_ngc.sh > ngc_download.log 2>&1 &
set -u
SPEC=./1.56.0-h3000_concatenated.yaml
DEST=/data/model
export NGC_API_KEY="${NGC_API_KEY:?NGC_API_KEY 를 먼저 export 하세요}" # nimcli 는 ngc config 가 아니라 이 변수를 본다
SUCCESS_FILE=ngc_success.txt; FAILED_FILE=ngc_failed.txt; MIN_MB=10
PROFILES=(
"nim/nvidia/llama-3.2-nv-embedqa-1b-v2:h100x1-trt-fp16-td9i48e6ow"
"nim/nvidia/llama-3.2-nv-rerankqa-1b-v2:extra-e850d59a"
"nim/nvidia/nemotron-parse:hf-v5"
"nim/nvidia/nemotron-3-nano:hf-fp8-f25a17a-tp2"
"nim/openai/gpt-oss-20b:hf-d666cf3-nim"
)
touch "$SUCCESS_FILE"; : > "$FAILED_FILE"
for p in "${PROFILES[@]}"; do
grep -qxF "$p" "$SUCCESS_FILE" && { echo "SKIP $p"; continue; }
python import_to_airgap.py -do -rt ngc -p "$DEST" -ns "$SPEC" -ri "$p"
sz=$(du -sm "$DEST/ngc/$(basename "$p")" 2>/dev/null | cut -f1); sz=${sz:-0}
if [ "$sz" -lt "$MIN_MB" ]; then echo "$p" >> "$FAILED_FILE"; else echo "$p" >> "$SUCCESS_FILE"; fi
done
종료 코드를 믿지 않고 디렉터리 크기로 판정하는 이유는, 스크립트가 파싱 오류(Invalid version)를 만나면 메타데이터만 만들고 성공으로 끝내기 때문이다. 스크립트를 우회해 직접 받을 때는 매니페스트의 프로파일 해시로 호출한다.
nimcli download --profiles <해시> \
--manifest-file ./manifests/1.14.0/nim/openai/gpt-oss-20b.yaml \
--model-cache-path "$DEST/ngc/gpt-oss-20b:hf-d666cf3-nim/artifacts" --use-cache 2>&1 | tail -3
# 완료 판정: "Checksum verification passed ... missing: 0"
nimcli 는 파일 단위로 이어받는다. 체크섬이 통과한 파일은 Skipping download, using cached copy 로 건너뛰지만, 받다 끊긴 파일은 처음부터 다시 받는다(HTTP Range 이어받기가 아니다). 그래서 수십 GB safetensors 하나가 계속 끊기면 진전이 없고, 실패한 조각이 정리되지 않은 채 쌓여 20B 모델 디렉터리가 100GB 로 부풀 수 있다. 완료 여부는 크기가 아니라 missing: 0 으로 본다. 전송 엔진은 Rust(reqwest/tokio) 라 TOKIO_WORKER_THREADS=1 같은 환경 변수 외에는 병렬도(max_parallel_files=10) 를 조절할 옵션이 없다.
nimcli 가 ConnectionError ... hyper_util ... TimedOut 으로 실패한다. reqwest 는 자체 CA 번들만 신뢰하므로 시스템 CA 등록이나 SSL_CERT_FILE 로는 풀리지 않는다. echo | openssl s_client -connect xfiles.ngc.nvidia.com:443 | grep issuer 의 발급자가 Amazon/DigiCert 가 아니면 xfiles.ngc.nvidia.com, api.ngc.nvidia.com, files.ngc.nvidia.com 의 검사 예외를 요청한다.-stig-fips-x86 같은 접미사가 붙은 release 는 nimlib 가 버전으로 파싱하지 못한다. 이때는 extra-* 프로파일을 쓰거나 nimcli 를 직접 호출한다.nohup 과 재시도 루프를 쓰고, 아침에 find $DEST -name "*.incomplete" 와 du -sh 변화로 정체된 모델을 찾는다.h100x1-trt-fp16) 을 명시적으로 고른다. 누락되면 범용 ONNX 프로파일이 적용돼 배치 상한 3 으로 느려진다(NIM 임베딩 응답 지연 참조).export 로만 주입하며, 노출됐으면 폐기한다.