ELK 관리자가 알아야 할 A to Z — 공식 문서로 검증한 13가지
ELK 운영의 목표는 하나다. 로그를 잃지 않으면서, 필요할 때 5분 안에 찾을 수 있게 만드는 것. 두 목표가 충돌하면 대개 앞이 이긴다. 그런데 ELK에서 데이터를 잃는 방식은 디스크가 터지는 것보다 훨씬 조용하다. 인덱스가 read-only로 바뀌고, 매핑 에러가 난 문서가 말없이 사라지고, 스냅샷에 닫힌 인덱스가 빠져 있다.
이 글은 그런 조용한 실패 지점 13개를 Elastic 공식 문서에서만 인용해 정리했다. 벤치마크 숫자나 “경험상” 값은 넣지 않았다. 확인 못 한 것은 마지막 ‘이 글의 한계’에 적어 뒀다.
0. 30초 요약
| # | 항목 | 핵심 | 안 지키면 |
|---|---|---|---|
| 1 | 샤드 크기 | 10~50GB, 샤드당 문서 2억 미만 | 오버샤딩 → 클러스터 불안정 |
| 2 | 삭제 | 문서 말고 인덱스를 지운다 | 삭제한 문서가 계속 자원 소모 |
| 3 | 매핑 | 기본 필드 상한 1000, 객체 경로도 카운트 | 매핑 폭발 → OOM |
| 4 | JVM 힙 | RAM의 50% 이하 그리고 26GB 이하 | 압축 포인터 해제 + GC 지연 |
| 5 | 디스크 워터마크 | 85 / 90 / 95% → 전 인덱스 read-only | Kibana까지 같이 죽음 |
| 6 | 마스터 노드 | 개수는 작게 고정, 스케일은 non-master로 | 쿼럼 붕괴 |
| 7 | 데이터 티어 + ILM | hot→warm→cold→frozen, 롤오버 기준은 프라이머리 크기 | 비용 폭증 or 성능 붕괴 |
| 8 | 스냅샷 | 닫힌 인덱스는 백업 안 됨 | 복구 시점에야 발견 |
| 9 | 쿼리 vs 필터 | 점수 필요 없으면 filter | 캐시 못 쓰고 CPU 낭비 |
| 10 | 디스크 절약 | dynamic string 이중 매핑 끄기, force merge는 읽기전용에만 | 저장량 2배 + 스냅샷 비용 증가 |
| 11 | Logstash PQ | 기본 비활성, NFS 미지원 | 재시작 시 in-flight 유실 |
| 12 | Logstash DLQ | 기본 비활성, 수동 정리 필요 | 매핑 에러 이벤트 소리 없이 증발 |
| 13 | 클러스터 샤드 한도 | 노드당 non-frozen 1000 | 새 인덱스 생성 실패 |
가장 위험한 건 5번(워터마크) 과 8번(스냅샷) 이다. 5번은 새벽에 깨우고, 8번은 깨울 기회조차 주지 않는다.
1. 샤드 크기 — 오버샤딩이라는 이름의 병
Elastic 공식 Size your shards 문서가 제시하는 기준선:
- 샤드 크기는 10GB~50GB 사이를 목표로 한다.
- 샤드당 문서 수는 2억 개 미만으로 유지한다(하드 리밋은 약 20억).
- “Too many shards can degrade search performance and make the cluster unstable. This is referred to as oversharding.”
왜 작은 샤드를 많이 만들면 안 되는가. 같은 문서의 두 문장이 핵심이다.
“Every index and every shard requires some memory and CPU resources. In most cases, a small set of large shards uses fewer resources than many small shards.”
“Searches run on a single thread per shard.”
샤드당 스레드 하나다. 검색이 수백 개 샤드에 걸치면 검색 스레드풀이 그대로 고갈된다. “샤드를 늘리면 병렬로 빨라지겠지”라는 직관이 정확히 반대로 작동하는 지점이다.
그리고 샤드 개수는 사후에 못 바꾼다. 같은 문서는 크기를 잘못 잡았을 때의 교정 수단으로 Split Index와 Reindex를 지목하며, “Restore Snapshot and/or Clone Index would be insufficient“라고 명시한다. 스냅샷 복구로 샤드 수를 고칠 수 있다고 생각했다면 그게 오해다.
시계열 로그라면 데이터 스트림 + ILM 롤오버로 크기를 자동 관리하는 게 정석이다. 문서가 제안하는 롤오버 조건은 max_primary_shard_size: 50gb 와 min_primary_shard_size: 10gb 조합이다.
2. 문서를 지우지 말고 인덱스를 지워라
같은 문서에 굵은 제목으로 박혀 있는 항목이다.
“Delete indices, not documents.”
이유는 Lucene의 구조 때문이다. 삭제된 문서는 즉시 사라지지 않고 삭제 표시만 된 채 세그먼트 병합 시점까지 계속 자원을 소모한다. 반면 인덱스를 통째로 지우면 파일이 그대로 사라진다.
로그 보존 정책을 delete_by_query로 구현하고 있다면, 그건 매일 클러스터에 병합 부하를 주는 구조다. 시간 기반 인덱스 + ILM delete 단계로 바꾸는 게 맞다.
3. 매핑 폭발 — 상한은 1000이고, 세는 법이 직관과 다르다
Elastic Mapping 문서:
“Defining too many fields in an index can lead to a mapping explosion, which can cause out of memory errors and difficult situations from which to recover.”
Mapping limit settings의 index.mapping.total_fields.limit 기본값은 1000이고, 넘으면 Limit of total fields [X] has been exceeded 에러가 난다.
함정은 세는 방식이다. 문서는 “The setting counts all mappers, not just leaf fields”라고 못 박고, 다음이 전부 카운트된다고 나열한다.
- 객체 매퍼 — 점(
.)으로 구분된 경로의 각 단계가 따로 카운트 - 리프 필드 매퍼
- 멀티필드 —
.keyword,.raw각각 별도 - 필드 별칭
- 런타임 필드
문서의 예시: host.os.name 하나가 host(객체) + host.os(객체) + host.os.name(필드) = 3개로 계산된다. ECS 스타일 매핑에서 필드 수를 리프만 세다가 한도를 넘기는 게 흔한 실수라고 문서가 직접 지적한다(“A common mistake is counting only leaf fields”).
대응책도 문서가 제시한다.
- 깊은 중첩 경로가 많으면
subobjects: false— 위 예시가 3개에서 1개로 줄어든다(8.3+). - 키가 임의로 늘어나는 데이터는
flattened타입. - 한도 초과 시 색인 실패 대신 무시하고 싶으면
index.mapping.total_fields.ignore_dynamic_beyond_limit: true(기본false). 이때 빠진 필드는_ignored에 들어간다. total_fields.limit을 올릴 거면indices.query.bool.max_clause_count도 같이 올리라고 문서가 권한다.
그리고 대전제: 이미 매핑된 필드의 타입은 대부분 바꿀 수 없다. 공식 문서 표현으로 “In most cases, you can’t change mappings for fields that are already mapped. These changes require reindexing.” 신규 필드 추가와 신규 멀티필드 추가만 열려 있다.
4. JVM 힙 — 50% 규칙과 26GB 벽
JVM settings 문서는 기본값(자동 산정)을 쓰라고 먼저 권하고, 굳이 바꾼다면 두 조건을 동시에 만족시키라고 한다.
Xms/Xmx를 노드 가용 메모리의 50% 이하로. Elasticsearch는 힙 외에도 네트워크 off-heap 버퍼와 OS 파일시스템 캐시에 크게 의존한다. 문서 표현: “It’s normal for Elasticsearch to use more memory than the limit configured with theXmxsetting.”- compressed oops 임계값 이하로. “The exact threshold varies but 26GB is safe on most systems and can be as large as 30GB on some systems.” 확인 방법은 로그의
heap size [1.9gb], compressed ordinary object pointers [true]또는 nodes info API의jvm.using_compressed_ordinary_object_pointers.
문서의 경고 두 줄이 중요하다.
“Larger heaps can also cause longer garbage collection pauses.”
“If you set the heap size too large, Elasticsearch may perform poorly and nodes may be terminated by the operating system.”
컨테이너/K8s에서 돌린다면 “total memory available”은 호스트가 아니라 컨테이너에 할당된 메모리를 뜻한다는 점도 문서가 명시한다.
그리고 Tune for search speed의 대응 문장:
“In general, you should make sure that at least half the available memory goes to the filesystem cache so that Elasticsearch can keep hot regions of the index in physical memory.”
힙을 키우면 검색이 빨라질 것 같지만, OS 캐시를 빼앗아 오히려 느려질 수 있다. 힙은 “남는 만큼 준다”가 아니라 “필요한 만큼만 준다”가 맞다.
ES_JAVA_OPTS는 다른 모든 JVM 옵션을 덮어쓰므로 프로덕션에서 쓰지 말라고 문서가 권고한다. 커스텀 옵션은 루트 jvm.options를 고치지 말고 jvm.options.d/*.options에 넣는다.
5. 디스크 워터마크 — 95%에서 클러스터가 read-only가 된다
가장 자주 새벽에 사람을 깨우는 항목이다. Watermark errors 문서의 기본 임계값:
| 임계값 | 이름 | 동작 |
|---|---|---|
| 85% | low | 해당 노드에 레플리카 샤드 할당 중단 (신규 인덱스 프라이머리 제외) |
| 90% | high | 해당 노드에서 샤드를 다른 곳으로 재배치 |
| 95% | flood-stage | 해당 노드의 모든 인덱스를 read-only로 전환 |
flood-stage 로그는 이렇게 찍힌다.
flood-stage watermark [95%] exceeded on [NODE_ID][NODE_NAME], all indices on this node will be marked read-only
여기서 진짜 무서운 건 파급 범위다. 문서가 직접 경고한다.
“If the block affects related system indices, Kibana and other Elastic Stack features can become unavailable.”
즉 Kibana의 Kibana Server is not Ready yet 에러가 사실은 디스크 문제일 수 있다. 인제스트 API는 HTTP 429와 함께 이런 본문을 돌려준다.
{
"reason": "index [INDEX_NAME] blocked by: [TOO_MANY_REQUESTS/12/disk usage exceeded flood-stage watermark, index has read-only-allow-delete block];",
"type": "cluster_block_exception"
}
문서에 따르면 쓰기 블록은 디스크 사용량이 high 워터마크 아래로 떨어지면 자동 해제된다. 수동으로 블록을 풀기 전에 디스크부터 확보하는 게 순서다.
같은 문서가 꼽는 흔한 원인 네 가지: 예상 초과 유입량, 비효율적 인덱스 설정·불필요한 stored field, 과도한 레플리카 수(레플리카는 프라이머리와 동일한 디스크를 먹는다), 지나치게 큰 샤드(복구·리밸런싱이 느려짐).
6. 마스터 노드 — 쿼럼은 늘리는 게 아니라 고정하는 것
Discovery and cluster formation 문서의 운영 원칙:
“It is recommended to have a small and fixed number of master-eligible nodes in a cluster, and to scale the cluster up and down by adding and removing master-ineligible nodes only.”
용량이 부족하면 데이터 노드를 늘려라. 마스터 후보를 늘리는 게 아니다. 그리고 마스터 후보의 절반 이상을 한 번에 제거할 때는 추가 절차가 필요하다고 문서가 명시한다.
부트스트랩 관련해서도 명확하다. 자동 부트스트랩은 “inherently unsafe“이며, 프로덕션 모드에서는 cluster.initial_master_nodes로 첫 선거 참여 노드를 명시해야 한다. 그리고 Important settings의 경고:
“After the cluster forms successfully for the first time, remove the
cluster.initial_master_nodessetting from each node’s configuration and never set it again for this cluster.”
이 설정을 Helm values나 ConfigMap에 넣어 두고 잊는 게 흔한 사고 패턴이다. 재시작·전체 클러스터 재시작·기존 클러스터 합류 시 모두 설정하면 안 된다.
마스터 노드 힙 사이징 기준도 있다. Size your shards 문서:
“Master-eligible nodes should have at least 1GB of heap per 3000 indices.”
즉 힙 4GB짜리 마스터라면 인덱스 12000개 미만을 유지해야 한다. 매핑 힙 오버헤드는 Cluster stats API의 total_deduplicated_mapping_size로 볼 수 있다.
network.host를 루프백이 아닌 주소로 설정하는 순간 Elasticsearch는 이를 프로덕션 모드로 간주하고, 부트스트랩 체크 실패가 경고에서 기동 실패로 승격된다는 점도 기억해 둘 것.
7. 데이터 티어와 ILM — 비용은 티어로, 전환은 정책으로
Data tiers 문서 기준 정리:
| 티어 | 용도 | 특징 |
|---|---|---|
| content | 비시계열(제품 카탈로그 등) | 쿼리 성능 우선, 레플리카 1개 이상 권장 |
| hot | 최신·최다 조회 시계열 | 읽기·쓰기 모두 빨라야 함(SSD) |
| warm | 최근 몇 주 | 조회 빈도 낮음, 갱신 드묾 |
| cold | 드문 조회 | fully mounted searchable snapshot → 디스크 약 50% 절감 |
| frozen | 거의 조회 안 함 | partially mounted 전용 → warm 대비 최대 20배 저장 확장 |
cold 티어의 fully mounted 인덱스는 레플리카가 필요 없다(장애 시 스냅샷에서 복구). frozen은 전용 노드를 권장하며, 스냅샷 저장소에서 데이터를 가져와야 해서 cold보다 검색이 느리다.
주의할 점 하나. 문서는 같은 티어의 노드는 동일한 하드웨어 프로파일을 쓰라고 반복해서 말한다. 자원이 불균등한 노드가 섞인 티어는 hot spotting 위험이 높아진다.
기본 배치 규칙도 알아 둘 것. 일반 인덱스는 _tier_preference가 data_content, 데이터 스트림 백킹 인덱스는 data_hot으로 자동 설정된다. ILM이 cold로 옮길 때는 data_cold,data_warm,data_hot처럼 선호 순서 목록을 넣는데, 이는 해당 티어 노드가 없을 때 인덱스가 미할당 상태로 남는 걸 막기 위한 설계다.
ILM 쪽에서 실무상 걸리는 두 가지:
- 클러스터 전 노드가 같은 버전이어야 한다. 혼합 버전 클러스터에서 정책이 의도대로 동작한다는 보장이 없다.
- 기존 인덱스에 정책을 나중에 붙일 때는 rollover 액션을 넣으면 안 된다. 롤오버로 새 인덱스가 생기면 정책이 이어지지 않기 때문이다.
8. 스냅샷 — 닫힌 인덱스는 백업되지 않는다
Snapshot and restore 문서에서 가장 중요한 한 문장.
“Snapshots back up only open indices. If you close an index, it is not included in snapshots and you will not be able to restore the data.”
디스크 확보하려고 오래된 인덱스를 close 해 두는 관행이 있다면, 그 인덱스들은 백업에서 빠져 있다. 복구를 시도하는 순간에야 알게 된다.
스냅샷에 들어가는 것: 클러스터 상태, 영구(persistent) 클러스터 설정, 인덱스 템플릿, 인제스트 파이프라인, ILM 정책, 저장된 스크립트, feature state.
스냅샷에 안 들어가는 것: 일시(transient) 클러스터 설정, 등록된 스냅샷 저장소 정보, 노드 설정 파일, 보안 설정 파일.
그 밖에 알아야 할 성질들:
- 세그먼트가 불변이므로 스냅샷은 자동 중복 제거된다. 새 세그먼트만 복사되지만, 각 스냅샷은 논리적으로 독립이다.
- “A snapshot doesn’t represent a cluster at a precise point in time. Instead, each snapshot includes a start and end time.” — DB의 PITR 같은 정합 시점 보장이 아니다.
- 프라이머리 샤드 중 하나라도 사용할 수 없으면 스냅샷은 실패한다.
- 8.0부터 시스템 인덱스 백업·복구는 feature state가 유일한 방법이다.
- 하위 버전 클러스터로는 복구할 수 없다.
그리고 파일시스템 백업 금지 조항이 별도로 있다(Important settings):
“Don’t attempt to take filesystem backups of the data directory; there is no supported way to restore such a backup. Instead, use Snapshot and restore.”
같은 문단에 data 디렉터리에 바이러스 스캐너를 돌리지 말라는 항목도 있다. “A virus scanner can prevent Elasticsearch from working correctly and may modify the contents of the data directory.”
버전 함정: Elasticsearch가 받아도 Kibana가 거부한다
스냅샷 문서가 드는 실제 실패 사례다. Elasticsearch 쪽 복구는 통과했는데 Kibana가 기동하면서 죽는다.
FATAL Error: Kibana 8.1.0 deployment detected. Please upgrade to Kibana 8.18.0 or newer before upgrading to 9.x series.
문서의 결론은 단호하다. “Restoring an old snapshot directly to a 9.x cluster is not a shortcut around the normal upgrade paths.” 오래된 스냅샷을 최신 클러스터에 부어 넣어 업그레이드를 건너뛰려는 시도는 통하지 않는다.
정기 백업은 SLM(스냅샷 수명주기 관리)으로 자동화하는 게 표준이다.
9. 쿼리 vs 필터 컨텍스트
Query and filter context 문서 기준.
- 쿼리 컨텍스트는 “이 문서가 이 조건에 얼마나 잘 맞는가”에 답하고
_score를 계산한다. - 필터 컨텍스트는 “맞는가/아닌가” 이진 판정만 한다.
필터의 이점을 문서가 다섯 가지로 나열한다: 이진 로직, 점수 계산이 없어 더 빠름, 자주 쓰는 필터는 자동 캐시, CPU 소모 감소, 스코어 쿼리와 조합 가능.
로그 검색은 대부분 구조화 데이터 조건(타임스탬프 범위, status, host.name, log.level)이다. 문서가 필터에 특히 적합하다고 꼽는 것이 정확히 그것들 — 숫자, 날짜/타임스탬프, boolean, keyword, geo.
문서의 마지막 권고를 그대로 옮긴다.
“Use query clauses in query context for conditions which should affect the score of matching documents, and use all other query clauses in filter context.”
필터 컨텍스트가 적용되는 위치는 bool의 filter/must_not, constant_score의 filter, filter 집계다. bool의 must에 term 조건을 넣고 있다면 대부분 filter로 옮겨야 한다.
10. 디스크 사용량 튜닝 — 기본값이 낭비하는 것들
Tune for disk usage 문서에서 로그 파이프라인에 바로 적용되는 것들.
dynamic string 매핑을 그냥 두지 마라. 기본 동작은 문자열 필드를 text와 keyword 양쪽으로 색인한다. 문서 표현으로 “This is wasteful if you only need one of them.” ID류는 keyword만, 본문은 text만 있으면 된다. dynamic template으로 전부 keyword로 강제하는 예시가 문서에 있다.
점수가 필요 없는 text 필드는 match_only_text. 스코어링·위치 정보를 버려 “significant space”를 절약한다.
best_compression 코덱으로 _source와 stored field를 더 압축할 수 있다.
_source 자체를 줄이는 두 가지 선택지: synthetic _source(구독 필요, 검색 시 재구성, 원본과 미세하게 다를 수 있음) 또는 완전 비활성화(update·reindex·highlight가 동작 중단).
force merge는 읽기 전용 인덱스에만. 문서가 굵게 강조한다.
“We recommend only force merging a read-only index (meaning the index is no longer receiving writes).”
이유가 구체적이다. force merge는 5GB를 넘는 매우 큰 세그먼트를 만들 수 있는데, 이런 세그먼트는 일반 병합 대상에서 제외된다. 그러면 soft-delete된 문서(tombstone)가 정리되지 않고 급격히 쌓여 디스크 사용량과 검색 성능이 모두 나빠진다. 게다가 쓰기가 계속되는 인덱스를 반복 force merge하면 새 문서를 증분 백업할 수 없어 스냅샷 비용도 올라간다.
Linux readahead도 챙길 것. Tune for search speed 문서는 소프트웨어 RAID·LVM·dm-crypt 위에서 readahead가 수 MiB로 커지면 “severe page (filesystem) cache thrashing”이 발생한다며 128KiB를 권장한다. 확인은 lsblk -o NAME,RA,MOUNTPOINT,TYPE,SIZE.
그리고 스토리지 일반론:
“Elasticsearch clusters using directly-attached (local) storage generally perform better than those using remote storage.”
11. Logstash 영속 큐(PQ) — 기본값은 메모리다
Persistent queues 문서. 먼저 기본값부터. PQ는 기본 비활성이며 기본 queue.type은 memory다. 즉 아무 설정 없이 쓰는 Logstash는 비정상 종료 시 in-flight 이벤트를 잃는다.
PQ가 해결하지 못하는 것도 문서가 명시한다.
- 응답-요청 프로토콜이 아닌 input(tcp, udp, zeromq push+pull 등)은 보호할 수 없다. 수신 확인 메커니즘이 없기 때문. beats, http처럼 ACK가 있는 플러그인은 잘 보호된다.
- 체크포인트 커밋 전에 비정상 종료되면 데이터를 잃을 수 있다.
- 디스크 손상·장비 손실 같은 영구 장애는 못 막는다. 디스크에 쓴 데이터는 복제되지 않는다.
- “Network File System (NFS) is not supported.”
사이징 공식도 문서에 있다.
Bytes Received Per Second = Incoming Events Per Second * Raw Event Byte Size
Bytes Received Per Hour = Bytes Received per Second * 3600s
Required Queue Capacity = (Bytes Received Per Hour * Tolerated Hours of Downtime) * Multiplication Factor
Multiplication Factor는 이벤트 직렬화 오버헤드다. 문서 표에 따르면 오버헤드는 대략 이벤트당 200바이트 안팎으로 고정이라, 작은 이벤트일수록 배수가 폭발한다. 11바이트 평문은 배수 19.4, 1212바이트는 1.17, 10240바이트는 1.02. 짧은 로그 라인을 대량으로 흘리는 파이프라인이 큐 용량을 가장 많이 먹는다는 뜻이다.
문서의 예시 계산: 1000 EPS × 1KB = 시간당 3.5GB, 12시간 다운타임을 견디려면 queue.max_bytes ≈ 50GB.
주요 기본값: queue.max_bytes 1024mb(파이프라인당), queue.page_capacity 64mb, queue.checkpoint.acks/writes 각 1024. 내구성을 최대로 하려면 queue.checkpoint.writes: 1이지만 문서는 “can severely impact performance”라고 경고한다. 반대로 0으로 두면 최고 성능·최저 내구성이다.
문서가 인용한 실사용 패턴 하나가 인상적이다.
“In our deployment, we use one pipeline per output, and each pipeline has a large PQ. This configuration allows a single output to stall without blocking the input (and thus all other outputs), until the operator can restore flow to the stalled output and let the queue drain.”
출력 하나가 막혀도 나머지가 안 죽게 하는 output isolator 패턴이다.
큐가 깨졌을 때(Page file size is too small to hold elements)의 절차도 정해져 있다. pqcheck로 손상된 큐 식별 → Logstash 정지 → pqrepair 실행.
12. Logstash DLQ — 잘못된 이벤트를 버리지 않으려면
Dead letter queues 문서. 역시 기본 비활성(dead_letter_queue.enable: true로 켠다). 꺼져 있으면 처리 불가 이벤트에 대해 파이프라인이 멈추거나 이벤트를 버린다.
범위가 좁다는 걸 알아야 한다.
“The dead letter queue is currently supported only for the Elasticsearch output and conditional statements evaluation. The dead letter queue is used for documents with response codes of 400 or 404.”
여기서 오해하기 쉬운 지점이 하나 있다. HTTP 요청 자체가 실패하면(ES 접속 불가, HTTP 에러 코드) Elasticsearch output은 요청 전체를 무한 재시도하며, 이때 DLQ가 개입할 기회가 없다. DLQ가 쓰이는 건 Bulk API가 200 OK를 반환했지만 개별 문서가 실패한 경우다(errors 플래그 true). 대표 사례가 매핑 에러 — 문서의 예시는 geo_point 필드에 문자열 "home"이 들어간 케이스다.
운영상 반드시 알아야 할 것:
- DLQ는 자동으로 비워지지 않는다. “Even if you regularly process events, events remain in the dead letter queue. The dead letter queue requires manual intervention to clear it.”
dead_letter_queueinput 플러그인으로 읽어도 큐에서 삭제되지 않고 참조만 커밋된다. 공간을 회수하려면clean_consumed => true. - 기본 최대 크기 1024mb, 초과 시 기본 정책은
drop_newer(신규 유입 거부).drop_older로 바꾸면 오래된 것부터 버린다. dead_letter_queue.retain.age: 2d같은 나이 정책을 쓸 수 있지만, 검증 시점이 쓰기 시점과 셧다운 시점이라 지정 기간보다 오래 남아 있을 수 있다.- 여기도 NFS 미지원이고, 두 Logstash 인스턴스가 같은 DLQ 경로를 공유할 수 없다.
- DLQ input이 내보낸 이벤트는 다시 실패해도 DLQ로 재투입되지 않는다.
start_timestamp옵션으로 특정 시점 이후 이벤트만 처리할 수 있다.
DLQ를 켜 놓고 소비 파이프라인을 안 만들면 결국 1GB를 채우고 drop_newer로 조용히 버리기 시작한다. 켜는 것과 처리하는 것은 별개 작업이다.
13. 클러스터 샤드 한도와 나머지 안전장치
Size your shards 문서의 클러스터 샤드 한도:
- 노드당 non-frozen 샤드 1000개
- 전용 frozen 노드당 frozen 샤드 3000개
한도에 걸리면 새 인덱스 생성이 실패한다. 인덱스가 계속 늘어나는 로그 클러스터에서는 언젠가 반드시 만나는 벽이다.
Cluster-level shard allocation 문서에서 손대고 싶어지지만 손대면 안 되는 값들도 정리해 둔다. 동시 복구 관련 설정(node_concurrent_incoming_recoveries / outgoing / node_concurrent_recoveries, 기본 2)과 node_initial_primaries_recoveries(기본 4), 동시 리밸런스(cluster_concurrent_rebalance, 기본 2)에 대해 문서는 일관되게 같은 말을 반복한다.
“Increasing this setting may cause shard movements to have a performance impact on other activity in your cluster, but may not make shard movements complete noticeably sooner. We do not recommend adjusting this setting from its default.”
복구가 느리다고 이 값들을 올리는 건 대개 상황을 악화시킨다.
유지보수로 cluster.routing.rebalance.enable을 none으로 내렸다면, 문서의 당부를 기억할 것. “If you adjust this setting, remember to set it back to all as soon as possible.” 리밸런싱이 꺼진 채 잊힌 클러스터는 장애 후 복원력을 회복하지 못한다.
8.6부터 기본 할당기는 desired_balance로, 백그라운드에서 목표 배치를 계산한 뒤 옮긴다. 그 이전의 balanced 할당기는 포그라운드에서 돌면서 마스터의 다른 작업을 막았다.
한 줄씩 다시
- 샤드는 10~50GB, 문서 2억 미만. 검색은 샤드당 스레드 하나다.
- 문서 말고 인덱스를 지운다.
- 필드 상한 1000.
host.os.name은 3개로 센다. - 힙은 RAM의 50% 이하 그리고 26GB 이하. 나머지는 OS 캐시 몫.
- 95%에서 전 인덱스 read-only. Kibana가 안 뜨면 디스크부터 본다.
- 마스터 후보는 작게 고정.
initial_master_nodes는 첫 형성 후 지운다. - 티어 안 노드는 같은 스펙으로. 기존 인덱스 정책에 rollover 넣지 않는다.
- 닫힌 인덱스는 스냅샷에 없다. 파일시스템 백업은 복구 방법이 없다.
- 점수 필요 없으면 전부 filter 컨텍스트로.
- force merge는 쓰기가 끝난 인덱스에만.
- PQ는 기본 꺼져 있고, NFS에서 못 쓰고, 짧은 로그일수록 큐를 많이 먹는다.
- DLQ는 기본 꺼져 있고, 켜도 자동으로 안 비워진다.
- 노드당 샤드 1000. 복구 동시성 기본값은 건드리지 않는다.
이 글의 한계
- 버전 명시 없음: 인용한 문서 대부분은 Elastic Stack 9.x 기준 현행 문서다. 8.x 이하를 운영 중이라면 기본값과 가용성이 다를 수 있다(예:
subobjects: false는 8.3+, feature state 기반 시스템 인덱스 백업은 8.0+,desired_balance할당기는 8.6+). - 성능 수치 없음: “샤드를 몇 개로 줄이면 검색이 몇 % 빨라진다” 같은 수치는 공식 문서에 재현 가능한 형태로 없어서 넣지 않았다. 티어별 저장 절감(cold 약 50%, frozen 최대 20배)은 Elastic이 자사 문서에서 제시한 값으로, 중립적 제3자 검증 자료는 확인하지 못했다.
- 검증 못 한 영역: Filebeat/Elastic Agent 인제스트 경로, Kibana saved objects·spaces 운영, Elastic Agent와 Logstash 중 무엇을 쓸지에 대한 선택 기준, ECK 오퍼레이터 특유의 함정, 보안(TLS·인증·RBAC) 설정은 이 글에서 다루지 않았다.
- 비교 주장 없음: ELK vs Loki/OpenSearch/ClickHouse 같은 우열 비교는 중립적 헤드투헤드 벤치마크를 확보하지 못해 다루지 않았다.
- 환경 의존: 힙·샤드·큐 크기의 “적정값”은 문서도 반복해서 말하듯 워크로드에 따라 다르다. 여기 숫자들은 상한·하한 가드레일이지 목표치가 아니다.
References
① Elastic 공식 문서 (1차·공식)
- Size your shards
- Discovery and cluster formation
- Snapshot and restore
- Important settings configuration
- JVM settings
- Mapping / Mapping limit settings
- Data tiers / Index lifecycle management
- Watermark errors
- Cluster-level shard allocation and routing settings
- Query and filter context
- Tune for search speed / Tune for disk usage
- Logstash — Persistent queues / Dead letter queues
② 벤더 주장으로 라벨링한 것
- cold 티어 fully mounted searchable snapshot의 “약 50% 디스크 절감”, frozen 티어의 “warm 대비 최대 20배 저장 확장”은 Elastic 공식 문서의 자사 제품 설명이며, 재현 가능한 벤치마크 방법론은 문서에 제시되어 있지 않다.
③ 독자가 직접 확인할 것
- 자신의 스택 버전에 해당하는 문서(위 링크는 현행 버전 기준). 기본값은 메이저 버전 간 바뀐다.
GET _cluster/stats의total_deduplicated_mapping_size,GET _cat/shards,GET _cluster/allocation/explain— 위 가이드라인 대비 현재 클러스터의 실제 위치.