컨테이너를 바꾼 뒤에는 CUDA 오류가 나고, 드라이버를 올린 뒤에는 OOM이나 통신 오류가 나고, 동시성을 낮추면 이번에는 캐시 관련 로그가 나타나는 상황이 반복됩니다.
가장 빠른 해결법은 지금 당장 성공을 만들려는 것이 아니라 호스트, 컨테이너, 시작 명령, 요청 샘플을 먼저 고정한 뒤 호환성부터 단일 기능까지 한 변수씩 재현하는 것입니다. 공식 호환 기준에서도 같은 오류가 안정적으로 나오지 않으면 원래 클러스터에서 계속 수정하지 말고 격리 테스트 환경으로 옮겨야 합니다.
이번 주 실행 시간표
| 시점 | 실행할 작업 | 바꾸지 말아야 할 것 | 다음 단계로 넘어가는 조건 |
|---|---|---|---|
| 지금 | 최초 실패 현장 저장 | 이미지, 드라이버, 명령, 요청 | 첫 오류와 전체 로그가 보관됨 |
| 1단계 | CUDA와 드라이버 확인 | 추론 옵션과 동시성 | 장치와 런타임이 정상 인식됨 |
| 2단계 | 최소 시작 명령 실행 | 업무용 래퍼와 도구 체인 | 엔진 초기화 또는 첫 실패점이 고정됨 |
| 3단계 | 단일 요청 검증 | 입력과 출력 상한 | 같은 요청에서 같은 실행 결과가 관찰됨 |
| 4단계 | 캐시와 부하를 하나씩 추가 | 직전 안정 기준선 | 변경된 기능의 영향이 확인됨 |
이번 주에는 드라이버 업그레이드와 이미지 교체를 동시에 진행하지 않는 것을 권합니다. 특히 현재 클러스터가 여러 팀의 작업을 공유한다면, 수정 전 상태를 보존한 뒤 별도 노드에서 비교해야 합니다.
이 글이 필요한 운영자
이미 Kimi K3를 여러 차례 시작했지만 변경할 때마다 다른 오류가 나타나는 인프라 엔지니어를 위한 글입니다. OOM, prefix caching, CUDA 초기화 오류를 안정적으로 재현해 플랫폼 팀이나 상위 프로젝트에 전달해야 하는 경우에도 사용할 수 있습니다.
기존 클러스터를 계속 점유할지, 격리된 GPU 환경을 빌릴지 판단해야 하는 기술 책임자도 마지막 결정 기준을 확인할 수 있습니다.
실패 현장 고정
오류가 바뀌는 가장 큰 이유는 여러 변수가 동시에 움직이기 때문입니다. 이미지 태그를 변경하면서 호스트 드라이버를 업그레이드하고, 동시에 max-model-len이나 동시성을 낮추면 이전 오류가 사라져도 원인이 해결된 것인지 판단할 수 없습니다.
비용도 커집니다. 첫째, 같은 실패를 다시 만들 수 없어 상위 팀에 전달할 증거가 약해집니다. 둘째, GPU를 점유한 채 반복 재시작하므로 대기 중인 작업의 기회비용이 늘어납니다. 셋째, 권한이 다른 컨테이너와 호스트에서 서로 다른 라이브러리를 읽으면 설치 기록과 실제 실행 환경이 달라질 수 있습니다.
다음 항목을 실패 직후 저장합니다.
- 호스트의 커널, NVIDIA 드라이버, GPU 목록
- 컨테이너 이미지의 전체 태그와 이미지 식별자
- 컨테이너 안의 vLLM, PyTorch, CUDA 런타임 정보
- 실제 실행한 전체 시작 명령
- 첫 번째 비정상 스택과 그 앞뒤 로그
- 요청 본문, 입력 길이, 출력 상한, 동시성
- 변경한 항목과 변경 시각
설치된 패키지 목록만으로는 충분하지 않습니다. 컨테이너가 실제로 어떤 GPU를 보고 있는지, 어떤 라이브러리 경로를 읽는지 확인해야 합니다. vLLM 공식 환경 변수 문서도 CUDA_VISIBLE_DEVICES, 호스트 주소, 엔진 준비 시간 같은 실행 환경 변수가 실제 동작에 영향을 줄 수 있음을 설명합니다. 공식 환경 변수 문서를 기준으로 환경 지문을 남기는 편이 안전합니다.
주의: 최소 재현의 목표는 즉시 서비스 성공이 아닙니다. 같은 조건에서 같은 실패 단계가 반복되는 것이 먼저입니다.
공식 호환 경계 확인
2026년 8월 9일 기준으로 vLLM의 공식 Kimi K3 레시피는 전용 이미지가 CUDA 13, 즉 cu130 빌드만 제공한다고 안내합니다. cu129 태그는 제공되지 않으며, NVIDIA 호스트에는 r580 이상 드라이버가 필요하다고 명시되어 있습니다. 공식 하드웨어 안내는 NVIDIA 기준 최소 8개 GPU 구성을 제시합니다. 이 내용은 Kimi K3 공식 레시피의 작성 시점 기준입니다.
| 확인 대상 | 기준선에 기록할 값 | 잘못 해석하기 쉬운 부분 |
|---|---|---|
| 이미지 | vllm/vllm-openai:kimi-k3의 실제 식별자 |
latest만 기록하면 나중에 같은 이미지를 찾기 어려움 |
| CUDA | 컨테이너가 사용하는 CUDA 13 계열 런타임 | 호스트에 CUDA 도구가 설치됐다는 사실만으로 컨테이너 런타임이 같아지지 않음 |
| 드라이버 | 호스트에서 실제 로드된 NVIDIA 드라이버 | 패키지 저장소의 설치 버전과 현재 로드 버전이 다를 수 있음 |
| 장치 | 컨테이너 안에서 보이는 GPU와 순서 | CUDA_VISIBLE_DEVICES로 일부 장치만 노출될 수 있음 |
| 모델 실행 | 공식 Kimi K3 시작 인자 | 업무용 래퍼가 추가한 인자를 놓치기 쉬움 |
| 캐시 | --enable-prefix-caching 사용 여부 |
일반 vLLM의 기본 동작을 Kimi K3에 그대로 적용하면 안 됨 |
컨테이너 안에서는 다음 정보를 한 번에 저장합니다.
nvidia-smi
python - <<'PY'
import torch
import vllm
print("torch:", torch.__version__)
print("cuda:", torch.version.cuda)
print("vllm:", vllm.__version__)
print("gpu_count:", torch.cuda.device_count())
PY
Kimi K3용 이미지는 CUDA 13 기반이고 호스트 드라이버 경계가 별도로 있으므로, 드라이버를 바꾼 뒤에는 nvidia-smi 결과와 컨테이너 내부의 torch.version.cuda를 함께 비교해야 합니다. 설치 파일에 남은 예전 CUDA 버전만 보고 혼용이 없다고 판단하면 안 됩니다.
드라이버를 바꾼 뒤 이전 버전이 섞이지 않았는지 어떻게 확인합니까?
호스트의 nvidia-smi 결과, 컨테이너 내부의 장치 목록, LD_LIBRARY_PATH, 실제 로드된 라이브러리 경로를 같은 시각에 저장합니다. 컨테이너를 재생성하지 않은 상태에서 호스트만 바꾸면 이전 프로세스나 마운트가 남을 수 있으므로, 기준선 검증에서는 컨테이너를 새로 만들고 같은 이미지 식별자를 사용해야 합니다.
이 단계에서 CUDA 초기화나 장치 인식이 실패하면 OOM 설정을 만지지 않습니다. 모델 가중치가 로드되기 전에 발생한 오류라면 메모리 예약이나 prefix caching이 원인이라고 볼 근거가 부족합니다.
최소 시작 명령
업무용 Agent 래퍼, 도구 호출 파서, 압력 테스트 스크립트, 장문 입력 생성기를 모두 제거하고 모델 엔진이 시작하는지만 확인합니다. 공식 블로그의 빠른 시작 예시는 Kimi K3에 텐서 병렬 설정과 --enable-prefix-caching을 함께 사용하지만, 최소 재현에서는 먼저 필요한 인자만 남긴 뒤 기능을 단계적으로 복구하는 편이 진단에 유리합니다. vLLM의 Kimi K3 배포 안내에서 원래 권장 명령과 기능별 인자를 확인할 수 있습니다.
실제 환경에 맞는 최소 명령은 다음처럼 별도 파일에 보존합니다.
vllm serve moonshotai/Kimi-K3 \
--tensor-parallel-size 8 \
--trust-remote-code \
--load-format fastsafetensors
여기서 8은 공식 Kimi K3 안내에 포함된 예시 실행 구성에 근거한 값입니다. 실제 장치 수와 노드 토폴로지가 다르면 그대로 복사하지 말고 현재 환경의 공식 레시피와 대조해야 합니다. 숫자만 줄여 단일 GPU에서 성공시키는 방식은 모델의 실제 병렬 실행 문제를 숨길 수 있습니다.
실패 단계는 다음 순서로 기록합니다.
- 컨테이너 초기화
- GPU와 CUDA 장치 인식
- 가중치 파일 접근
- 엔진과 커널 초기화
- 통신 그룹 구성
- API 준비 완료
예를 들어 NCCL error가 엔진 초기화 중 먼저 발생했는데 이후에 OOM 로그가 추가되었다면, OOM부터 해결하려고 해서는 안 됩니다. 앞선 통신 실패가 비정상 종료와 후속 메모리 정리를 유발했을 가능성이 있기 때문입니다. vLLM의 공식 디버깅 안내도 하드웨어와 드라이버 문제, NCCL 통신, 주소 설정을 별도 확인하도록 권고합니다. 공식 디버깅 안내를 참고해 첫 실패 위치를 찾습니다.
단일 요청 기준선
엔진이 준비된 뒤에는 압력 테스트를 중단하고 고정된 요청 하나만 보냅니다. 입력 내용, 출력 상한, 온도, 호출 경로를 매번 동일하게 유지해야 합니다.
예시는 다음과 같이 단순화합니다.
{
"model": "moonshotai/Kimi-K3",
"messages": [
{
"role": "user",
"content": "고정된 짧은 테스트 문장에 답하세요."
}
],
"max_tokens": 128,
"temperature": 0
}
온라인 서버의 결과는 스케줄링과 실행 순서의 영향을 받으므로, 한 번 성공했다고 완전히 재현된 것으로 볼 수 없습니다. vLLM 공식 재현성 문서도 같은 하드웨어와 같은 vLLM 버전이 필요하며, 온라인 서빙에서는 스케줄링을 완전히 결정적으로 만들기 어렵다고 설명합니다. 공식 재현성 문서를 기준으로 결과의 한계를 표시해야 합니다.
Kimi K3의 OOM이 진짜 원인인지 앞선 CUDA 오류의 결과인지 어떻게 구분합니까?
첫 실패의 시간순 위치를 봅니다. CUDA 초기화, 장치 등록, NCCL 통신이 먼저 실패했다면 뒤에 나타난 OOM은 후속 현상일 수 있습니다. 반대로 엔진이 정상 초기화되고 고정 요청을 처리하는 중 메모리 할당이 실패했다면 그때부터 입력 길이, 출력 상한, 동시성 같은 메모리 변수를 조사합니다.
단일 요청이 안정되면 한 번에 하나만 바꿉니다.
- 입력 길이만 증가
- 출력 상한만 증가
- 동시성만 증가
- 다중 노드 통신만 추가
- Agent 도구 호출만 추가
각 회차에는 이전 로그와 새 로그를 모두 남깁니다. 오류 유형이 바뀌면 새 오류를 해결하기 전에 바로 직전 안정 기준선으로 되돌립니다.
기능 변수의 단계적 복구
prefix caching은 처음부터 생산 설정처럼 넣지 않습니다. Kimi K3는 일반적인 vLLM 기본값과 달리 prefix caching이 기본으로 켜져 있지 않으므로, 기능 검증 단계에서 명시적으로 --enable-prefix-caching을 추가해야 합니다. 공식 안내는 전체 어텐션 KV와 반복형 KDA 상태를 모두 대상으로 캐시를 지원하지만 기본값은 비활성이라고 설명합니다. Kimi K3의 캐시 설계 설명에서 세부 동작을 확인할 수 있습니다.
prefix caching을 최소 재현 명령에 넣어야 합니까?
캐시 자체의 오류를 재현하려는 경우에만 넣습니다. CUDA, 드라이버, 장치 인식, 기본 엔진 시작을 확인하는 첫 기준선에는 넣지 않습니다. 먼저 캐시 없이 단일 요청이 안정적으로 처리되는지 확인한 뒤, 같은 명령에 캐시 플래그 하나만 추가합니다.
캐시를 넣은 뒤에는 성능 향상보다 다음 증거를 먼저 봅니다.
- 두 번째 동일 요청에서 캐시 관련 로그가 나타나는지
- 첫 요청과 두 번째 요청의 입력이 실제로 같은지
- 캐시 활성화 직후 메모리 할당 오류가 나타나는지
- 캐시 없이 성공하던 요청이 캐시를 켠 뒤 실패하는지
그 다음에 긴 문맥, 동시성, 다중 노드를 각각 추가합니다. Kimi K3의 캐시 구조는 반복 상태와 일반 KV 상태를 함께 다루므로, 단순히 일반 모델의 캐시 적중률만 보고 정상 여부를 판단하지 않는 것이 좋습니다.
재현 인계 점검
다음 체크리스트를 모두 통과한 뒤에야 CUDA, OOM, 통신 또는 캐시 관련 수정으로 넘어갑니다.
- [ ] 호스트 드라이버와 컨테이너 내부 CUDA 정보를 같은 시각에 저장했습니다.
- [ ] 이미지 태그뿐 아니라 이미지 식별자도 기록했습니다.
- [ ] 실제 시작 명령에서 업무용 추가 인자를 분리했습니다.
- [ ] 첫 번째 오류 스택과 오류 직전 로그를 보존했습니다.
- [ ] 고정 입력과 출력 상한을 사용했습니다.
- [ ] 단일 요청 성공 여부를 부하 테스트와 구분했습니다.
- [ ] 한 회차에 하나의 변수만 변경했습니다.
- [ ] 오류가 바뀌면 직전 안정 기준선으로 되돌렸습니다.
- [ ] prefix caching을 별도 단계에서 명시적으로 검증했습니다.
- [ ] 재현성의 한계와 온라인 스케줄링 영향을 인계 문서에 적었습니다.
- [ ] 원래 클러스터의 다른 작업과 GPU 점유 상태를 기록했습니다.
이 자료는 단순 로그 묶음보다 유용합니다. 플랫폼 팀은 환경 지문, 최소 명령, 고정 요청, 첫 실패 단계, 단일 변수 결과를 보고 바로 재현을 시도할 수 있습니다. JexMac의 도움말 페이지를 이용해 원격 접속과 테스트 환경 운영에 필요한 기본 조건도 함께 확인할 수 있습니다.
수정과 환경 전환의 판단
다음 세 경우에는 기존 환경에서 계속 수정하지 않는 편이 낫습니다.
첫째, 공식 CUDA 13과 r580 이상 드라이버 기준을 맞췄는데도 실패 지점이 실행마다 달라질 때입니다. 둘째, 클러스터 정책 때문에 드라이버나 컨테이너를 완전히 고정할 수 없을 때입니다. 셋째, 다른 작업이 GPU 메모리와 네트워크를 사용해 단일 변수 실험이 불가능할 때입니다.
이때 필요한 것은 더 많은 옵션이 아니라 독립된 재현 공간입니다. 원래 환경과 격리 환경에서 같은 이미지 식별자, 같은 시작 명령, 같은 요청을 실행하고 첫 실패 단계만 비교합니다. 격리 환경에서도 동일한 오류가 반복되면 모델이나 vLLM 관련 문제로 인계할 근거가 생깁니다. 반대로 격리 환경에서만 정상이라면 기존 클러스터의 드라이버 잔재, 장치 노출, 네트워크, 권한 또는 공유 메모리 구성을 조사해야 합니다.
Kimi K3 자체를 CUDA GPU에서 구동하는 것이 목적이라면 Mac은 호환 테스트 장비를 대신할 수 없습니다. 다만 Agent 플랫폼의 요청 재생, API 클라이언트, 로그 수집, 스키마 검증, 원격 운영 도구를 잠시 분리해 검증하려는 경우에는 장비를 직접 구매하는 것보다 필요한 기간만 JexMac의 Mac 환경을 사용하는 편이 관리 부담이 낮을 수 있습니다. 직접 장비를 마련하면 초기 구매비, macOS 유지 관리, 원격 접속 구성이라는 비용이 생기고, 기존 GPU 클러스터는 다른 작업과 자원을 공유해 재현성이 흔들릴 수 있습니다. 실제 Kimi K3 CUDA 추론은 호환되는 GPU 환경에서 진행하고, 주변 테스트와 운영 도구를 임시 Mac 환경으로 분리하는 방식이 현실적입니다.
필요한 기간과 원격 사용 조건을 먼저 비교하려면 JexMac의 Mac 대여 요금 안내를 확인한 뒤, 문서에 정리한 최소 명령과 환경 지문을 기준으로 격리 테스트 범위를 정하는 것이 좋습니다.
실행 환경을 분리해 오류 원인을 확인하려면 JexMac을 이용해 보십시오
JexMac은 가상화 없이 맥 미니 엠포 한 대를 전용으로 제공해 설정별 결과를 안정적으로 비교할 수 있습니다.