Archive

[Elasticsearch] 엘라스틱서치 클러스터 구성 ( Node / Shard / Segment) 본문

------- DE -------/ELK

[Elasticsearch] 엘라스틱서치 클러스터 구성 ( Node / Shard / Segment)

enent 2022. 6. 15. 09:51
반응형

1. 노드 ( Node ) 

  • 클러스터를 구성하는 하나의 Instance이다
  • 데이터를 저장하고 클러스터의 Indexing과 Searching 역할을 한다. 
  • 물리서버 하나에 노드 하나를 구성하는 것을 권장하지만, 단일 서버에 복수 노드를 설치하는 것도 가능하다
  • HW Spec을 고려하여 노드를 구성해야한다

 

1.1 Master Node

  • 클러스터는 반드시 한개의 마스터 노드를 가진다
  • Cluster의 모든 상태 정보 관리 및 상태 모니터링
  • Master Eligible Node에 의해 선출된다 (사용자 지정 X)
    - 선출 방식은 과반 수 이상의 투표를 얻어야 한다
    - Voting only Node를 통해 Master Eligible Node가 특정 이유에 의해 대량으로 장애가 발생했을 때 Availability 확보

 

1.2 Data Node

  • Indexing한 Document를 Shard형태로 저장하여 데이터의 CRUD작업과 검색/집계 작업을 한다
    = 실질적 Data Processing이 일어나는 노드
  • 리소스 사용량에 민감하여 모니터링 하면서 부하 상태를 체크해야 한다
    - 상황에 따라 Shard 재 분배/ Datanode 추가/변경 작업을 진행

 

1.3 Ingest Node

  • Document 가공/정제를 위한 Ingest Pipeline이 실행되는 노드
  • Pipeline을 통해 Indexing전에 원하는 형태로 변형
  • 구성요소 - Process, Pipeline

 

1) Pipeline : Process의 집합

PUT _ingest/pipeline/mypipe
{
  "description" : "description",
  "processors" : [
    {
      "set" : { 
        "field" : "status",
        "value" : "low",
        
        "on_failure" : [
          {
          "set" : {
            "field" : "error",
            "value" : "set processor error"
            }
          }
        ]
      }
    }
  ],
  "on_failure": [
    {
      "set" : {
        "field" : "error",
        "value" : "pipeline1 error"
      }
    }
  ]
}

- description: pipeline에 대한 설명

- processors : 여러 개의 processor 들을 리스트 형태로 작성하고 적힌 순서대로 실행

- on_failure : pipeline/processor processing에 실패했을 때 예외 처리 방법

  ▶ 작성 위치에 따라 어떤 부분의 예외를 처리할 건지 결정된다.

 

 

ex1) pipeline을 적용하여 document 저장 요청

PUT my_index/_doc/1?pipeline=mypipe
{
  "name" : "id1",
  "status" : "high"
}

 

ex2) 기존 Index를 pipeline을 이용하여 수정

PUT my_index2/_doc/1
{
  "name" : "id1",
  "status" : "high"
}

 

ex3-1) pipeline을 적용하여 document 수정 (by update_by_query API)

POST my_index2/_update_by_query?pipeline=mypipe

- 수정해야 하는 document가 많을 때 성능 상 유리하다.

 

ex3-2) pipeline을 적용하여 document 수정 (by reindex API)

POST _reindex
{
  "source" : {
    "index" : "my_index2"
  },
  "dest" : {
    "index" : "my_index3",
    "pipeline" : "mypipe"
  }
}

 

ex4) Index 설정 pipeline 적용

PUT my_index4
{
  "settings"  : {
    "default_pipeline" : "mypipe"
  }
}

 

 

2) Processor 

  • Pipeline을 구성하는 컴포넌트
  • Document를 변형할 수 있는 기능적으로 구분되는 모듈
  • date, drop, grok, set, split 등 존재

 

1.4 ETC

  • Machine Learning Node : ML 기능 활용할 수 있는 노드. 유료라이센스에 포함되어 있음
  • Coordinator Node : REST API 요청 처리 (HTTP)
    - 처리해야 할 요청이 많거나 규모가 크고 복잡한 검색, 무거운 집계시 리소스 많이 필요 -> 이 경우 코디네이터 노드를 따로 두어 부하 감소 및 검색 효율을 높힐 수 있음
  • Dedicated Node : 노드별로 하나의 역할을 수행하게끔 설정
    - master, master+voting_only, data, ingest, ml 등 설정 가능

역할 별 H/W 구성

  • Master : 클러스터 상태 관리가 주 역할로 하드웨어 성능이 크게 중요하지 않다.
  • Data : Client 요청 처리를 위한 빈번한 I/O 작업과 연산작업이 필요하기 때문에 고사양의 H/W 구성 필요. 가능하면 전용노드 구성
  • Ingest : 데이터 수집이 목적으로 연산량을 위한 고사양의 CPU
  • Coordinator : API 요청 부하 분산. 역할. 무거운 집계 요청이 잦을 땐 CPU 를 많이 할당하는 것을 추천

 


2. 샤드(Shard) 

  • Document를 저장하는 기본 단위 
    - ES는 Index를 Shard단위로 나누어 노드들에 분산 저장하여 Cluster내 Computing Resource를 최대한 활용할 수 있도록 한다
    - Index는 가상의 논리적 단위이며, 실제 Document의 Indexing, Searching은 Shard에서 일어남
  • Index를 생성할 때 생성할 Shard의 개수를 정할 수 있다
    - Routing : 여러 개의 Shard중 어떤 Shard에 저장할 지 결정하는 것 
  • Shard의 개수가 전체 ES Cluster 성능에 영향을 미치므로 구성에 유의해야 한다

 

2.1 Primary Shard / Replica Shard 

ES는 Index를 Shard단위로 나누어 노드들에 분산 저장하는데, 이 때 노드 하나에 장애가 생긴다면 데이터도 같이 손실되어 데이터 정합성 이슈가 생길 수 있다. 이를 방지하기 위해 Primary / Replica 샤드를 분리하여 관리한다.

  • Primary Shard 
    - 데이터의 원본 저장
    - number_of_shards 를 통해 설정하며 default 는 1
  • Replica Shard
    - 데이터의 복제본 저장 
    - number_of_replicas를 통해 설정하며 default 는 1

Replica Shard의 필요성

  • High Availability
  • 처리 속도 향상 
    - 응답성이 빠른 노드에서 데이터를 가져옴으로서 빠른 검색 수행 및 부하 상태에 놓인 노드에 추가적인 부하를 방지하여 전체 처리 성능의 안정성에도 기여

 

 

2.2 세그먼트 (Segment)

  • ES에서 Index가 물리적으로 저장되는 가장 작은 단위이자 Lucene 검색이 가능한 최소 단위
    - Shard 내부적으로는 Segment 형태로 저장됨
    - Tokenize된 역인덱스 데이터와 소스 데이터가 들어있다
  • 읽기 최적화 형태로 구성되어 있음 (수정 불가) 
    - 너무 많은 Segment들이 생성되면 읽기 성능이 저하되므로, 이를 방지하기 위해 내부적으로는 틈틈히 Segment들을 병합하는 과정을 거친다

Lucene에서 Index 검색을 요청하면 각각의 Segment들로부터 검색하고, 이를 통합하여 최종 결과가 나온다.

 

 

2.3 Shard 할당 과정  

1) Unassigned

: Shard는 생성되었으나 아직 Node에 할당되지 않은 상태

 

2) Iniitializing

: Node에 Shard를 로딩중인 상태
  - Segment들을 Memory에 띄우는 과정

 

Master Node는 Data Node들 중 Shard를 생성할 수 있는 Node를 찾고, 할당이 가능한 Node부터 Primary Shard를 적재하기 시작한다

 

3) Started

: Shard가 Memory에 올라간 상태

 

Primary Shard가 Started 상태가 되면 Replica Shard가 할당된다. Replica Shard도 Initializing을 거쳐 Started가 된다. 

 

4) Relocating

: Shard가 재배치 되는 단계

 

Node가 변경(추가/삭제 등) 될 때 혹은 주기적인 Re-Balancing이 있을때 마다 Shard는 재배치 된다. 

 

 

 

2.4 Shard 모니터링

cat API 활용하여 모니터링 할 수 있다

1) shard 상태 확인

: Shard 종류 (p/r), Shard 상태(STARTED, UNASSIGNED 등) 확인 가능

GET _cat/shards?v

 

2) Index 상태 확인

: Shard의 이상유무 확인 가능 (health Col - red / yellow / green ) 

GET _cat/shards?v
  • red : 하나 이상의 Primary Shard가 정상적으로 적재되지 않음. 데이터 Read/Write가 정상적으로 동작 X
  • yellow : 하나 이상의 Replica Shard가 정상적으로 적재되지 않음. Primary Shard는 적재된 상태이기 때문에 Read/Write는 문제 없으나 장애 발생시 서비스가 불가할 수 있음
  • green : Primary Shard, Replica Shard 정상적으로 적재됨

 

 

 

2.5 Shard 개수 및 크기 설정

1) 개수 설정

Shard 개수가 늘어나면 더 많은 스레드를 활용하여 Index를 병렬 검색할 수 있고, 줄어들면 그만큼 요청을 분배하고 합치는 비용이 줄어든다. 따라서 적절한 Shard 개수 설정은 중요하다.

또한, Oversharding을 조심해야 한다. 필요이상으로 잘게 Shard를 나누면 Shard 개별적으로 많은 리소스를 사용할 뿐만 아니라 Index검색하는데에도 많은 리소스가 필요된다. 

권장하는 개수는 따로 없으며, 각자의 클러스터에 저장된 실 데이터를 가지고 Shard수를 조정해가며 벤치마크를 하는 것이다

 

 

2) 크기 설정

Shard 크기 역시도 너무 컼지면 성능 문제가 생기고, 너무 작으면 한 번에 담을 수 있는 Document가 작아진다.

때문에 이 역시도 테스트 해보며 알맞은 Shard의 크기를 찾아야하는데, 통계적으로 Shard 하나의 크기가 10GB ~ 40GB 정도로 관리하는게 좋다고 권고한다.

 

보통 특정 시간을 기준으로 Index를 분리하거나, Document 개수나 Index 크기를 기준으로 분리하기도 한다.

 

Shard 크기를 관리하는 API에는 두가지가 있다. 모두 Kibana의 ILM 에서 동작의 원리로 사용된다. (ILM에선 자동으로 조건에 따라 내부적으로 두 개의 API 원리들을 사용함)

  • rollover API
    - Index가 특정 조건에 도달하면 새로운 Index를 생성 -> 예측 불가한 상황에서도 Index의 크기를 일정하게 유지할 수 있음
    - 생성 후에는, 새로 생성된 Index가 쓰기를 담당하게 되고, 읽기는 새로 생성된 Index 포함 같은 Rollover-alias를 가지고 있는 모든 Index에서 이루어진다
POST rollover-alias/_rollover
{
  "conditions" : 
    "max_age" : "30d",
    "max_docs" : 1, 
    "max_size" : "50gb"
  }
}

  - max_age : Index 생성 후 경과된 시간
  - max_docs : Index 내 Document 최대 개수
  - max_size : Index 최대 크기

 

  • shrink API
    - 기존 Index의 Primary Shard를 병합하여 Shard의 개수를 줄이는 데 사용된다
    - Index 내 모든 Shard를 한 Node에 옮기고, ( 이 때 Replica Shard 임시로 비활성화. 어짜피 옮기면 새로 Replica 생성할 것 ) Index를 읽기전용 모드로 만든 후 Shard 재할당이 끝나면 Shard 수축을 진행한다.

 

POST shrink-1/_shrink/shrink-1-target
{
  "settings" : {
    "index.number_of_shards" : 1,
    "index.number_of_replicas" : 1,
    "index.routing.allocation.require._name" : null,
    "index.blocks.write" : null,
    "codec" : "best_compression"
  }
}

 

  - index.routing.allocation.require._name" : Index를 name 조건에 맞는 샤드에서만 접근하게 함. 

  - index.blocks.write" : true로 설정시 Index를 읽기 전용 모드로 설정할 수 있음

  

 

 

 

3. 노드 및 시스템 구성

시스템이 커질 수록 전용 노드를 통해 구성하고 HA 및 그에 맞는 하드웨어와 운영 방식이 필요하다.

  • HA 구성을 위해 Master Node는 3개 이상의 홀수 개로 지정한다.
  • Data Node는 많으면 많을수록 좋다.

 

3.1 대규모 클러스터 구성

클러스터 내 서버 대수가 5대 안팎의 클러스터면, 각 노드의 역할 구분이 완벽히 분리되어 있지 않아도 괜찮다. 하지만 대규모로 갈수록 전용 노드를 잘 활용하는 것이 중요하며, 특히 Master Node와 Data Node는 꼭 분리하여 구성해야 한다.

 

  • Master Node : HA 구성을 위해 최소 3대로 구성
  • Data Node : 온전히 데이터 작업만 진행. 노드가 많으면 많을수록 좋다. 
    - 가능한 고사양 HW 및 HW Spec을 통일하는 것이 좋다 
  • Ingest Node : 파이프라인을 이용한 데이터 정제작업에 집중
  • Coordinator Node : 검색이나 집계 작업 담당 (서비스 성격에 따라 필요유무 결정)

 

3.2 Hot / Warm / Cold Node  구성

클러스터 효율을 높이기 위한 구성

 

  • Hot Node
    - 활발하게 인덱싱과 검색이 일어나는 Index
    - 충분한 H/W 리소스 할당
  • Warm Node
    - 자주 사용하지 않는 데이터. Query 빈도가 낮고 인덱싱이 잘 일어나지 않는 Index
    - CPU/Mem 성능은 중요치 않으나 대용량 디스크 사용
  • Cold Node
    - Freeze 상태의 Index. 검색을 수해앟진 않으나 데이터 보존기간 정책상 보관해야만 하는 데이터
    -  CPU/Mem 성능은 중요치 않으나 필요한 만큼의 디스크 사용. HA 구성 필요 X
         

1) Shard Allocation Filtering

샤드를 조건에 따라 특정 노드에 저장하는 방법

 

(1) Index 생성시 설정하는 방법

각 노드들에 Hot/ Warm 등의 속성 태그 ( node.attr.node_tag) 를 통해 속성을 부여해준다.

  • elasticsearch.yml 에 nodeattr.node_tag : hot / warm 
    - 사용자가 원하는 태그명으로 부여 가능

② Index에 생성한 속성태그를 부여한다 

- Index에 태그를 부여하면 자동으로 Index의 모든 Document, 즉 해당하는 Shard가 특정 Node로 Indexing 된다.

  = Attribute와 Tag값이 일치하는 특정 노드에만 저장됨

PUT sample_data
{
  ...
  "settings" : {
    "index.routing.allocation.require.node_tag" : "hot"
  }
}

 

(2) 사용 중 Hot Node -> Warm Node로 Index 동적 이동

  • settings API 사용
PUT sample_data/_settings
{
  "index.routing.allocation.require.node_tag" : "warm"
}

 

  • Kibana Web UI 활용
    : Management -> Stack Management -> Index Lifecycle Policies에서 수명주기 정책 생성 및 세부내용 확인 가능

 

 

 

4. 클러스터 백업

데이터 백업을 위해 Snapshot을 뜰 수 있고, 해당 Snapshot을  Repository에 저장할 수 있다.

 

1) Repository 등록

Repository Type을 선택할 수 있다 ( fs, hdfs, s3, azure, gcs 등)

 

ex) Filesystem repository 예시

PUT _snapshot/fsrepo
{
  "type" : "fs",
  "settings" : {
    "location" : "/etc/elasticsearch"
  }
}

 

2) Snapshot 생성

특정 시각의 모든 데이터를 복사하여 데이터를 저장하며,  클러스터 전체 / 특정 인덱스만 저장할 수도 있다.

Snapshot생성은 기존 데이터 대비 변경사항만 추가 반영되는 구조이기 때문에 가능하면 자주 스냅샷을 찍어주는 것을 권장한다.

실제 운영에서는 Kibana내 SLM(Snapshot Lifecycle Managemet)가 스냅샷 빈도와 관리를 자동화해줄 수 있어, 관리 운영의 효율성을 높일 수 있다.

 

ex1) 클러스터 전체 Snapshot 

- fsrepo repository 에 저장되며, 특별히 인덱스를 지정하지 않으면 클러스터 내의 모든 인덱스의 스냅샷을 찍음

PUT _snapshot/fsrepo/snapshot1

 

ex2) 특정 Index Snapshot

PUT _snapshot/fsrepo/snapshot2
{
  "indices" : "kibana_sample_data_*",
  "ignore_unavilable":true
 }

- ignore_unavailable : 활성화되지 않은 Index의 Snapshot은 찍지 않음

 

 

3) Snapshot 복원

restore API를 통해 모든 인덱스를 가져올 수도 있고, 특정 인덱스만 가져올 수 있다.

 

-모든 인덱스 복원 요청

POST _snapshot/fsrepo/snapshot1/_restore

 

-특정 인덱스 복원요청

POST _snapshot/fsrepo/snapshot1/_restore
{
  "indices" : "kibana_sample_data_*",
  "ignore_unavailable" : true,
  "rename_pattern": : "kibana_Sample_data_(.+)",
  "rename_replacement" : "restored-kibana_sample_data_$1"
}

 

 

 

 

Reference
Elastic Stack 개발부터 운영까지 - 13. 클러스터와 노드 구성
반응형
Comments