Back to Blog
ElasticsearchClusterNodeILMData LifecycleMigrationMonitoring

0x03. Elasticsearch 클러스터 운영

Elasticsearch 클러스터의 노드 구성, ILM을 통한 데이터 생명주기 관리, 그리고 마이그레이션과 모니터링을 알아본다.

Elasticsearch는 단일 서버에서도 동작하지만, 실서비스에서는 여러 노드로 구성된 클러스터(Cluster) 로 운영된다. 데이터가 수십 테라바이트로 늘어나고, 검색 트래픽이 초당 수천 건에 달하면 단일 노드로는 감당할 수 없기 때문이다.

이 글에서는 Elasticsearch 클러스터를 구성하는 노드의 종류, 클러스터 상태 관리, 데이터 생명주기 자동화(ILM), 그리고 버전 마이그레이션 전략까지 운영에 필요한 핵심 주제를 다룬다.


노드의 종류와 역할

Elasticsearch 클러스터는 하나 이상의 노드(Node) 로 구성된다. 각 노드는 elasticsearch.ymlnode.roles 설정을 통해 하나 이상의 역할을 부여받는다. 역할을 명시하지 않으면 모든 역할이 기본으로 활성화되지만, 프로덕션 환경에서는 역할을 분리하여 전담 노드를 구성하는 것이 권장된다.

Master Node

마스터 노드(Master Node) 는 클러스터의 두뇌 역할을 한다. 인덱스 생성/삭제, 샤드 할당 결정, 클러스터 내 노드 추적 등 클러스터 전체의 메타데이터를 관리하는 경량 작업을 담당한다.

# elasticsearch.yml
node.roles: ["master"]

마스터 노드는 실제 데이터를 저장하거나 검색 요청을 처리하지 않는다. 그 대신 클러스터의 안정성에 직접적인 영향을 미치므로, 프로덕션 환경에서는 전용 마스터 노드를 3대 이상 구성하여 장애 시에도 마스터 선출(election)이 가능하도록 해야 한다. 마스터 후보 노드가 홀수여야 스플릿 브레인(Split Brain) 문제를 방지할 수 있다.

Data Node

데이터 노드(Data Node) 는 실제 데이터를 저장하고 CRUD, 검색, 집계(aggregation) 등의 작업을 수행한다. 클러스터에서 가장 많은 리소스(CPU, 메모리, 디스크)를 사용하는 노드이다.

Elasticsearch는 데이터 계층(Data Tier) 아키텍처를 지원하며, 데이터 노드를 더 세분화할 수 있다.

역할설명
data_hot최신 데이터를 저장. 빠른 SSD 디스크 사용
data_warm조회 빈도가 낮아진 데이터. 중간 성능 디스크
data_cold거의 조회되지 않는 오래된 데이터. 대용량 HDD
data_frozen아카이브 수준. 필요 시에만 검색
data_content시계열이 아닌 일반 콘텐츠 데이터
# Hot 노드 예시
node.roles: ["data_hot", "ingest"]

이 계층 구조는 뒤에서 다룰 ILM(Index Lifecycle Management) 과 결합하여 비용 효율적인 데이터 관리를 가능하게 한다.

Coordinating Node

코디네이팅 노드(Coordinating Node) 는 클라이언트의 요청을 받아 적절한 데이터 노드로 라우팅하고, 각 노드에서 돌아온 결과를 집계(reduce) 하여 최종 응답을 반환한다. 일종의 스마트 로드 밸런서 역할이다.

모든 노드는 기본적으로 코디네이팅 역할을 수행한다. 하지만 node.roles를 빈 배열로 설정하면 코디네이팅 전용 노드가 된다.

# Coordinating 전용 노드
node.roles: []

검색 트래픽이 많은 환경에서는 전용 코디네이팅 노드를 두어 데이터 노드의 부하를 분산할 수 있다.

Ingest Node

인제스트 노드(Ingest Node) 는 데이터가 인덱싱되기 전에 인제스트 파이프라인(Ingest Pipeline) 을 적용하여 문서를 변환하고 보강하는 역할을 한다. 로그 데이터의 날짜 파싱, 필드 추가/제거, GeoIP 변환 등의 전처리를 수행한다.

node.roles: ["ingest"]

데이터 변환 로직이 무겁지 않다면 데이터 노드가 인제스트 역할을 겸할 수 있다. 하지만 복잡한 파이프라인이 대량의 데이터에 적용되는 경우에는 전용 인제스트 노드를 분리하는 것이 좋다.

ML Node

머신러닝 노드(ML Node) 는 Elasticsearch의 머신러닝 기능(이상 탐지, 추론 등)을 실행하는 전용 노드이다. ML 작업은 CPU와 메모리를 많이 소모하므로, 데이터 노드와 분리하여 검색 성능에 영향을 주지 않도록 한다.

node.roles: ["ml", "remote_cluster_client"]

노드 구성 전략 요약

소규모 클러스터에서는 한 노드가 여러 역할을 겸할 수 있지만, 규모가 커질수록 역할을 분리해야 한다. 일반적인 프로덕션 구성은 다음과 같다.

  • 전용 마스터 노드 3대: 클러스터 안정성 확보
  • 데이터 노드 N대: 트래픽과 데이터량에 따라 확장
  • 코디네이팅 노드 2대 이상: 검색 요청 분산
  • 인제스트 노드: 필요 시 전용 구성

클러스터 상태 관리

Green, Yellow, Red

Elasticsearch 클러스터는 샤드(Shard) 의 할당 상태에 따라 세 가지 건강 상태를 가진다.

상태의미
Green모든 프라이머리 샤드와 레플리카 샤드가 정상 할당
Yellow모든 프라이머리 샤드는 할당되었으나, 일부 레플리카 샤드가 미할당
Red일부 프라이머리 샤드가 미할당. 데이터 손실 위험

클러스터 상태는 _cluster/health API로 확인할 수 있다.

GET /_cluster/health
{
  "cluster_name": "my-cluster",
  "status": "green",
  "number_of_nodes": 5,
  "number_of_data_nodes": 3,
  "active_primary_shards": 10,
  "active_shards": 20,
  "relocating_shards": 0,
  "unassigned_shards": 0
}

Yellow 상태는 단일 노드 클러스터에서 흔히 발생한다. 레플리카 샤드는 프라이머리 샤드와 같은 노드에 배치될 수 없기 때문이다. 노드가 하나뿐이면 레플리카를 할당할 곳이 없어 자연스럽게 Yellow가 된다. 이 경우 노드를 추가하거나, 테스트 환경이라면 레플리카 수를 0으로 설정하면 된다.

PUT /my-index/_settings
{
  "number_of_replicas": 0
}

Red 상태는 즉각적인 대응이 필요하다. 해당 프라이머리 샤드가 포함된 노드가 복구되지 않으면 데이터가 유실될 수 있다.

샤드 할당 전략

Elasticsearch는 샤드를 노드에 자동으로 분배하지만, 몇 가지 전략으로 할당을 제어할 수 있다.

디스크 워터마크(Disk Watermark): 기본적으로 디스크 사용량이 85%를 초과하면 해당 노드에 새로운 샤드를 할당하지 않는다. 90%를 넘으면 기존 샤드를 다른 노드로 이동시키기 시작하며, 95%에 도달하면 인덱스를 읽기 전용으로 전환한다.

PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.disk.watermark.low": "85%",
    "cluster.routing.allocation.disk.watermark.high": "90%",
    "cluster.routing.allocation.disk.watermark.flood_stage": "95%"
  }
}

Shard Allocation Awareness: 물리적 인프라를 인식하도록 구성할 수 있다. 예를 들어 가용 영역(Availability Zone)을 태깅하면, 프라이머리와 레플리카 샤드가 서로 다른 영역에 배치되어 장애 내성이 높아진다.

# elasticsearch.yml
node.attr.zone: zone-a
cluster.routing.allocation.awareness.attributes: zone

노드 추가와 제거

노드 추가는 간단하다. 동일한 cluster.name을 설정한 새 노드를 시작하면 자동으로 클러스터에 합류하고, 마스터 노드가 기존 샤드를 재배치하여 부하를 분산한다.

노드 제거는 신중하게 진행해야 한다. 노드를 바로 종료하면 해당 노드의 샤드가 미할당 상태가 되어 클러스터 상태가 악화될 수 있다. 안전한 제거 절차는 다음과 같다.

# 1. 해당 노드에서 샤드를 다른 노드로 이동 (drain)
PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.exclude._name": "node-to-remove"
  }
}

# 2. 샤드 이동 완료 확인
GET /_cat/shards?v&h=index,shard,prirep,state,node

# 3. 샤드가 모두 이동한  노드 종료

ILM: 데이터 생명주기 관리

시계열 데이터(로그, 메트릭, 이벤트 등)는 시간이 지남에 따라 가치가 변한다. 오늘의 로그는 실시간 모니터링에 핵심이지만, 3개월 전 로그는 가끔 조회되는 정도이고, 1년 전 로그는 규정 준수 목적으로만 보관될 수 있다.

ILM(Index Lifecycle Management) 은 이러한 데이터의 생명주기를 자동으로 관리하는 기능이다. 인덱스가 일정 조건을 충족하면 다음 단계로 전환하며, 각 단계에서 적절한 작업(압축, 이동, 삭제 등)을 수행한다.

Hot-Warm-Cold-Delete 아키텍처

ILM의 핵심 개념은 데이터를 네 개의 단계(Phase) 로 나누어 관리하는 것이다. 여기에 frozen 단계를 추가하면 다섯 단계가 된다.

단계데이터 상태하드웨어 특성주요 작업
Hot활발히 쓰기/읽기고성능 SSDRollover
Warm읽기 위주, 쓰기 없음중간 성능Force Merge, Shrink
Cold드물게 읽기대용량 HDD읽기 전용 설정
Frozen거의 접근 안 함가장 저렴한 스토리지Searchable Snapshot
Delete보관 기간 만료-인덱스 삭제

이 아키텍처는 앞서 살펴본 data_hot, data_warm, data_cold, data_frozen 노드 역할과 직접 연결된다. ILM 정책이 인덱스를 Warm 단계로 전환하면, 해당 인덱스의 샤드가 자동으로 data_warm 노드로 이동한다.

ILM 정책 설정

ILM 정책은 _ilm/policy API로 생성한다. 다음은 로그 데이터를 위한 정책 예시이다.

PUT /_ilm/policy/log-policy
{
  "policy": {
    "phases": {
      "hot": {
        "min_age": "0ms",
        "actions": {
          "rollover": {
            "max_primary_shard_size": "50gb",
            "max_age": "1d"
          },
          "set_priority": {
            "priority": 100
          }
        }
      },
      "warm": {
        "min_age": "7d",
        "actions": {
          "forcemerge": {
            "max_num_segments": 1
          },
          "shrink": {
            "number_of_shards": 1
          },
          "set_priority": {
            "priority": 50
          }
        }
      },
      "cold": {
        "min_age": "30d",
        "actions": {
          "set_priority": {
            "priority": 0
          }
        }
      },
      "delete": {
        "min_age": "90d",
        "actions": {
          "delete": {}
        }
      }
    }
  }
}

이 정책의 동작은 다음과 같다.

  1. Hot 단계: 인덱스가 50GB에 도달하거나 1일이 경과하면 롤오버(Rollover) 한다. 기존 인덱스는 쓰기가 중단되고 새 인덱스가 생성된다.
  2. Warm 단계: 롤오버 후 7일이 지나면 Warm으로 전환한다. 세그먼트를 1개로 강제 병합(Force Merge) 하고, 샤드 수를 1개로 축소(Shrink) 하여 리소스 사용을 줄인다.
  3. Cold 단계: 30일이 지나면 Cold로 이동한다. 인덱스 우선순위를 낮추어 복구 시 후순위로 처리한다.
  4. Delete 단계: 90일이 지나면 인덱스를 삭제한다.

정책 적용

생성한 ILM 정책은 인덱스 템플릿(Index Template) 에 연결하여 새로 생성되는 인덱스에 자동 적용할 수 있다.

PUT /_index_template/log-template
{
  "index_patterns": ["logs-*"],
  "template": {
    "settings": {
      "index.lifecycle.name": "log-policy",
      "index.lifecycle.rollover_alias": "logs"
    }
  }
}

ILM 정책의 현재 상태는 다음 API로 확인한다.

GET /logs-*/_ilm/explain

주요 ILM 액션 정리

액션설명사용 가능 단계
Rollover조건 충족 시 새 인덱스 생성Hot
Force Merge세그먼트 수를 줄여 검색 성능 개선Hot(롤오버 후), Warm
Shrink프라이머리 샤드 수 축소Warm
Allocate레플리카 수 변경, 특정 노드로 이동Warm, Cold
Searchable Snapshot스냅샷 기반 검색 가능한 인덱스Cold, Frozen
Delete인덱스 영구 삭제Delete

Force Merge를 Hot 단계에서 사용하려면 반드시 Rollover 액션이 함께 설정되어 있어야 한다. 쓰기가 진행 중인 인덱스에 강제 병합을 실행하면 성능 문제가 발생할 수 있기 때문이다.


마이그레이션 전략

Elasticsearch의 메이저 버전 업그레이드나 클러스터 간 데이터 이전은 운영에서 피할 수 없는 작업이다. 상황에 따라 적절한 전략을 선택해야 한다.

롤링 업그레이드 (Rolling Upgrade)

롤링 업그레이드(Rolling Upgrade) 는 클러스터의 노드를 하나씩 순차적으로 업그레이드하는 방식이다. 서비스 중단 없이 업그레이드를 수행할 수 있어 프로덕션 환경에서 가장 선호된다.

기본 절차는 다음과 같다.

  1. 샤드 할당 비활성화: 노드를 종료하기 전에 불필요한 샤드 재배치를 방지한다.
PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": "primaries"
  }
}
  1. Synced Flush 실행 (7.x 이하): 샤드 복구 속도를 높이기 위해 실행한다. 8.x부터는 자동으로 처리된다.

  2. 노드 종료 후 업그레이드: 한 노드를 종료하고, 새 버전을 설치한 뒤 다시 시작한다.

  3. 샤드 할당 재활성화: 업그레이드된 노드가 클러스터에 합류하면 할당을 다시 켠다.

PUT /_cluster/settings
{
  "persistent": {
    "cluster.routing.allocation.enable": null
  }
}
  1. 클러스터 Green 확인 후 다음 노드로 진행: 모든 샤드가 정상 할당된 것을 확인한 뒤 다음 노드를 업그레이드한다.

롤링 업그레이드에는 제약이 있다. 업그레이드 중에 새 버전 노드의 프라이머리 샤드에 대한 레플리카가 구 버전 노드에 할당될 수 없다. 데이터 포맷이 달라질 수 있기 때문이다. 따라서 마이너 버전 간 업그레이드에서 주로 사용하며, 메이저 버전 점프(예: 7.x -> 8.x)에도 지원되지만 반드시 공식 호환성 매트릭스를 확인해야 한다.

Reindex API

Reindex API는 한 인덱스의 데이터를 다른 인덱스로 복사하는 기능이다. 클러스터 간 마이그레이션뿐 아니라 매핑 변경, 샤드 수 조정 등에도 활용된다.

POST /_reindex
{
  "source": {
    "index": "old-index"
  },
  "dest": {
    "index": "new-index"
  }
}

원격 클러스터에서 데이터를 가져오는 것도 가능하다.

POST /_reindex
{
  "source": {
    "remote": {
      "host": "http://old-cluster:9200",
      "username": "user",
      "password": "pass"
    },
    "index": "old-index"
  },
  "dest": {
    "index": "new-index"
  }
}

Reindex는 매핑(mapping)과 설정(settings)을 복사하지 않는다는 점에 주의해야 한다. 대상 인덱스의 매핑과 인덱스 템플릿은 미리 정의해 두어야 한다. 또한 대량의 데이터를 Reindex할 때는 slices 파라미터로 병렬 처리하면 속도를 크게 높일 수 있다.

POST /_reindex?slices=auto
{
  "source": { "index": "old-index" },
  "dest": { "index": "new-index" }
}

스냅샷과 복원 (Snapshot & Restore)

스냅샷(Snapshot) 은 클러스터의 데이터를 백업하는 가장 안정적이고 권장되는 방법이다. Elasticsearch 공식 문서에 따르면, 노드의 데이터 디렉터리를 파일 시스템 수준에서 복사하는 것은 지원되지 않는 백업 방법이다. 반드시 스냅샷 API를 사용해야 한다.

스냅샷 저장소를 등록하고 백업을 생성하는 과정은 다음과 같다.

# 1. 스냅샷 저장소 등록 (S3 예시)
PUT /_snapshot/my-backup
{
  "type": "s3",
  "settings": {
    "bucket": "my-es-backups",
    "region": "ap-northeast-2"
  }
}

# 2. 스냅샷 생성
PUT /_snapshot/my-backup/snapshot-2026-02-11?wait_for_completion=true
{
  "indices": "logs-*,metrics-*",
  "ignore_unavailable": true,
  "include_global_state": false
}

# 3. 스냅샷 상태 확인
GET /_snapshot/my-backup/snapshot-2026-02-11

복원 시에는 필요한 인덱스만 선택적으로 복원할 수 있다.

POST /_snapshot/my-backup/snapshot-2026-02-11/_restore
{
  "indices": "logs-2026.01.*",
  "rename_pattern": "logs-(.+)",
  "rename_replacement": "restored-logs-$1"
}

rename_patternrename_replacement를 사용하면 기존 인덱스와 이름이 충돌하지 않도록 복원할 수 있다.

마이그레이션 전략 선택 가이드

상황권장 전략
마이너 버전 업그레이드 (예: 8.12 -> 8.19)롤링 업그레이드
메이저 버전 업그레이드 (예: 7.x -> 8.x)롤링 업그레이드 + 호환성 확인
클러스터 간 데이터 이전스냅샷/복원 또는 원격 Reindex
매핑 구조 변경이 필요한 경우Reindex API
전체 클러스터 교체스냅샷 -> 새 클러스터에 복원

클러스터 모니터링

클러스터를 안정적으로 운영하려면 상태를 지속적으로 관찰해야 한다. Elasticsearch는 다양한 모니터링 API를 기본 제공한다.

_cat API

_cat API는 사람이 읽기 쉬운 형태로 클러스터 정보를 출력한다. CAT은 Compact and Aligned Text의 약자로, 터미널이나 Kibana 콘솔에서 빠르게 상태를 확인할 때 유용하다.

# 클러스터 건강 상태
GET /_cat/health?v

# 노드 목록과 리소스 사용량
GET /_cat/nodes?v&h=name,node.role,heap.percent,ram.percent,cpu,load_1m

# 인덱스 목록과 크기
GET /_cat/indices?v&h=index,health,status,pri,rep,docs.count,store.size&s=store.size:desc

# 미할당 샤드 확인
GET /_cat/shards?v&h=index,shard,prirep,state,unassigned.reason&s=state

_cat API는 사람이 확인하기 위한 용도이다. 애플리케이션에서 프로그래밍적으로 사용하려면 JSON을 반환하는 _cluster, _nodes API를 사용해야 한다.

주요 모니터링 지표

안정적인 클러스터 운영을 위해 다음 지표를 주기적으로 확인해야 한다.

클러스터 수준

  • 클러스터 상태 (Green/Yellow/Red)
  • 미할당 샤드 수
  • 활성 노드 수

노드 수준

  • JVM 힙 메모리 사용률 (75% 이하 권장)
  • CPU 사용률
  • 디스크 사용률 (워터마크 기준 관리)
  • GC(Garbage Collection) 빈도와 소요 시간

인덱스 수준

  • 인덱싱 속도 (docs/sec)
  • 검색 지연시간 (latency)
  • 세그먼트 수와 머지 활동
# 노드별 상세 통계
GET /_nodes/stats

# 특정 인덱스의 통계
GET /my-index/_stats

Kibana의 Stack Monitoring 기능을 사용하면 이러한 지표들을 시각화된 대시보드로 확인할 수 있다. 자체 모니터링 클러스터를 별도로 두어 메트릭을 수집하는 것이 프로덕션 권장 사항이다.


정리

Elasticsearch 클러스터 운영의 핵심은 다음과 같다.

  • 노드 역할 분리: Master, Data, Coordinating, Ingest 등 역할을 목적에 맞게 분리하여 안정성과 성능을 확보한다.
  • 클러스터 상태 관리: Green/Yellow/Red 상태를 이해하고, 샤드 할당 전략과 디스크 워터마크로 클러스터 건강을 유지한다.
  • ILM으로 데이터 생명주기 자동화: Hot-Warm-Cold-Delete 아키텍처를 통해 시계열 데이터의 비용과 성능을 자동으로 최적화한다.
  • 상황에 맞는 마이그레이션 전략: 롤링 업그레이드, Reindex, 스냅샷/복원을 상황에 따라 적절히 선택한다.
  • 지속적인 모니터링: _cat API와 노드 통계를 활용하여 문제를 조기에 감지하고 대응한다.