
Primary Shard · Replica · Node를 몇 개로 잡아야 할까?
앞 단계에서 구조를 이렇게 배웠습니다.
Document
↓
Index
↓
Primary Shard
↓
OpenSearch Node
↓
Replica Shard
이제 실무에서 가장 중요한 질문으로 넘어갑니다.
“그래서 Primary Shard는 몇 개 만들고, Replica는 몇 개 두고, Node는 몇 대가 필요한가?”
여기부터가 실제 OpenSearch 용량 산정과 아키텍처 설계입니다.
OpenSearch 공식 문서도 일반적인 시작점으로 Shard 하나를 약 10~50GB 범위로 유지하는 것을 제시하며, Shard를 무조건 많이 만드는 것은 오히려 Cluster에 부담을 준다고 설명합니다. (OpenSearch Documentation)
1️⃣ 먼저 세 가지를 완전히 구분하자
예를 들어 아래와 같이 설정했다고 하겠습니다.
{
"number_of_shards": 3,
"number_of_replicas": 1
}
뜻은:
Primary Shard = 3개
Replica = Primary마다 1개
따라서 실제 Cluster에 존재하는 Shard 수는:
Primary
P0
P1
P2
Replica
R0
R1
R2
총 Shard = 6개
즉 공식처럼 기억하면 편합니다.
전체 Shard 수
=
Primary Shard 수 × (1 + Replica 수)
예:
PrimaryReplica총 Shard
| 3 | 0 | 3 |
| 3 | 1 | 6 |
| 3 | 2 | 9 |
| 10 | 0 | 10 |
| 10 | 1 | 20 |
| 10 | 2 | 30 |
여기서 Replica=1은 Replica가 총 1개라는 뜻이 아닙니다.
각 Primary마다 하나씩 생깁니다.
2️⃣ Replica 0이면 어떻게 될까?
설정:
Primary = 3
Replica = 0
그러면:
P0
P1
P2
밖에 없습니다.
3개 Node라면 예를 들어:
Node 1
└─ P0
Node 2
└─ P1
Node 3
└─ P2
깔끔합니다.
하지만 문제가 있습니다.
Node 2 장애:
Node 2 ❌
└─ P1 ❌
Replica가 없으므로 P1 데이터에 대한 정상적인 복구 경로가 없습니다.
따라서 운영 서비스에서는 일반적으로 위험합니다.
OpenSearch 공식 성능 가이드에서도 대량 색인 시 일시적으로 Replica를 0으로 두면 쓰기 성능을 높일 수 있지만, 그 상태에서 Node가 실패하면 데이터 손실 위험이 있다고 경고합니다. (OpenSearch Documentation)
Replica 0이 적합할 수 있는 경우
예를 들어:
개발 환경
테스트 환경
다시 생성 가능한 데이터
Bulk Import 중 임시 설정
등입니다.
3️⃣ Replica 1이면?
가장 이해하기 쉬운 운영 구성입니다.
Primary = 3
Replica = 1
따라서:
P0 → R0
P1 → R1
P2 → R2
총:
3 × (1 + 1)
= 6 Shards
입니다.
3 Node라면 예를 들어:
┌─────────────┐
│ Node 1 │
│ │
│ P0 │
│ R2 │
└─────────────┘
┌─────────────┐
│ Node 2 │
│ │
│ P1 │
│ R0 │
└─────────────┘
┌─────────────┐
│ Node 3 │
│ │
│ P2 │
│ R1 │
└─────────────┘
OpenSearch는 같은 Shard의 Primary와 Replica를 같은 Node에 배치하지 않습니다. (OpenSearch Documentation)
그래서 Node 1이 죽더라도:
Node1 ❌
P0 ❌
다른 Node에:
Node2
└─ R0
가 있기 때문에 R0을 Primary로 승격시킬 수 있습니다.
⭐ 초보 단계에서의 기준
운영 Cluster라면 우선:
Replica = 1
을 기본 출발점으로 생각하면 좋습니다.
4️⃣ Replica 2이면?
이번에는:
Primary = 3
Replica = 2
라고 해봅시다.
Primary 하나당 복사본이 2개입니다.
P0
├─ R0-1
└─ R0-2
P1
├─ R1-1
└─ R1-2
P2
├─ R2-1
└─ R2-2
총 Shard 수:
3 × (1 + 2)
= 9개
3 Node라면 논리적으로 이런 모습이 가능합니다.
Node 1
├─ P0
├─ R1
└─ R2
Node 2
├─ P1
├─ R0
└─ R2
Node 3
├─ P2
├─ R0
└─ R1
즉 같은 데이터가:
Primary
+
Replica #1
+
Replica #2
총 3곳에 존재합니다.
5️⃣ Replica를 많이 만들면 무조건 좋은가?
아닙니다. ❌
장점도 있지만 비용이 생깁니다.
Replica 증가의 장점
장애 대응 ↑
검색 처리 능력 ↑
데이터 복제본 ↑
Replica도 검색 요청을 처리할 수 있기 때문에 검색 중심 Cluster에서는 처리량 향상에 도움이 될 수 있습니다. (OpenSearch Documentation)
하지만:
Replica 증가
↓
디스크 사용량 증가
↓
쓰기 작업 증가
↓
네트워크 복제 증가
↓
Shard 관리 부담 증가
가 발생합니다.
6️⃣ 저장공간 차이를 보면 훨씬 쉽다
원본 Index 데이터가:
1 TB
라고 해보겠습니다.
Replica 0
Primary 데이터 = 1TB
총 저장량 ≈ 1TB
Replica 1
Primary = 1TB
Replica = 1TB
총 ≈ 2TB
Replica 2
Primary = 1TB
Replica1 = 1TB
Replica2 = 1TB
총 ≈ 3TB
대략적인 데이터 저장량 관점에서는:
총 데이터량
≈
Primary 데이터량 × (Replica + 1)
입니다.
물론 실제 디스크 산정에서는 segment, translog, merge 여유 공간, watermark, OS 등을 추가로 고려해야 합니다.
7️⃣ 그렇다면 Primary Shard는 몇 개가 좋은가?
여기가 핵심입니다. ⭐
Primary Shard 수는 단순히:
Node 수와 동일
하게 만드는 것이 아닙니다.
가장 먼저 봐야 하는 것이:
Index 전체 크기와 목표 Shard 크기
입니다.
OpenSearch 공식 입문 문서에서는 일반적인 기준으로 Shard당 10~50GB 정도를 제시합니다. (OpenSearch Documentation)
따라서 아주 단순한 초기 계산은:
Primary Shard 수
≈
Primary 데이터 크기
÷
목표 Shard 크기
입니다.
8️⃣ 예를 들어 하루 로그가 300GB라면?
하루 Index가:
gpu-logs-2026.08.09
300GB
라고 하겠습니다.
Shard 목표를:
30GB
로 잡으면:
300GB ÷ 30GB
= 10
따라서 시작점으로:
Primary Shard ≈ 10개
를 검토할 수 있습니다.
구조:
Index 300GB
├─ P0 ≈ 30GB
├─ P1 ≈ 30GB
├─ P2 ≈ 30GB
├─ P3 ≈ 30GB
├─ P4 ≈ 30GB
├─ P5 ≈ 30GB
├─ P6 ≈ 30GB
├─ P7 ≈ 30GB
├─ P8 ≈ 30GB
└─ P9 ≈ 30GB
실제로 데이터가 정확히 30GB씩 균등하게 나뉜다는 의미라기보다는 용량 설계를 위한 목표치입니다.
9️⃣ 질문의 핵심: Node 3대 + Primary Shard 10개라면?
아주 좋은 실무 예입니다.
조건:
Data Node = 3대
Primary Shard = 10
Replica = 0
라고 해봅시다.
OpenSearch는 Shard를 가능한 균형 있게 분산하려고 합니다.
예를 들면:
Node 1
├─ P0
├─ P3
├─ P6
└─ P9
총 4개
Node 2
├─ P1
├─ P4
└─ P7
총 3개
Node 3
├─ P2
├─ P5
└─ P8
총 3개
즉:
10 ÷ 3
= 3개씩 + 1개 남음
그래서:
4 / 3 / 3
처럼 배치될 수 있습니다.
🔟 중요한 오해 하나
Primary Shard가 10개라고 해서:
Node도 10대 필요
한 것이 아닙니다. ❌
하나의 Node에 여러 Shard가 존재할 수 있습니다.
Node1
├─ Shard
├─ Shard
├─ Shard
└─ Shard
가능합니다.
반대로:
Node = 10
Primary = 3
라면 해당 Index의 Primary만 놓고 보면 모든 Node를 골고루 활용하지 못할 수 있습니다.
1️⃣1️⃣ Node 3대 + Primary 10개 + Replica 1이면?
이제 실무에 가까워집니다.
Node = 3
Primary = 10
Replica = 1
전체 Shard는:
10 × 2
= 20개
입니다.
대략적으로 Node당:
20 ÷ 3
≈ 6.7
즉:
Node1 ≈ 7 Shards
Node2 ≈ 7 Shards
Node3 ≈ 6 Shards
형태로 분산됩니다.
예시는:
Node 1
--------------------------------
P0
P3
P6
P9
R1
R4
R7
Node 2
--------------------------------
P1
P4
P7
R0
R2
R5
R8
Node 3
--------------------------------
P2
P5
P8
R3
R6
R9
실제 배치는 Cluster 상태, 디스크, allocation rules 등에 따라 달라질 수 있지만 중요한 원칙은:
P0와 R0
P1과 R1
P2와 R2
...
가 같은 Node에 존재하지 않는다는 것입니다. (OpenSearch Documentation)
1️⃣2️⃣ 그런데 왜 10 Shard보다 9 Shard가 예쁠까?
Node가 3개라면:
Primary = 9
일 경우:
9 ÷ 3
= 3
입니다.
따라서:
Node1 → 3 Primary
Node2 → 3 Primary
Node3 → 3 Primary
깔끔합니다.
OpenSearch의 최신 성능 튜닝 문서 역시 쓰기 분산을 고려할 때 Index의 Shard 수를 Data Node 수의 배수로 설정하는 방식을 하나의 방법으로 설명합니다. (OpenSearch Documentation)
예를 들어:
3 Node
Primary 후보
3
6
9
12
15
...
처럼 생각할 수 있습니다.
하지만 여기서 매우 중요한 점:
Node 수의 배수라고 무조건 좋은 것은 아닙니다.
먼저 Shard 크기가 적절한지를 확인해야 합니다.
1️⃣3️⃣ 예를 들어 300GB Index라면
Node:
3
Index:
300GB
Primary = 3
300 ÷ 3
≈ 100GB/Shard
공식 가이드의 일반적인 10~50GB 출발점보다 큽니다.
Primary = 6
300 ÷ 6
≈ 50GB
꽤 합리적인 시작점이 될 수 있습니다.
Primary = 9
300 ÷ 9
≈ 33GB
역시 좋은 후보입니다.
Primary = 30
300 ÷ 30
≈ 10GB
가능할 수 있지만 Shard 수가 많아집니다.
Primary = 300
300 ÷ 300
≈ 1GB
이건 대부분의 이런 워크로드에서 지나치게 잘게 쪼갠 상태일 가능성이 높습니다.
1️⃣4️⃣ Shard가 너무 많으면 왜 안 좋은가? 💣
이것을 Oversharding이라고 합니다.
예:
300GB Index
Primary 300개
≈ 1GB / Shard
보기에는:
"엄청 병렬 처리되니까 빠르겠네?"
싶지만 그렇지 않습니다.
각 Shard 자체가 독립적인 검색/저장 단위이기 때문에 관리 비용이 있습니다.
Shard 증가
↓
Cluster Metadata 증가
Shard 증가
↓
Heap 사용 증가
Shard 증가
↓
검색 Fan-out 증가
Shard 증가
↓
Merge / Recovery 작업 증가
Shard 증가
↓
Cluster 관리 복잡성 증가
공식 문서도 Shard를 더 많이 만드는 것이 항상 더 좋은 것이 아니며, 예를 들어 400GB Index를 1,000 Shard로 쪼개는 것은 불필요한 Cluster 부담을 만든다고 설명합니다. (OpenSearch Documentation)
1️⃣5️⃣ 반대로 Shard가 너무 적으면?
예를 들어:
1TB Index
Primary = 1
이라면:
Shard 0 ≈ 1TB
입니다.
문제:
검색 병렬성 ↓
Shard Recovery 시간 ↑
Node 장애 시 이동 데이터 ↑
Merge 부담 ↑
특정 Node 부하 집중 가능
따라서:
Shard 너무 많음 ❌
Shard 너무 큼 ❌
둘 사이의 균형을 맞춰야 합니다.
1️⃣6️⃣ 실무에서는 이렇게 계산하면 쉽다
예를 들어 Kubernetes 로그가:
하루 600GB
발생한다고 해보겠습니다.
보관:
30일
Replica:
1
입니다.
Step 1. 하루 Primary 데이터
600GB
Step 2. Shard 목표 크기 설정
예를 들어:
30GB
Step 3. Primary Shard 계산
600 ÷ 30
= 20 Primary Shards
Step 4. Replica 포함
20 Primary
+
20 Replica
= 40 Shards / day
1️⃣7️⃣ 30일이면?
단순하게 계산하면:
40 Shards/day
×
30 days
= 1,200 Shards
입니다.
여기서 중요한 개념이 등장합니다.
❗ OpenSearch 용량 설계는 Index 하나만 보면 안 됩니다.
전체 Cluster에서:
Index 개수
×
Index당 Shard
×
Replica
×
보관 기간
을 봐야 합니다.
1️⃣8️⃣ 디스크도 계산해보자 💾
하루 원본:
600GB
30일:
600GB × 30
= 18TB
Replica 1:
18TB × 2
= 36TB
여기까지만 보고:
36TB 디스크면 되겠네!
하면 위험합니다.
실제 운영에서는:
Primary Data
+
Replica
+
Segment Merge 여유 공간
+
Translog
+
OS / 기타
+
장애 시 재배치 공간
+
Disk Watermark 여유
를 고려해야 합니다.
1️⃣9️⃣ Disk Watermark도 중요하다 🚨
OpenSearch는 디스크가 꽉 차기 전에 Shard 배치를 제한합니다.
현재 공식 Cluster 설정 문서 기준으로 기본 low watermark는 **85%**입니다. 즉 디스크 사용률이 해당 수준에 도달하면 Shard allocation에 제약이 생기기 시작합니다. (OpenSearch Documentation)
그래서:
10TB Disk
→ 데이터 10TB까지 사용
하는 식으로 설계하면 안 됩니다.
운영에서는 상당한 여유 공간을 남겨야 합니다.
2️⃣0️⃣ 3 Node라면 디스크는 어떻게 계산될까?
가령 Replica 포함 실제 데이터량을:
36TB
라고 하겠습니다.
Data Node 3대라면 단순 평균:
36TB ÷ 3
= 12TB / Node
입니다.
하지만 딱:
12TB × 3 Node
로 만들면 운영 여유가 없습니다.
Node 장애도 생각해야 하기 때문입니다.
2️⃣1️⃣ Node 한 대가 죽으면 무슨 일이 벌어질까?
정상 상태:
Node1 Node2 Node3
P/R P/R P/R
Node3 장애:
Node1 Node2 Node3
❌
OpenSearch는 가능한 경우 남은 Node들에게 Replica를 재배치하려고 합니다.
Node1
↑
Shard ──┤
↓
Node2
따라서 Node1과 Node2에 추가 Shard를 수용할 공간이 있어야 합니다.
이게 바로:
N+1 관점 용량 설계
와 연결됩니다.
2️⃣2️⃣ Replica 수에 따른 장애 허용 개념
단순화하면:
Replica 0
P
Node 장애
→ 데이터 가용성 위험
Replica 1
P
+
R
서로 다른 Node에 존재하므로 일반적으로 한 Node 장애에 대응할 수 있는 구조가 됩니다.
Replica 2
P
+
R
+
R
적절히 서로 다른 Node/Zone에 배치한다면 더 높은 수준의 장애 대응이 가능합니다.
하지만 단순히 Replica 숫자만 늘린다고 Zone 장애까지 자동으로 완벽하게 대응하는 것은 아닙니다.
Rack/Zone 단위 장애까지 고려한다면 Shard Allocation Awareness 같은 배치 정책을 함께 사용해야 합니다. OpenSearch도 Node attribute와 zone awareness를 이용해 Primary와 Replica를 서로 다른 장애 도메인에 분산하는 기능을 제공합니다. (OpenSearch Documentation)
2️⃣3️⃣ 실무에서는 이렇게 생각하면 된다
예를 들어:
Data Node = 3
일 데이터 = 300GB
Shard 목표 = 30~50GB
Replica = 1
이라면:
후보 A
Primary = 6
300 ÷ 6
= 50GB
좋은 시작 후보입니다.
전체:
6 Primary
+
6 Replica
= 12 Shards
Node당 평균:
12 ÷ 3
= 4 Shards
후보 B
Primary = 9
300 ÷ 9
≈ 33GB
역시 적절한 후보입니다.
전체:
9 Primary
+
9 Replica
= 18 Shards
Node당:
18 ÷ 3
= 6 Shards
후보 C
Primary = 30
≈ 10GB / Shard
가능하지만 Shard 수 증가를 고려해야 합니다.
2️⃣4️⃣ 그래서 6이 좋아? 9가 좋아?
여기서는 정답이 없습니다.
다음 요소를 함께 봐야 합니다.
항목확인
| 하루 데이터량 | GB/day |
| 보관 기간 | 7/30/90일 |
| Data Node 수 | 몇 대 |
| Node CPU | vCPU |
| Node RAM | GB |
| JVM Heap | GB |
| Disk | SSD/NVMe |
| 검색량 | Query/sec |
| 색인량 | Document/sec |
| Document 크기 | KB |
| Replica | 0/1/2 |
| 장애 허용 | Node / Rack / Zone |
| 검색 SLA | 응답시간 |
따라서 정확한 설계는 결국 실제 워크로드 Benchmark로 검증해야 합니다.
OpenSearch 역시 실제 Production 설정에 가까운 환경에서 Benchmark를 수행하도록 권고합니다. (OpenSearch Documentation)
2️⃣5️⃣ 지금 단계에서는 이 공식 3개만 기억하세요 ⭐
공식 ① Shard 크기
Primary 데이터량
──────────────
Primary Shard 수
공식 ② 전체 Shard 개수
Primary Shard
×
(Replica + 1)
공식 ③ 대략적인 저장량
Primary 데이터량
×
(Replica + 1)
입니다.
예:
300GB
6 Primary
Replica 1
이면:
Shard Size
≈ 300 / 6
≈ 50GB
전체 Shard:
6 × 2
= 12
저장 데이터:
300GB × 2
≈ 600GB
가 됩니다.
🎯 전체 설계 그림
예를 들어:
Kubernetes 로그
↓
Fluent Bit
↓
OpenSearch
하루 로그
300GB
↓
Index
gpu-logs-YYYY.MM.DD
↓
6 Primary Shards
↓
Replica = 1
↓
총 12 Shards
↓
3 Data Nodes
배치는 대략:
gpu-logs Index
│
┌────────────┼────────────┐
↓ ↓ ↓
Node 1 Node 2 Node 3
------ ------ ------
P0 P1 P2
P3 P4 P5
R1 R2 R0
R4 R5 R3
결과:
Node당
Primary 2개
Replica 2개
총 4 Shards
아주 균형 잡힌 구조가 됩니다.
💡 실무용 초보 기준으로 정리
처음 OpenSearch 로그 Cluster를 설계한다면 다음 순서로 생각하세요.
① 하루 로그량을 확인한다
↓
② 보관 기간을 확인한다
↓
③ Shard당 약 10~50GB를 초기 후보로 잡는다
↓
④ Primary Shard 수를 계산한다
↓
⑤ 운영이면 Replica 1을 우선 검토한다
↓
⑥ Primary + Replica 총 Shard 수 계산
↓
⑦ Data Node에 균등 분산 가능한지 확인
↓
⑧ Replica 포함 디스크 계산
↓
⑨ Disk 여유 + Node 장애 여유 확보
↓
⑩ 실제 로그로 Benchmark
🔥 가장 중요한 포인트
Node 3대니까 Primary Shard 3개가 아닙니다.
정확한 접근은:
데이터량 → 목표 Shard 크기 → Primary 개수 → Replica → 총 Shard → Node 배치 → CPU/RAM/Disk 검증
순서입니다.
그리고 OpenSearch가 커질수록 단순히 TB만 계산하는 것이 아니라 Shard 수까지 반드시 용량 산정 대상으로 관리해야 합니다. (OpenSearch Documentation)
다음 단계에서는 이 내용을 그대로 이어서 “하루 로그 1TB, 30일 보관, Replica 1, Data Node 3/6/9대일 때 실제 서버 CPU·RAM·NVMe 용량을 어떻게 산정하는지”를 예제로 계산하면, 실제 구축 제안서 수준의 OpenSearch Capacity Planning까지 연결할 수 있습니다.
'J-H-T > OpenSearch' 카테고리의 다른 글
| [🔍 OpenSearch 내부 구조 쉽게 이해하기] Index → Document → Shard → Replica → Node (0) | 2026.08.09 |
|---|---|
| [🔍 OpenSearch란 무엇일까?] Fluent Bit · Logstash까지 이해하기! (0) | 2026.08.09 |
댓글