하루 만에 정상 상태의 모델 서버를 여덟 번이나 재시작한 헬스 체크
운영
7월 22일, 워치독이 로컬 모델 서버를 여덟 번 재시작했습니다. 그중 크래시가 있었던 경우는 하나도 없었습니다. 모델을 살려두려던 체크가 오히려 모델을 꺼뜨린 셈이었습니다.
무슨 일이 있었나요
모델 서버는 NVIDIA GB10 머신 한 대에서 vLLM을 실행했으며, 단일 요청당 초당 약 8개의 토큰을 생성했습니다. 5분마다 워치독이 실제 채팅 요청을 보내고 응답을 최대 45초까지 기다렸습니다. 연속으로 다섯 번 체크에 실패하면 서버가 멈춘 것으로 간주하고 워치독이 재시작했습니다. 재시작하면 약 19GB의 가중치를 다시 불러오는 동안 모델이 몇 분간 사용 불가 상태가 되었습니다.
그날 배치 작업이 서버에서 두세 개에서 네 개까지의 요청을 각각 몇 분간 점유하고 있었습니다. 워치독의 요청은 그 뒤에 대기열에서 기다리다 시간을 초과해 실패로 집계되었습니다. 그렇게 다섯 번의 체크가 지나자 정상 상태의 서버가 재시작되었습니다. 워치독이 존중하는 "busy" 플래그 파일이 있었지만, 배치 작업은 이를 설정하지 않았습니다.
하루의 오판 재시작이 다음 재시작으로 이어진 과정
재시작마다 진행 중이던 요청이 500 오류("cannot schedule new futures after shutdown")로 실패했습니다. 두 번째 워치독은 500 오류를 집계해 너무 많으면 서버를 재시작했는데, 오류가 많을수록 더 빨리 작동했습니다. 따라서 오판 재시작이 있을 때마다 다음 재시작이 더 빨리 찾아왔습니다. 결국 5분, 10분, 15분, 30분 타이머를 가진 네 개의 별도 워치독이 해당 서버를 재시작할 수 있었습니다.
이 사례에서 얻은 규칙
헬스 체크는 자신이 보호하는 자원을 사용해서는 안 됩니다. 모델 서버의 희소 자원은 진행 중인 요청을 위한 슬롯입니다. 그 슬롯 하나를 차지하거나 대기하는 체크는 판단 대상인 부하의 일부가 됩니다. 저렴하게 체크하고, 서버가 멈췄음을 입증할 수 있을 때만 재시작하십시오.
이를 대체한 체크
vLLM은 자체 카운터를 /metrics에 게시합니다. 새 체크는 이를 먼저 읽습니다:
- 실행 중인 요청과 엔진의 진행 상황: 정상 및 사용 중. 테스트 요청은 보내지 않습니다.
- 두 번의 읽기 사이에 실행 중인 요청은 있으나 진행 없음: 멈춤. 여전히 재시작하는 경우입니다.
- 실행 중인 요청 없음: 유휴 상태. 이때만 짧은 응답을 요청하며, 유휴 엔진은 즉시 응답합니다.
첫 번째 버전은 생성된 토큰 수를 진행 상황으로 집계했습니다. 여덟 번의 테스트를 통과했고, 첫 실전 실행에서는 서버가 사용 중이며 정상임을 확인했습니다: 2개의 요청 실행 중, 두 번의 읽기 사이에 107개의 새 토큰 생성.
그 이후 변경 사항
- 엔진 단계, 출력 토큰이 아닙니다. vLLM이 긴 프롬프트를 읽는 동안에는 한동안 출력 토큰을 생성하지 않지만 여전히 단계를 진행합니다. 단계를 세면(vllm:iteration_tokens_total의 개수) 긴 프롬프트가 서버가 멈춘 것처럼 보이는 것을 방지할 수 있습니다.
- "멈춤"으로 판단하기 전 두 번의 대기, 짧은 일시 정지가 실패로 간주되지 않도록 합니다.
- 두 번의 읽기 사이에 재시작이 발생하면 동일한 메트릭의 프로세스 시작 시간을 통해 감지됩니다. 이후 확인 단계에서는 서로 다른 두 프로세스의 카운터를 비교하는 대신 응답을 요청합니다.
- 프록시는 /models를 통해서만 확인합니다. 최소 연결 수 기반 프록시 뒤에서는 /metrics를 읽을 때마다 서로 다른 백엔드에서 응답할 수 있는데, 이는 우리가 두 대의 각 머신에 모델의 사본을 실행했을 때 확인한 바와 같습니다. 백엔드는 직접 확인합니다.
차이는 쉽게 확인할 수 있습니다. 이 노트를 작성하는 시점에 두 모델 서버 모두 각각 12개의 요청을 처리 중이었으며, 이는 한계치였습니다. 테스트 요청은 대기열에서 기다려야 했을 것입니다. 새로운 확인 기능은 요청을 보내지 않고도 두 서버 모두 바쁘지만 정상 상태임을 보고했으며, 초당 126개와 101개의 토큰을 처리했습니다.
Factory Floor 1.0.2는 이 확인 기능을 models/llm-health.py로 제공하며, 유휴 상태, 바쁨, 멈춤, 재시작된 서버, 메트릭이 없는 서버, 프록시 및 죽은 백엔드에 대한 테스트를 포함합니다.