Post

Elasticsearch 핵심 요소: 클러스터, 샤드, 시스템 설정

클러스터 규모별 구성 방식, 스냅샷 백업/복원, 샤드 분배와 모니터링, 클러스터/노드/인덱스 설정값 관리

Elasticsearch 핵심 요소: 클러스터, 샤드, 시스템 설정

1. 클러스터 구성

1-1. 소규모 클러스터 구성 예시

  • 마스터 후보 노드는 홀수로 지정해야 한다
  • 데이터 노드는 많은 컴퓨터 리소스를 필요로 하기 때문에 가능한 많을수록 좋다


1-2. 대규모 클러스터 구성 예시

  • 마스터 후보 노드들은 하드웨어 성능은 비교적 중요하지 않지만 최소 3대를 준비하고 가능한 한 클라이언트의 요청을 받지 않도록 구성한다
  • 데이터 전용 노드는 온전히 데이터 작업만 진행하고 클러스터에서 가장 많이 배치해야 한다
  • 데이터 전용 노드는 가능하면 고사양의 하드웨어를 구성하고 사양은 통일하는 것이 좋다
    • 분산 처리 시 복수의 노드에서 발생한 결과를 코디네이터 노드에서 취합해야 하는데 데이터 노드 하나의 응답이 느리면 전체 응답 속도에 영향을 미치기 떄문이다
  • 데이터 읽기가 많은 시스템인지 데이터 쓰기가 많은 시스템인지 데이터가 얼마나 많이 필요한지에 따라 노드들을 다양하게 구성할 수 있다
  • 다만 대규모 클러스터를 구성할 때 마스터 후보 전용 노드와 데이터 전용 노드를 나고, 마스터 노드는 클라이언트의 요청이나 데이터 작업에 참여하지 않고 클러스터 관리에 집중시키는 것이 좋다


1-3. 핫/웜/콜드 노드 구성

  • 핫 노드
    • 활발하게 인덱싱과 검색이 일어나는 인덱스를 위치 시키고 충분한 리소스의 하드웨어 할당
  • 웜 노드
    • 자주 사용하지 않는 데이터를 저장
    • 쿼리의 빈도가 낮고 인덱싱은 일어나지 않는 인덱스
    • 핫노드에 비해 성능 좋은 디스크나 큰 메모리는 필요 없지만 많은 데이터를 저장하기 위해 대용량 디스크를 사용
  • 콜드 노드
    • 프리즈 모드의 인덱스를 저장
    • 프리즈 모드의 인덱스는 평상시에는 메모리에 띄워놓지 않으므로 인덱스를 유지하기 위한 메모리 공간이 필요하지는 않음
    • 검색 요청이 올 때 인덱스 파일을 오픈하기 때문에 검색 시간이 많이 소요
    • 하드웨어는 시스템 내에서 지원하는 최소한의 사양으로 구성하되 디스크의 용량만 필요한 만큼 갖추면 되고, 가용성을 위한 시스템 구성은 필요 없다



2. 클러스터 백업

  • repository를 지정하고 snapshot을 찍고 복원할 수 있다
  • snapshot은 클러스터 전체를 찍거나 특정 인덱스만 찍을 수 있다


2-1. repository 등록

  • repository 등록 API
    1
    2
    3
    4
    5
    6
    7
    
    PUT _snapshot/fsrepo
    {
      "type" : "fs",
      "settings" : {
        "location" : "C:\\elasticsearch-7.10.1"
      }
    }
    
    • 지원하는 타입
      • fs, hdfs, s3, azure, gcs
    • repository는 클러스터를 구성하는 마스터 노드와 데이터 노드가 동일한 위치를 공유해야 한다


2-2. snapshot 찍기

  • snapshot을 찍을 때는 기존 데이터 대비 변경사항만 추가 반영되는 구조이기 때문에 가능하면 자주 찍는 방식을 권장
  • snapshot 찍기 요청
    1
    
    PUT _snapshot/fsrepo/snapshot1
    
    • fsrepo는 레퍼지토리 이름, snapshot1은 스냅샷 이름
    • "accepted" : true 결과를 받으면 성공한 것
  • 특정 인덱스의 snapshot 찍기 요청
    1
    2
    3
    4
    5
    
    PUT _snapshot/fsrepo/snapshot2
    {
      "indices" : "kibana_sample_data_*",
      "ignore_unavailable" : true
    }
    
    • indices 필드는 스냅샷을 찍을 인덱스들이다. 배열 형태로 여러 인덱스를 선택할 수 있고 와일드카드 형식으로 인덱스 패턴을 지정해 여러 인덱스를 선택할 수도 있다
    • 인덱스를 지정하지 않으면 클러스터 내의 모든 인덱스의 스냅샷을 찍는다
    • "ignore_unavailable" : true 옵션을 true로 지정하면 비활성화 상태의 인덱스는 스냅샷에 기록되지 않는다


2-3. snapshot 복원

  • 모든 인덱스 복원 요청
    1
    
    PUT _snapshot/fsrepo/snapshot1/_restore
    
    • 예를 들어, 현재 클러스터에 index1 인덱스가 있는데 레퍼지토리에 index1 인덱스가 있다면 복원이 되지 않는다. 이름이 겹치는 인덱스를 지우고 복원을 하던지 아니면 인덱스 이름을 변경해야 한다.
  • 특정 인덱스만 복원
    1
    2
    3
    4
    5
    6
    7
    
    PUT _snapshot/fsrepo/snapshot1/_restore
    {
      "indices" : "kibana_sample_daata_*",
      "ignore_unavaliable" : true,
      "rename_pattern" : "kibana_sample_data_(.+)",
      "rename_replacement" : "restored-kibana_sample_data_$1"
    }
    
    • rename_pattern은 변경하려는 인덱스 이름, rename_replacement는 변경되는 인덱스 이름



3. 샤드

  • 엘라시틱서치는 여러 대의 노드를 효율적으로 활용하기 위해 데이터를 샤드 단위로 나눠 분산 저장한다
  • 실제로 인덱스는 가상의 논리적 단위이며 실제 도큐먼트의 인덱싱과 검색은 샤드에서 일어난다
  • 샤드 구성과 인덱싱 과정
    • 인덱스를 만들 때 샤드 개수를 정한다
    • n개의 샤드는 노드에 적절히 분배된다
    • 도큐먼트가 인덱싱되면 도큐먼트는 n개의 샤드 중 하나의 샤드 내의 세그먼트로 저장된다
    • 코디네이터 노드(최초 요청을 수신한 노드)는 문서에 별도의 ID가 주어지지 않는다면 랜덤 ID를 생성하며, _routing 파라미터가 명시되지 않았다면 ID를 이용해 도큐먼트가 인덱싱될 샤드를 결정한다
  • 샤드와 세그먼트 구조
    • 샤드는 하나의 루씬 인스턴스이며 여러 개의 세그먼트를 포함하고 있다
    • 세그먼트는 엘라스틱서치에서 인덱스가 물리적으로 저장되는 가장 작은 단위로 읽기에 최적화된 형태이며 수정은 불가능하다
    • 세그먼트는 자체적으로 루씬 검색이 가능한 구조이며 토큰화된 역인덱스 데이터와 소스 데이터가 들어 있다
    • 루씬에서 인덱스 검색을 요청하면 각각의 세그먼트들로부터 검색하고 이를 통합해 최종 결과가 나온다
    • 세그먼트는 리프레시될 때마다 생기는데 리프레시는 클러스터의 모든 샤드에서 기본적으로 1초마다 발생하며 리프레시가 되어야 새로 추가된 도큐먼트 검색이 가능하다
    • 너무 작은 세그먼트들이 만들어지면 읽기 성능이 저하되므로 이를 방지하기 위해 내부적으로 틈틈이 세그먼트들을 병합한다


3-1. 프라이머리 샤드와 레플리카 샤드

  • 인덱스 설정에서 프라이머리 샤드와 레플리카 샤드 개수를 지정할 수 있다
    1
    2
    3
    4
    5
    6
    
    PUT index
    {
      "settings" : {
        "number_of_shards" : 3,
        "number_of_replicas" : 2
    }
    
    • number_of_shards는 프라이머리 샤드 개수, number_of_replicas는 레플리카 샤드 개수
    • 레플리카 샤드는 프라이머리 샤드 개수를 한 단위로 두 벌을 추가한다
      • 위 경우 프라이머리 샤드가 3개이고, 이 3개의 샤드가 각각 두 벌씩 복제되어 6개의 레플리카 새드가 만들어진다
  • 샤드가 균형 있게 분산되어 있으면 좋은 샤드를 취사선택해 리소스 활용량을 최적화 할 수 있다.


3-2. 샤드 할당 과정

  • UNASSIGNED(미할당)
    • 샤드는 있지만 아직 노드에 할당되지 않은 상태
  • INITIALIZING(초기화)
    • STARTED 전 초기화를 위한 상태
    • 노드에 샤드가 추가된 상태이지만 아직 메모리에 온전하게 적재된 것은 아니라서 샤드를 사용할 수는 없다
    • 마스터 노드는 데이터 노드들 중에서 샤드를 생성할 수 있는 노드를 찾고 할당이 가능한 노드부터 프라이머리 샤드를 적재하기 시작한다
  • STARTED(동작)
    • 샤드가 메모리에 올라간 상태로 이 상태에서만 접근이 가능
    • 프라이머리 새드가 STARTED 상태가 되면 레플리카 샤드가 할당된다
  • RELOCATING(재할당)
    • 샤드가 재배치되는 단계
    • 분산 환경 시스템에서 노드들은 고장이나 네트워크 문제로 노드가 추가되거나 삭제되는데, 노드가 변경될 때마다 샤드 역시 재배치가 필요하다
    • 노드 수가 변하지 않더라도 저장공간이나 샤드 수 등을 기준으로 주기적인 리밸런싱이 일어날 때도 재배치 작업이 필요하다

3-3. 샤드 상태 모니터링

  • 샤드 상태 확인
    1
    
    GET _cat/shards?v
    
  • 인덱스 상태 구분
    • red
      • 하나 이상의 프라이머리 시드가 클러스터에 정상적으로 적재되지 않았다. 데이터 읽기/쓰기가 정상적으로 동작하지 않는다
    • yellow
      • 프라이머리 샤드는 모두 적재되었지만 하나 이상의 래플리카 샤드가 정상적으로 적재되지 않았다. 인덱스를 읽고 쓰는 것은 문제없지만 레플리카 샤드가 없으면 장애 발생 시 해당 인덱스에 대한 서비스가 불가능할 수 있다
    • green
      • 프라이머리 새드와 레플리카 샤드가 모두 정상적으로 적재되었다



4. 샤드 개수와 구성

  • 샤드가 늘어나면 더 많은 스레드를 활용해 인덱스를 병렬 검색
  • 샤드가 적으면 요청을 분배하고 취합하기 위한 비용이 줄어든다

4-1. 샤드 개수

  • 인덱스를 생성할 때 따로 설정을 하지 않을 경우 기본값으로 샤드가 생성된다
  • 오버 샤딩은 샤드를 잘게 나누어 필요 이상의 많은 리소스를 사용하게 하는 문제다
    • 샤드는 개별적으로 리소스를 소비한다. CPU나 메모리는 물론이고 루씬 인스턴스의 리소스도 필요하다
    • 인덱스를 검색하기 위해서는 인덱스가 저장된 모든 샤드에 접근해야 한다
  • 기본적으로 오버샤딩은 피하고 분산/병렬이 잘되는 샤드 개수를 찾아야 한다
    • 공식적으로 권장하는 방법은 실 데이터를 가지고 샤드 수를 조정하며 벤치마크 하는 것
    • 클러스터에서 제공하는 CPU 코어 개수에 따라 샤드 개수를 결정하기도 하지만, 적절한 샤드 수는 프로젝트 성격이나 시스템 구성에 따라 바뀐다

4-2. 샤드 크기

  • 샤드가 너무 크면 성능 문제가 발생하고 샤드가 너무 작으면 담을 수 있는 도큐먼트가 작아진다
  • 검색이 많은 시스템인지 저장이 중요한 시스템인지에 따라 샤드 크기는 변경될 수 있고 노드의 리소스 상태도 영향을 미친다
  • 엘라스틱에서는 통계적으로 볼 때 샤드 하나의 크기가 10GB~40GB 정도로 관리하는 것이 좋다고 권고한다
  • rollover API
    • rollover API는 인덱스가 특정 조건에 도달했을 때 새로운 인덱스를 생성하는 API
    • 요청이 있을 경우만 발생하기 때문에 요청 전까지는 샤드 크기가 아무리 커져도 새로운 인덱스가 생성되지 않는다. 시스템이 자동으로 조건을 체크하고 조건에 맞는 경우 새로운 인덱스를 생성하는 기능은 ILM이 제공하낟.
  • shrink API
    • shrink API는 기존 인덱스의 프라이머리 샤드 개수를 줄이는 데 사용한다
    • 처음 인덱스를 생성할 때 프라이머리 샤드를 너무 많이 만들었다면 shrink API로 샤드를 병합해 샤드 수를 줄일 수 있다
    • 자주 사용하지 않아 핫 노드에서 웜 노드로 이동하는 인덱스에서도 사용 가능
    • 자주 사용하지 않는 기존 인덱스를 롤오버하며 shrink API로 샤드 개수를 줄이기도 한다



5. 설정

운영이나 개발 과정에서 발생하는 시스템의 크고 작은 설정값들을 변수화하여 상황에 맞게 사용

설정설명
클러스터 설정로그 레벨이나 클러스터 전반에 관한 설정을 한다. REST API를 이용해 동적으로 설정값을 변경할 수 있다.
노드 설정네트워크 인터페이스, 보안 설정 등 같은 노드 구성에 관한 설정을 한다. elasticsearch.yml 파일에서 정적으로 수정한다.
인덱스 설정인덱스와 관련된 설정을 할 수 있다. 프라이머리 샤드나 레플리카 개수 설정 등을 할 수 있으며 정적/동적으로 설정이 가능하다. 제공하는 REST API를 이용해 동적으로 인덱스별 설정값을 변경할 수 있다.


5-1. 클러스터 설정

  • 클러스터 설정 확인 요청
    1
    2
    
    GET _cluster/settings
    GET _cluster/settings?include_defaults=true
    
  • 클러스터 설정
    • logger.*
    • cluster.routing.allocation.*
    • cluster.blocks.read_only


5-2. 노드 설정

  • 노드 설정 확인 요청
    1
    
    GET _nodes/settings
    
  • 노드 설정
    • node.roles
    • path.data


5-3. 인덱스 설정

  • 인덱스 설정 확인 요청
    1
    
    GET index/settings
    
  • 인덱스 설정
    • index.number_of_shards
    • index.number_of_replica
    • index.refresh_interval
    • index.blocks.read_only
This post is licensed under CC BY 4.0 by the author.