프로덕션 환경에서 수억 개의 벡터를 실시간 검색해야 하는 상황을 상상해보세요. 저는 이전에 단일 노드 Milvus 인스턴스로 시작했으나, 데이터가 1억 개를 넘기는 순간 TimeoutError: Request timed out after 30s 오류가 연발하기 시작했습니다. 결국 분산 클러스터 마이그레이션을 결정했고, 그 과정에서踩まった坑들을 공유하고자 합니다.
Milvus 분산 아키텍처 이해
Milvus는 마스터-워커 아키텍처를 기반으로 하며, 프로덕션 분산 클러스터는 다음과 같은 핵심 컴포넌트로 구성됩니다:
- Coordination Layer: Proxy, Root Coordinator, Index Coordinator, Query Coordinator, Data Coordinator
- Storage Layer: etcd(메타데이터), MinIO/S3(객체 스토리지), Pulsar(로그 스트림)
- Worker Layer: Query Node, Data Node, Index Node
사전 요구사항
# 시스템 요구사항 확인
cat /etc/os-release
Ubuntu 20.04 LTS 이상 권장
필수 패키지 설치
sudo apt-get update
sudo apt-get install -y \
docker.io \
docker-compose \
etcd-client \
curl \
wget
Docker 권한 설정
sudo usermod -aG docker $USER
newgrp docker
Helm 확인 (Kubernetes 배포 시)
helm version
version.BuildInfo{Version:"v3.14.0"}
Helm을 이용한 Kubernetes 분산 클러스터 배포
본격적인 분산 배포를 시작하겠습니다. Minikube 환경에서 프로덕션과 유사한 구조를 구축해보겠습니다.
# Helm 차트 추가
helm repo add milvus https://milvus-io.github.io/milvus-helm/
helm repo update
사용자 정의 values 파일 생성
cat > milvus-cluster.yaml << 'EOF'
cluster:
enabled: true
replica: 2
etcd:
replicaCount: 3
persistence:
enabled: true
size: 20Gi
resources:
limits:
cpu: '1'
memory: 2Gi
minio:
replicaCount: 4
persistence:
enabled: true
size: 100Gi
resources:
limits:
cpu: '2'
memory: 4Gi
pulsar:
replicaCount: 3
bookkeeper:
replicaCount: 3
persistence:
enabled: true
size: 50Gi
resources:
limits:
cpu: '2'
memory: 4Gi
proxy:
replicaCount: 2
resources:
limits:
cpu: '1'
memory: 2Gi
queryNode:
replicaCount: 3
resources:
limits:
cpu: '2'
memory: 8Gi
dataNode:
replicaCount: 3
resources:
limits:
cpu: '1'
memory: 4Gi
indexNode:
replicaCount: 2
resources:
limits:
cpu: '2'
memory: 8Gi
config:
etcd:
endpoint: etcd:2379
pulsar:
endpoint: pulsar://pulsar:6650
minio:
endpoint: minio:9000
EOF
Milvus 클러스터 배포
kubectl create namespace milvus
helm install milvus-cluster milvus/milvus \
--namespace milvus \
--values milvus-cluster.yaml \
--set service.type=LoadBalancer
배포 상태 확인
kubectl get pods -n milvus -w
Python SDK로 분산 클러스터 연결 및 검증
클러스터가 정상적으로 배포되면, Python SDK를 통해 연결을 테스트하고 실제 벡터 검색 성능을 측정해보겠습니다.
# 필요한 패키지 설치
pip install pymilvus[grpc] grpcio grpcio-tools
연결 테스트 스크립트
cat > test_cluster.py << 'EOF'
from pymilvus import connections, Collection, FieldSchema, CollectionSchema, DataType
import time
import numpy as np
분산 클러스터 연결
try:
connections.connect(
alias="default",
host="milvus-cluster.milvus.svc.cluster.local",
port="19530",
timeout=30
)
print("✅ Milvus 클러스터 연결 성공")
except Exception as e:
print(f"❌ 연결 실패: {e}")
raise
컬렉션 생성
dim = 128
fields = [
FieldSchema(name="id", dtype=DataType.INT64, is_primary=True),
FieldSchema(name="embedding", dtype=DataType.FLOAT_VECTOR, dim=dim),
FieldSchema(name="metadata", dtype=DataType.VARCHAR, max_length=256)
]
schema = CollectionSchema(fields, "분산 클러스터 테스트 컬렉션")
collection = Collection("distributed_test", schema)
인덱스 생성
index_params = {
"index_type": "IVF_FLAT",
"metric_type": "L2",
"params": {"nlist": 128}
}
collection.create_index("embedding", index_params)
테스트 데이터 삽입 (100만 개 벡터)
num_vectors = 1_000_000
vectors = np.random.rand(num_vectors, dim).tolist()
ids = list(range(num_vectors))
metadata = [f"doc_{i}" for i in range(num_vectors)]
start = time.time()
collection.insert([ids, vectors, metadata])
collection.flush()
insert_time = time.time() - start
print(f"📊 100만 개 벡터 삽입 시간: {insert_time:.2f}초")
검색 성능 테스트
search_vectors = np.random.rand(100, dim).tolist()
start = time.time()
results = collection.search(
search_vectors,
"embedding",
{"metric_type": "L2", "params": {"nprobe": 16}},
limit=10,
timeout=30
)
search_time = time.time() - start
print(f"📊 100회 검색 평균 시간: {search_time/100*1000:.2f}ms")
분산 쿼리 노드 상태 확인
from pymilvus import utility
print(f"📊 Query Node 수: {len(utility.get_query_nodes_info())}")
print(f"📊 Index Node 수: {len(utility.get_index_nodes_info())}")
collection.release()
connections.disconnect("default")
EOF
python test_cluster.py
HolySheep AI와 통합: 하이브리드 검색 파이프라인
여기서 HolySheep AI를 활용하면 텍스트를 벡터로 변환하고 Milvus에서 유사도를 검색하는 하이브리드 파이프라인을 구성할 수 있습니다.
# HolySheep AI SDK 설치
pip install openai
HolySheep AI 통합 하이브리드 검색
cat > hybrid_search.py << 'EOF'
from openai import OpenAI
from pymilvus import connections, Collection
import numpy as np
HolySheep AI 초기화
client = OpenAI(
api_key="YOUR_HOLYSHEEP_API_KEY",
base_url="https://api.holysheep.ai/v1"
)
Milvus 연결
connections.connect(host="milvus-cluster.milvus.svc.cluster.local", port="19530")
collection = Collection("distributed_test")
collection.load()
def embed_text(text: str) -> list:
"""HolySheep AI로