리소스 쿼터
리소스 쿼터 (Resource Quotas) (ops-configuration-quotas)
Qdrant 노드가 메모리나 디스크 공간이 부족해지면 어떻게 될까요? 데이터가 계속 들어오다가 결국 장애가 나는 걸 막고 싶을 때 쓰는 장치가 바로 리소스 쿼터(Resource Quotas)예요. 쿼터는 노드가 메모리나 디스크 공간이 부족해지면 더 이상 데이터를 받지 않도록 멈춰요. 사용량이 설정한 한계에 도달하면, 노드는 그 리소스를 더 소모하게 만드는 업데이트를 거부하다가, 사용량이 다시 내려갈 때까지 거부 상태를 유지해요.
출처: Qdrant 공식문서
Available as of v1.19.0 (v1.19.0부터 사용 가능)
쿼터 설정하기 (Configuring Quotas)
쿼터는 기본적으로 비활성화되어 있어요. 쿼터는 노드별로, 또는 API를 통해 클러스터의 모든 노드에 적용할 수 있어요.
노드에 쿼터를 적용하려면 노드의 설정 파일에서 storage.quotas를 설정해요.
storage:
quotas:
enabled: true
max_disk_usage_percent: 90
또는 환경 변수를 사용해요.
QDRANT__STORAGE__QUOTAS__ENABLED=true
QDRANT__STORAGE__QUOTAS__MAX_DISK_USAGE_PERCENT=90
클러스터 전체에 쿼터를 바꾸려면 PUT /quotas API를 사용해요.
PUT /quotas?wait=true
{
"enabled": true,
"max_disk_usage_percent": 90
}
Qdrant는 새 구성을 모든 피어(peer)에 전파하고 이를 영구 저장하므로, 재시작 후에도 유지돼요.
참고: 일단
PUT /quotas로 쿼터가 설정되면, Qdrant는storage.quotas를 더 이상 읽지 않아요. Configuration Precedence를 참고하세요.
사용할 수 있는 파라미터는 다음과 같아요.
| 파라미터 | 설명 |
|---|---|
enabled |
한계(limit)가 적용되는지 여부. 기본값은 false. |
max_resident_memory_percent |
프로세스 상주 메모리(resident memory)가 노드에 사용 가능한 메모리의 이 비율에 도달하면 메모리를 소모하는 업데이트를 거부. 1–100 범위의 값을 허용. 설정하지 않으면 메모리 쿼터가 적용되지 않음. |
max_disk_usage_percent |
저장 디렉터리를 담고 있는 파일 시스템이 용량의 이 비율까지 차면 디스크를 소모하는 업데이트를 거부. 1–100 범위의 값을 허용. 설정하지 않으면 디스크 쿼터가 적용되지 않음. |
release_margin_percent |
노드가 다시 업데이트를 받기 전에 리소스가 한계 아래로 얼마나 내려가야 하는지. 0–100 범위의 값을 허용. 기본값은 5. |
Qdrant는 상주 메모리를, cgroup 한계가 적용되는 곳에서는 그 한계에 대비해 측정하고, 그 외에는 시스템 전체 메모리에 대비해 측정해요.
설정 우선순위 (Configuration Precedence)
API를 통해 설정된 쿼터는 설정 파일이나 환경 변수보다 우선해요.
클러스터 어디에서도 API로 쿼터가 설정되기 전까지는, Qdrant가 시작할 때마다 설정 파일을 읽어요. 그래서 노드를 멈추고 설정을 바꾼 뒤 다시 시작하면 새 쿼터가 적용돼요. 이미 API로 쿼터가 설정된 클러스터에 합류하는 노드는 컨센서스(consensus)를 통해 그 구성을 받기 때문에, 자신의 설정 파일은 더 이상 읽히지 않아요.
노드마다 쿼터가 다를 때 (When Nodes Have Different Quotas)
각 노드는 자신의 쿼터를 각자 해석해요. Qdrant는 피어 간에 쿼터를 비교하지도, 다를 때 경고하지도 않아요. 시행은 노드별로 이뤄져요. 한계에 도달한 노드는 자신이 보유한 레플리카에 대한 업데이트를 거부해요. 샤드가 다른 곳에 복제되어 있으면, Qdrant는 로컬 레플리카를 비활성화하고 그 업데이트는 다른 노드에 적용돼요.
모든 노드에 균일한 쿼터를 보장하려면 PUT /quotas API를 사용하세요.
쿼터 초과 시 (When a Quota Is Exceeded)
쿼터는 노드가 데이터를 저장하는 것을 막지, 요청을 처리하는 것을 막지는 않아요. 읽기 연산은 절대 영향받지 않아요. 쓰기의 경우, 한계를 넘은 노드도 여전히 업데이트를 받아들이고 조정(coordinate)해요. 그래서 꽉 찬 노드에 쓰기를 보내는 것 자체는 문제가 아니에요. 요청을 보낸 노드가 쓰여지는 샤드의 레플리카를 보유하고 있지 않다면, 그 노드의 쿼터는 아예 적용되지도 않아요.
업데이트가 꽉 찬 노드의 샤드에 도달하면, Qdrant는 그 레플리카를 제외하고 그 제외를 해당 노드의 실패로 기록해요. 업데이트 전체는 최소한 write_consistency_factor개의 레플리카가 받아들이는 한 여전히 성공해요. 기본적으로 write_consistency_factor는 1이라서, 정상 레플리카 하나면 충분하고 클라이언트는 정상적인 성공 응답을 받아요.
그다음 Qdrant는 제외된 레플리카를 죽은 것으로 표시해요. 노드에 다시 공간이 생길 때까지 비활성 상태로 남아 있고 샤드 복구를 요청하지 않아요. write_consistency_factor를 여전히 공간이 있는 레플리카 수보다 높이 올리면, 같은 쓰기가 오류로 바뀌게 돼요.
어떤 레플리카도 쓰기를 받지 못할 때 클라이언트는 HTTP 507 Insufficient Storage나 gRPC ResourceExhausted 오류를 보게 돼요. 이는 샤드가 레플리카 하나만 가지고 있고 그것이 꽉 찬 노드에 있을 때, 또는 샤드의 모든 레플리카가 한계를 넘은 노드에 있을 때 일어나요. 오류는 리소스 이름, 현재 사용률, 설정된 한계를 함께 알려줘요.
Disk usage is at 95% of total capacity, exceeding the configured limit of 90%.
Help: Reduce disk usage (e.g. delete points or drop collections), or raise
`max_disk_usage_percent` in the global quota config.
노드가 쿼터 초과에서 회복되지 않은 동안에는:
- 포인트 삭제는 항상 허용돼요. 꽉 찬 노드에서 한계 아래로 돌아가는 방법이 바로 이거예요.
- 벡터나 payload 키 삭제는 허용되지 않아요. 내부적으로 Qdrant가 그 필드를 빼기 위해 포인트를 다시 쓰므로, 무엇이 회수되기 전에 저장 공간이 오히려 늘어나기 때문이에요.
- 샤드 전송은 항상 허용돼요. Qdrant는 전송이 시작되기 전에 한 번 여유 공간을 확인해서, 중간에 배치를 거부하면 거의 다 끝난 작업을 버리는 셈이 되기 때문이에요.
꽉 찬 노드 찾기 (Finding the Node That Is Full)
GET /quotas API로 전체 클러스터의 쿼터를 확인할 수 있어요.
{
"config": {"enabled": true, "max_disk_usage_percent": 90},
"usage": {"resident_memory_percent": 12, "disk_usage_percent": 46},
"peers": {
"3421...": {"resident_memory_percent": 12, "disk_usage_percent": 46, "exceeded": false},
"7719...": {"resident_memory_percent": 9, "disk_usage_percent": 91, "exceeded": true}
}
}
응답에서:
config는 요청을 처리한 노드의 쿼터 구성이에요.usage는 같은 노드의 현재 메모리와 디스크 사용량을 보고해요.peers는 각 피어가 자신에 대해 보고하는 내용으로, 피어 ID를 키로 해요. 응답하지 않는 피어는 호출을 실패시키는 대신 목록에서 빠져요. 그래서 누락된 피어를 신호로 삼아야 해요. 공간이 부족한 노드일수록 타임아웃 날 가능성이 높거든요. 분산 모드로 실행하지 않으면peers는 없어요.
참고: 피어가
exceeded를true로 보고하면서, 보고한 사용률은 이미 설정된 한계 아래로 돌아온 경우가 있어요. 이는 사용량이 충분히 내려갈 때까지 한계를 붙잡아 두는 release margin 때문이지, 불일치가 아니에요.
어떤 컬렉션이 사용량을 차지하는지 알아보려면 컬렉션 메모리 사용량 모니터링을 참고해요.
릴리스 마진 (Release Margin)
한계(limit)는 사용량이 그 수준에 도달하는 순간 발동되지만, 해제는 사용량이 release_margin_percent 퍼센트 포인트만큼 그 아래로 내려간 뒤에야 이뤄져요. 기본 마진이 5이면, max_disk_usage_percent가 90으로 설정된 노드는 90%에서 쓰기를 멈추고 85% 아래로 내려가야 다시 쓰기를 시작해요.
쿼터 구성을 변경하면 발동된 한계가 해제되므로, 새 한계가 마진을 기다리는 대신 즉시 적용돼요.
사용량이 마진 안에 머물러 있는 동안에는, 거부 메시지가 더 이상 초과되지 않는 한계를 주장하는 대신 상황을 이렇게 설명해요.
Disk usage is at 87% of total capacity. It reached the configured limit of 90%
and has to fall below 85% before this node takes writes again.
쿼터 모니터링 (Monitoring Quotas)
각 노드는 현재 한계에 있거나 넘었는지를 /metrics의 quota_exceeded 메트릭으로 보고해요. 메모리와 디스크는 각각 다른 일련번호(series)를 가져요. 왜냐하면 둘을 해제하는 방법이 다르기 때문이죠.
quota_exceeded{resource="memory"} 0
quota_exceeded{resource="disk"} 1
노드는 사용량이 한계에 도달하는 순간부터 release margin 아래로 내려갈 때까지 1을 보고해요. 사용량이 설정된 한계 아래로 내려간 뒤에도 이 series가 한동안 1로 유지될 거라고 예상해야 해요.
Qdrant는 한계가 없는 리소스나 쿼터가 비활성화된 동안에는 아예 series를 내보내지 않아요.
/telemetry 엔드포인트는 피어가 시행 중인 쿼터 구성과 함께 같은 판정을 최상위 quota 필드로 보고해요. 이는 클러스터가 합의한 내용이 아니라 해당 피어가 적용하고 있는 내용을 반영하므로, 컨센서스 업데이트를 놓친 피어가 여기에 나타나요.
더 알아보기 (Learn more)
- 운영 구성 전체 — Qdrant 설정·운영 주제 모음
- 컬렉션 메모리 사용량 모니터링 — 사용량의 원인 파악
- 일관성 보장 —
write_consistency_factor동작 원리