파이썬 클라이언트로 Milvus 에 붙으면 다음 메시지가 반복된다.
[get_server_version] retry:1, cost: 0.27s, reason: <_InactiveRpcError:
StatusCode.UNAVAILABLE, internal: Milvus Proxy is not ready yet. please wait>
Milvus 는 단일 프로세스가 아니라 역할이 나뉜 여러 구성 요소로 돌아간다. 클라이언트가 처음 만나는 것이 Proxy 이고, Proxy 는 자기 뒤의 구성 요소가 준비될 때까지 요청을 받지 않는다.
| 구성 요소 | 역할 |
|---|---|
| Proxy | 클라이언트 진입점. gRPC 수신 |
| RootCoord | 메타데이터·DDL 조정 |
| QueryCoord / QueryNode | 검색 실행 |
| DataCoord / DataNode | 적재·세그먼트 관리 |
| IndexCoord / IndexNode | 인덱스 구축 |
| etcd | 메타데이터 저장 |
| MinIO 또는 S3 | 세그먼트·인덱스 파일 저장 |
| Pulsar 또는 Kafka | 내부 메시지 큐 |
StatusCode.UNAVAILABLE 은 gRPC 계층에서 "지금은 못 받는다"는 뜻이고, 그 뒤의 문구가 이유다. 즉 연결 자체는 됐고 서비스가 아직 안 뜬 상태다. 주소나 포트가 틀렸다면 이 메시지가 아니라 연결 거부가 난다.
기동 직후라면 이것이 정상 동작이다. 데이터가 쌓인 인스턴스는 재기동 시 세그먼트를 다시 읽고 인덱스를 적재하므로, 준비까지 수 분에서 수십 분이 걸리기도 한다. 이 시간 동안 Proxy 는 같은 메시지를 계속 돌려준다.
기다려서 해결되는 경우가 대부분이므로, 원인 분석보다 먼저 컬렉션 적재 진행 상황을 본다.
구성 요소별 상태를 본다. 쿠버네티스 배포(Helm 또는 Milvus Operator)라면 다음이다.
kubectl -n milvus get pod
kubectl -n milvus get pod -l app.kubernetes.io/name=milvus -o wide
kubectl -n milvus logs deploy/milvus-proxy --tail=100
kubectl -n milvus logs deploy/milvus-rootcoord --tail=100
Running 인데 READY 가 0/1 인 파드를 찾는다. Proxy 가 기다리는 대상은 그쪽이다.
Docker Compose 로 띄운 단독 구성이라면 다음이다.
docker compose ps
docker compose logs --tail=100 standalone
docker compose restart standalone
의존 서비스가 먼저다. etcd · 오브젝트 스토리지 · 메시지 큐 중 하나라도 불안하면 Milvus 는 영원히 준비 상태로 가지 못한다.
kubectl -n milvus logs sts/milvus-etcd --tail=50
kubectl -n milvus logs sts/milvus-minio --tail=50
etcd 디스크가 가득 차서 읽기 전용 모드로 넘어간 경우다. etcd 로그에 mvcc: database space exceeded 가 보이면 압축과 defrag 가 필요하다.
오브젝트 스토리지 자격증명이나 버킷이 바뀐 경우다. DataNode 가 세그먼트를 못 읽어 계속 재시도한다.
메모리 부족이다. QueryNode 가 컬렉션을 메모리에 적재하다 OOM 으로 죽고 다시 뜨기를 반복하면 준비 상태에 도달하지 못한다. 파드 재시작 횟수가 늘어나는지 본다.
kubectl -n milvus get pod -o wide | awk '{print $1, $4, $5}'
버전 불일치도 있다. pymilvus 와 서버의 주 버전이 다르면 초기 핸드셰이크에서 어긋난다. 클라이언트를 서버에 맞춘다.
애플리케이션에서는 기동 대기를 전제로 재시도를 넣는다. 예외를 삼키지 말고 타임아웃을 정한다.
from pymilvus import connections, utility
import time
for attempt in range(60):
try:
connections.connect(alias="default", host="milvus.example.local", port="19530")
print(utility.get_server_version())
break
except Exception as exc:
print(f"waiting for milvus: {exc}")
time.sleep(10)
else:
raise RuntimeError("Milvus 가 제한 시간 안에 준비되지 않았다")
docker restart 나 파드 삭제로 무작정 되살리면 적재 중이던 작업이 처음부터 다시 시작돼 대기가 더 길어진다. 로그를 먼저 읽고 정말 멈춰 있는지 확인한 뒤에 재시작한다.
기동 지연을 줄이려면 자주 안 쓰는 컬렉션을 release 해 두고, 필요할 때 load 한다.