NaizVL 운영 안정화 — 재발 방지 가이드
2026-05-26 운영 서버에서 발생한 "/infer 100% 500 에러" 인시던트 대응 및 재발 방지 작업.
1. 인시던트 요약
| 시각 | 상황 |
|---|---|
| 2026-05-21 15:21 | naizvl.service 시작 (4일 가동) |
| 2026-05-26 ~10:00 | 모든 /infer 요청이 500 Internal Server Error |
| /status | 정상 응답 (서비스 자체는 active) |
| journal | traceback 없음 — 500 만 보이고 원인 불명 |
| GPU | util 0%, mem 45.6+45.8/48 GB (KV cache 만적) |
| Host RAM | 103.6/125.6 GB (82.5%) — 누수 의심 |
| 복구 | sudo systemctl restart naizvl 으로 즉시 해결 |
근본 원인: Ray Serve replica 가 unhealthy 상태로 들어갔는데, proxy/HTTP layer 는 정상 → /status 200 OK 응답. inference 호출이 worker 에 도달 못해 timeout/RPC 실패로 500. 코드의 except Exception as e: return JSONResponse(status_code=500, content={"error": str(e)}) 가 traceback 출력 안 해서 journal 에 흔적 없음.
2. 적용된 코드 fix
2.1 naizvl_server_replica.py — traceback 출력
| 위치 | 변경 |
|---|---|
| import 부 | import traceback 추가 |
_call_worker_and_build_response 의 except Exception |
traceback.print_exc() + 명시적 stderr 로그 추가. 응답에 error_type 컬럼 추가 (디버그 용이) |
FastAPI 전역 @app.exception_handler(Exception) |
모든 미처리 예외 catch-all. traceback 출력 + 구조화된 500 응답 |
→ 다음 인시던트 발생 시 journalctl -u naizvl --since "10 min ago" 로 traceback 즉시 확인 가능.
2.2 /healthz 엔드포인트 추가
@app.get("/healthz")
async def healthz():
# 인증 불필요. worker_handle 존재 + 가용성 확인.
# systemd / 외부 watchdog 용 라이트 체크.
응답:
- 200 {"ok": true, "active": N, "completed": N} — 정상
- 503 {"ok": false, "reason": "..."} — worker handle 없음 또는 예외
/status 는 인증 필요 + 무거운 system snapshot. /healthz 는 watchdog 용 가벼운 체크.
3. Watchdog — 자동 재시작
naizvl-watchdog.sh — 2분마다 /healthz 점검, 연속 3회 실패 시 자동 systemctl restart naizvl.
HTTP 호출은 3-layer fallback (curl → wget → python3) — Ubuntu Desktop minimal install 에 curl 빠진 케이스 (2026-05-26 보고) 대응. python3 는 NaizVL 환경에 보장됨. 신규 키트 (2026-05-26 이후) 는 APT_PKGS 에 curl 명시 포함하여 첫 fallback 단계가 항상 성공.
운영 적용
# 1) 스크립트 배포
sudo cp /home/naiz/NaizVL/deploy/naizvl-watchdog.sh /usr/local/bin/
sudo chmod +x /usr/local/bin/naizvl-watchdog.sh
# 2) state 디렉토리 생성
sudo mkdir -p /var/lib/naizvl
# 3) cron 등록 (root 으로 — systemctl restart 권한 필요)
sudo crontab -e
# 다음 줄 추가:
*/2 * * * * /usr/local/bin/naizvl-watchdog.sh
# 4) 동작 확인 (수동 실행)
sudo /usr/local/bin/naizvl-watchdog.sh
# 정상이면 출력 없음. 로그:
journalctl -t naizvl-watchdog --since "5 min ago"
동작 매트릭스
| /healthz 응답 | 누적 fail | 동작 |
|---|---|---|
| 200 OK | 0 으로 reset | (조용히 통과) |
| 200 OK (직전에 fail 있었음) | reset + 로그 | "counter reset (was N)" 기록 |
| 5xx / timeout | +1 | 카운터 증가 로그 |
| 5xx / timeout, count ≥ 3 | restart 실행 | systemctl restart naizvl |
| 재시작 후 /healthz 200 | reset | "recovery successful" |
| 재시작 후 /healthz still 5xx | reset (무한 재시작 방지) | "manual intervention required" 경고 |
Tuning
환경변수로 조정 가능:
NAIZVL_WATCHDOG_FAIL=5 # 연속 실패 임계 (default 3)
NAIZVL_WATCHDOG_TIMEOUT=10 # /healthz timeout 초 (default 5)
NAIZVL_SERVER=http://127.0.0.1:7860
4. 메모리 모니터링
4일 가동 후 RAM 82.5% 사용 — 메모리 누수 패턴 의심. 일일 추세 모니터:
# 매 시간 RAM 사용량 기록 (cron)
0 * * * * curl -sS http://127.0.0.1:7860/status 2>/dev/null | \
python3 -c "import json,sys; d=json.load(sys.stdin); m=d['system']['memory']; \
print(f'{m[\"used_gb\"]} {m[\"total_gb\"]} {m[\"percent\"]}')" \
>> /var/log/naizvl/memory.log
이후 분석:
# 일일 평균 RAM%
awk '{sum+=$3; n++} END {print sum/n}' /var/log/naizvl/memory.log
RAM% 가 매일 +수% 씩 누적되면 정기 재시작 cron 추가:
# 매주 일요일 03:00 재시작 (사용자 적은 시간)
0 3 * * 0 /usr/bin/systemctl restart naizvl
5. 운영 점검 항목
다음 발생 시 즉시 확인:
| 증상 | 명령 |
|---|---|
| 클라이언트가 500 받음 | journalctl -u naizvl -f --since "5 min ago" — traceback 확인 |
| /infer 느림 | curl http://127.0.0.1:7860/status — requests.active 큐 backlog |
| GPU util 0% but 응답 없음 | Ray Serve replica unhealthy — systemctl restart naizvl |
| RAM 90% 초과 | 정기 재시작 (점진적 누수 일반적 패턴) |
/healthz 503 |
watchdog 가 곧 재시작. 수동: sudo systemctl restart naizvl |
6. 변경 파일 목록
| 파일 | 변경 |
|---|---|
naizvl_server_replica.py (NaizVL 저장소 참고) |
import traceback, _call_worker_and_build_response 의 except 보강, 전역 @app.exception_handler(Exception), /healthz 엔드포인트 추가 |
naizvl-watchdog.sh |
신규 — 자동 헬스체크 + 재시작 스크립트 |
| deploy/HARDENING.md | 이 문서 |
7. 다음번 키트 빌드 시 자동 포함
naizvl_server_replica.py의 변경 — 키트 02-app/ 에 자동 포함됨 (이미 키트가 그 파일만 명시 복사)naizvl-watchdog.sh는 키트에 추가 필요.make-offline-kit.sh의 02-app 복사부에 추가:
# make-offline-kit.sh 의 02-app 복사 부분에
cp "$SRC_ROOT/deploy/naizvl-watchdog.sh" "$STAGE_DIR/02-app/"
그리고 install.sh 마지막에:
cp "$KIT/02-app/naizvl-watchdog.sh" /usr/local/bin/
chmod +x /usr/local/bin/naizvl-watchdog.sh
mkdir -p /var/lib/naizvl
# 운영자가 직접 crontab 등록 안내 (자동 등록은 멱등성 어려움)
8. 관련 문서
- INSTALL.md — NaizVL 서버 설치
- INSTALL_FRONTEND.md — 웹 UI 설치
- BUILD.md — 키트 제작
- README.md — 인덱스 + 변경 이력