개발환경 또는 테스트를 진행하기 위해서는 엘라스틱서치의 단일 노드로도 충분하다.  그래서 엘라스틱서치 노드는 기본적으로 싱글 노드에서 모든 역할을 수행할 수 있게 설정하는 것이 가능하다. 하지만 실제 운영환경에서는 대부분 다수의 노드를 클러스터링하여 구성하기 때문에 각각 목적에 맞는 노드를 적절히 설정해 운영하는 것이 유리하다.

 

엘라스틱서치 노드의 종류

elasticsearch.yml 파일에는 노드 관련 속성이 제공된다. 이 속성들을 적절히 조합해서 특정 모드로 설정하는 것이 가능하다.

 

  • node.master : 마스터 기능 활성화 여부
  • node.data : 데이터 기능 활성화 여부
  • node.ingest : Ingest 기능 활성화 여부
  • search.remote.connect : 외부 클러스터 접속 가능 여부

위의 설정들을 조합하여 아래와 같은 노드 모드로 운영가능하다.

 

  • Single Node mode
  • Master Node mode
  • Data Node mode
  • Ingest Node mode
  • Coordination Node mode

 

Single Node mode

모든 기능을 수행하는 모드다. 기본 설정으로 지정돼 있기 때문에 elasticsearch.yml 파일에 아무런 설정을 하지 않는다면 기본적으로 싱글모드로 동작한다.

 

node.master: true / node.data: true / node.ingest: true / search.remote.connect: true

 

검색 클러스터의 규모가 작을 때는 노드별로 별도의 Role을 분담하여 운영하기 보다는 모든 노드가 싱글 모드로 수행하게 하는 것이 좋다. 일반적으로 3대 이하의 소규모 클러스터를 구축한다면 모든 엘라스틱서치 노드를 싱글모드로 동작시키는 것이 좋다.

 

 

Master Node mode

클러스터의 제어를 담당하는 모드이다. 

 

node.master: true / node.data: false / node.ingest: false / search.remote.connect: false

 

마스터 모드는 기본적으로 인덱스 생성/변경/삭제 등의 역할을 담당한다. 그리고 분산코디네이터 역할을 담당하여 클러스터를 구성하는 노드의 상태를 주기적으로 점검하여 장애를 대비한다. 즉, 마스터 모드는 클러스터 전체를 관장하는 마스터 역할을 수행하게 된다. 이처럼 중요한 역할을 하는 마스터 노드는 클러스터에 다수 존재하는 것이 좋다. 그래야 장애가 발생할 경우에도 후보 마스터 노드가 역할을 위임받아 안정적으로 클러스터 운영 유지가 되기 때문이다.

 

 

Data Node mode

클러스터의 데이터를 보관하고 데이터의 CRUD, 검색, 집계 등 데이터 관련 작업을 담당하는 모드이다.

 

node.master: false / node.data: true / node.ingest: false / search.remote.connect: false

 

노드가 데이터 모드로 동작하면 내부에 색인된 데이터가 저장된다. 이말은 즉, 마스터 노드와는 달리 대용량의 저장소를 필수적으로 갖춰야한다.(물론 대용량 서비스 운영환경이라면) 또한 CRUD 작업과 검색, 집계와 같은 리소스를 제법 잡아먹는 역할도 수행하기 때문에 디스크만이 아닌 전체적인 스펙을 갖춘 서버로 운영하는 것이 좋다.

 

 

Ingest Node mode

다양한 형태의 데이터를 색인할 때 데이터의 전처리를 담당하는 모드다.

 

node.master: false / node.data: false / node.ingest: true / search.remote.connect: false

 

엘라스틱서치에서 데이터를 색인하려면 인덱스라는(RDB Schema) 틀을 생성해야한다. 비정형 데이터를 다루는 저장소로 볼 수 있지만 일정한 형태의 인덱스를 생성해주어야한다. 그리고 해당 인덱스에는 여러 포맷의 데이터 타입 필드가 존재한다. 만약 데이터를 색인할때 간단한 포맷 변경이나 유효성 검증 같은 전처리가 필요할 때 해당 모드를 이용할 수 있다.

 

Coordination Node mode

사용자 요청을 받아 처리하는 코디네이터 모드이다.

 

node.master: false / node.data: false / node.ingest: false / search.remote.connect: false

 

엘라스틱서치의 모든 노드는 기본적으로 코디네이션 모드 노드이다. 이 말은 즉, 모든 노드가 사용자의 요청을 받아 처리할 수 있다는 뜻이다. 하지만 이렇게 별도의 코디네이션 노드가 필요한 이유가 있을까? 싱글 모드로 구성된 클러스터에 사용자가 검색 요청을 보낸다면 검색요청을 받은 노드는 클러스터에 존재하는 모든 데이터 노드에게(싱글 모드는 모든 노드가 대상) 검색을 요청한다. 왜냐하면 클러스터에 존재하는 모든 데이터 노드에 샤드로 데이터가 분산되어 있기 때문이다. 그리고 각 샤드는 자신이 가지고 있는 데이터 내에서 검색을 수행하고 자신에게 요청을 보낸 노드에서 결과값을 전송한다. 그리고 모든 데이터를 취합하여 사용자에게 전달한다. 모든 데이터가 취합될때까지 요청을 다른 노드에게 보낸 코디네이션 노드역할(싱글모드에서는 코디네이션 이외의 모든일을 하는 노드가 된다.)을 하는 노드는 아무 일도 못하고 기다리고 있어야한다. 또한 데이터를 취합하는 일도 많은 양의 메모리가 필요한 작업이다. 이 상황에서 코디네이션 노드를 따로 구축하지 않았다면 이렇게 결과를 취합하는 과정에 마스터 노드로서의 역할이나 데이터 노드로서의 역할을 할 수 없게 되고 최악의 경우에는 노드에 장애가 발생할 수 있다. 이렇게 다른 노드들에게 요청을 분산하고 결과값을 취합하는 코디네이션 노드를 별도로 구축한다면 안정적인 클러스터 운영이 가능해진다.

 

 

대용량 클러스터 환경에서 전용 마스터 노드 구축이 필요한 이유

예를 들어보자. 만약 모든 노드를 싱글모드로 클러스터링을 구축한 환경에서 무거운 쿼리가 주 마스터 역할을 하는 싱글 노드에 요청되어 데이터 노드의 부하로 인해 시스템에 순간적으로 행(hang, freezing 시스템이 아무런 일도 하지 못하는 상황)이 걸리거나 노드가 다운되는 경우가 발생할 수 있다. 그렇다면 주 마스터 역할로써도 정상적으로 동작하지 못할 것이다. 이 순간 시스템 장애가 발생하면 쉽게 복구할 수 있는 상황도 복구할 수 없게되는 상황이 발생한다.

 

이러한 경우 다른 싱글 노드 중 하나가 마스터 역할로 전환되어 처리되지 않을 까라는 생각을 당연히 하게 되지만 모든 상황에서 그렇지는 않다. 주 마스터 노드가 hang 상태에 빠져있지만 시스템적으로 정상적으로 프로세스로 떠 있다 판단 될 수 있어 다른 후보 마스터에게 역할이 위임되지 않을 가능성이 있기 때문이다.

 

이렇게 마스터 노드와 데이터 노드의 분리는 대용량 클러스터 환경에서 필수이게 되는 것이다.

 

 

대용량 클러스터 환경에서의 검색엔진에서 코디네이션 노드 구축이 필요한 이유

엄청난 데이터량을 가지고 있는 클러스터를 가지고 있다고 생각해보자. 만약 이러한 클러스터에서 복잡한 집계 쿼리를 날린다고 가정하면 안그래도 리소스를 많이 잡아먹는 집계쿼리인데 데이터마저 크다면 엄청난 부하를 주게 될 것이다. 이런 상황에서 데이터 노드 모드와 코디네이션 노드 모드를 분리하여 클러스터 환경을 구성한다면 장애가 발생할 가능성이 조금은 낮아질 것이다. 왜냐 검색은 데이터노드가 담당하고 이러한 요청을 보내는 역할과 결과의 병합을 코디네이션 노드가 담당하기에 리소스 사용의 부담을 서로 나누어 갖기 때문이다.

 

 

클러스터 Split Brain 문제 방지

클러스터에는 마스터 노드 모드로 설정된 노드가 최소한 하나 이상 존재해야 장애가 발생하였을 때, 즉시 복구가 가능해진다. 다수의 마스터 노드가 존재할 경우 모든 마스터 노드들은 투표를 통해 하나의 마스터 노드만 마스터 노드로서 동작하고 나머지는 후보 마스터 노드로서 대기한다. 클러스터를 운영하는 중에 마스터 노드에 장애가 발생할 경우 대기 중인 후보 마스터 노드 중에서 투표를 통해 최종적으로 하나의 후보 마스터 노드가 주 마스터 노드로 승격하게 된다. 이후 장애가 발생한 주 마스터노드는 다시 후보 마스터 노드로 하락하게 된다. 이런식으로 마스터 노드의 부재없이 안정적인 클러스터 운영이 가능한 것이다.

 

그렇다면 전용으로 구축되는 마스터 노드는 몇개가 적당할까?

 

이런 상황을 생각해보자. 만약 주 마스터 노드에 장애가 발생하였고 후보 마스터 노드 3개 중 투표를 통해 하나의 마스터 노드를 선출하는 도중에 네트워크 환경에 단절이 발생했다 생각하자. 그렇다면 후보노드들은 모두 나 자신밖에 마스터노드 후보가 없다고 생각하고 자기 자신을 마스터 노드로 승격시킬 것이고, 각 노드가 동일하게 행동하여 하나 이상의 마스터 노드가 생겨버릴 수 있다.(Split Brain 문제) 이렇다면 클러스터는 엉망진창으로 꼬일 것이고 서비스 불능 상태가 될 수 있다. Split Brain 문제는 비단 엘라스틱서치만의 문제는 아니고 클러스터 환경에서 운영되는 애플리케이션 전반적인 문제이다. 엘라스틱서치는 이 상황을 하나의 설정만으로 해결방법을 제시한다.

 

elasticsearch.yml -> discovery.zen.minimum_master_nodes

 

이 속성은 기본 값으로 1을 가진다. 이 뜻은 마스터 노드 선출 투표를 진행할 때, 후보 마스터 노드의 최소한의 갯수를 뜻하는 것이다. 클러스터에 존재하는 마스터 노드의 개수가 1개이거나 2개일 경우는 해당 설정은 1로 설정하고 마스터 노드의 수가 3개 이상일 경우에는 다음 공식에 대입해서 적절한 값을 찾아 설정한다.

 

(마스터 후보 노드 수 / 2) + 1

 

  • 마스터 노드가 3개일 경우 : 3/2+1 = 2
  • 마스터 노드가 4개일 경우 : 4/2+1 = 3
  • 마스터 노드가 5개일 경우 : 5/2+1 = 3
  • 마스터 노드가 6개일 경우 : 6/2+1 = 4

싱글모드노드로 구성하는 간단한 클러스터링

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<node1>
cluster.name: clusterName
node.name: node1
network.host: 0.0.0.0
http.port: 9200
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9500"]
discovery.zen.minimum_master_nodes: 1
transport.tcp.port: 9300
#########싱글 노드로 동작 여부#########
node.master: true
node.data: true
node.ingest: true
search.remote.connect: true
 
 
<node2>
cluster.name: clusterName
node.name: node1
network.host: 0.0.0.0
http.port: 9400
discovery.zen.ping.unicast.hosts: ["127.0.0.1:9300"]
discovery.zen.minimum_master_nodes: 1
transport.tcp.port: 5300
#########싱글 노드로 동작 여부#########
node.master: true
node.data: true
node.ingest: true
search.remote.connect: true
cs

 

두개의 엘라스틱서치 디렉토리를 준비한 후에 각각의 설정 파일을 위와 같이 바꾸어준다. 우선 중요한 것은 cluster.name을 동일하게 마추어줘야한다. 그리고 포트는 적절히 할당해준다. 필자는 동일한 서버환경에서 두개의 노드를 설치한 것이라 포트가 다르지만 서로 다른 환경이라면 동일하게 포트를 맞춰놔도 무방하다. 그리고 중요한 것은 discovery 설정이다. 디스커버리 설정으로 서로다른 노드를 discovery할 수 있게 해주는 설정인 것이다. 그리고 모든 노드가 싱글모드로 동작시키게 하기 위해 싱글 노드 설정으로 세팅해주었다.

 

설정파일을 모두 변경하였으면 각각 엘라스틱서치를 실행 시킨 후에 아래의 요청을 보내 클러스터링이 잘 걸렸나 확인해보자.

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
GET http://localhost:9200/_cluster/health
 
result ->
{
    "cluster_name": "clusterName",
    "status": "green",
    "timed_out": false,
    "number_of_nodes": 2,
    "number_of_data_nodes": 2,
    "active_primary_shards": 0,
    "active_shards": 0,
    "relocating_shards": 0,
    "initializing_shards": 0,
    "unassigned_shards": 0,
    "delayed_unassigned_shards": 0,
    "number_of_pending_tasks": 0,
    "number_of_in_flight_fetch": 0,
    "task_max_waiting_in_queue_millis": 0,
    "active_shards_percent_as_number": 100
}
cs

 

필자는 클러스터 설정이 모두 정상적으로 적용되어 Active한 노드가 2개인것을 볼 수 있다. 물론 완벽한 클러스터링을 위해서는 설정해야 할것이 많을 수도 있다. 그리고 지금은 개발모드로 작성되어 부트스트랩과정을 거치지 않아서 쉽게 구성되었을 것이다. 하지만 추후에 운영환경모드로 실행을 하면 14가지정도의 부트스트랩 과정을 검사하기 때문에 맞춰주어야 하는 설정들이 많이 있다. 더 자세한 클러스터링 환경설정은 추후에 다루어볼 것이다.

posted by 여성게
: