이 문서의 허가되지 않은 무단 복제나 배포 및 출판을 금지합니다. 본 문서의 내용 및 도표 등을 인용하고자 하는 경우 출처를 명시하고 김종민(kimjmin@gmail.com)에게 사용 내용을 알려주시기 바랍니다.
여러 서버에 하나의 클러스터로 실행
Elasticsearch의 노드들은 클라이언트와의 통신을 위한 http 포트(9200~9299), 노드 간의 데이터 교환을 위한 tcp 포트 (9300~9399) 총 2개의 네트워크 통신을 열어두고 있습니다. 일반적으로 1개의 물리 서버마다 하나의 노드를 실행하는 것을 권장하고 있습니다. 3개의 다른 물리 서버에서 각각 1개 씩의 노드를 실행하면 각 클러스터는 다음과 같이 구성됩니다.
하나의 물리적인 서버 안에서 여러 개의 노드를 실행하는 것도 가능합니다. 이 경우에는 각 노드들은 차례대로 9200, 9201… 순으로 포트를 사용하게 됩니다. 클라이언트는 9200, 9201 등의 포트를 통해 원하는 노드와 통신을 할 수 있습니다. 만약에 서버1 에서 두개의 노드를 실행하고, 또 다른 서버에서 한개의 노드를 실행시키면 클러스터는 다음과 같이 구성됩니다.
서버1에는 두개의 노드가 있기 때문에 서버 1의 두번째 노드는 실행되는 http, tcp 포트가 각각 9201, 9301 로 실행이 됩니다.
물리적인 구성과 상관 없이 여러 노드가 하나의 클러스터로 묶이기 위해서는 클러스터명 cluster.name 설정이 묶여질 노드들 모두 동일해야 합니다. 같은 서버나 네트워크망 내부에 있다 하더라도 cluster.name이 동일하지 않으면 논리적으로 서로 다른 클러스터로 실행이 되고, 각각 별개의 시스템으로 인식이 됩니다.
하나의 서버에서 여러 클러스터 실행
하나의 물리 서버에 3개의 노드를 실행시킨다고 가정 해 보겠습니다. 노드들의 이름은 각각 node-1, node-2, node-3 이고 node-1과 node-2의 클러스터명은 es-cluster-1, node-3의 클러스터명은 es-cluster-2로 실행을 합니다. 설정은 config/elasticsearch.yml 파일에서 아래와 같이 입력합니다. 각 탭에서 노드의 설정을 확인합니다.
node-1과 node-2는 하나의 클러스터로 묶여있기 때문에 데이터 교환이 일어납니다. node-1로 입력된 데이터는 node-2 에서도 읽을 수 있으며 그 반대도 가능합니다. 하지만 node-3 은 클러스터가 다르기 때문에 node-1, node-2에 입력된 데이터를 node-3 에서 읽을 수는 없습니다.
가장 먼저 node-1을 실행시켰을 때 나타나는 화면입니다.
node-1 실행
$bin/elasticsearch-Ecluster.name=es-cluster-1-Enode.name=node-1[2019-08-27T05:22:07,254][INFO ][o.e.e.NodeEnvironment ] [node-1] using [1] data paths, mounts [[/ (/dev/disk1s1)]], net usable_space [88.2gb], net total_space [465.6gb], types [apfs]
[2019-08-27T05:22:07,256][INFO ][o.e.e.NodeEnvironment ] [node-1] heap size [989.8mb], compressed ordinary object pointers [true]
[2019-08-27T05:22:07,261][INFO ][o.e.n.Node ] [node-1] node name [node-1], node ID [RYhEbLLjQKaoHzGNkSNo-g], cluster name [es-cluster-1]
...
위 실행 화면에서 먼저 노드명이 [node-1]인 것을 확인할 수 있습니다. 실행 메시지를 계속 확인 하다 보면 다음과 같은 부분이 있습니다.
[o.e.c.s.MasterService] [node-1] elected-as-master부분에서 현재 node-1 이 마스터 노드로 선출 것을 확인할 수 있습니다. 마스터 노드에 대한 자세한 설명은 뒤에서 계속 다루도록 하겠습니다.
이제 node-1이 실행중인 상태에서 두번째 노드인 node-2를 실행시키면 다음과 같은 실행 메시지들을 확인할 수 있습니다.
node-2 실행
$bin/elasticsearch-Ecluster.name=es-cluster-1-Enode.name=node-2...[2019-08-27T07:50:54,308][INFO ][o.e.n.Node ] [node-2] starting ...[2019-08-27T07:50:54,479][INFO ][o.e.t.TransportService ] [node-2] publish_address {127.0.0.1:9301}, bound_addresses {[::1]:9301}, {127.0.0.1:9301}
...[2019-08-27T07:50:54,488][WARN ][o.e.b.BootstrapChecks ] [node-2] the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be configured
[2019-08-27T07:50:54,503][INFO ][o.e.c.c.ClusterBootstrapService] [node-2] no discovery configuration found, will perform best-effort cluster bootstrapping after [3s] unless existing master is discovered
[2019-08-27T07:50:54,778][INFO ][o.e.c.s.ClusterApplierService] [node-2] master node changed {previous [], current [{node-1}{RYhEbLLjQKaoHzGNkSNo-g}{KZxmWwFVTPKU5QHDbmULfg}{127.0.0.1}{127.0.0.1:9300}{dim}{ml.machine_memory=17179869184, ml.max_open_jobs=20, xpack.installed=true}]}, added {{node-1}{RYhEbLLjQKaoHzGNkSNo-g}{KZxmWwFVTPKU5QHDbmULfg}{127.0.0.1}{127.0.0.1:9300}{dim}{ml.machine_memory=17179869184, ml.max_open_jobs=20, xpack.installed=true},}, term: 1, version: 16, reason: ApplyCommitRequest{term=1, version=16, sourceNode={node-1}{RYhEbLLjQKaoHzGNkSNo-g}{KZxmWwFVTPKU5QHDbmULfg}{127.0.0.1}{127.0.0.1:9300}{dim}{ml.machine_memory=17179869184, ml.max_open_jobs=20, xpack.installed=true}}
...[2019-08-27T07:50:55,216][INFO ][o.e.h.AbstractHttpServerTransport] [node-2] publish_address {127.0.0.1:9201}, bound_addresses {[::1]:9201}, {127.0.0.1:9201}
...
node-2의 경우 tcp 포트가 9301, http 포트가 9201 로 잡힌 것을 확인할 수 있습니다.
[o.e.c.s.ClusterApplierService] [node-2] master node changed {previous [], current [{node-1} ... added {{node-1} ... 부분을 보면 같은 클러스터에 이미 실행중인 마스터 노드 node-1이 있기 때문에 node-2 는 node-1이 마스터로 있는 클러스터에 묶인 것이 확인됩니다.
node-2 를 실행하고 난 뒤 다시 node-1 의 콘솔 메시지를 확인하면 마찬가지로 node-2 가 클러스터에 추가되었다는 메시지를 확인할 수 있습니다.
먼저 node-3 의 http, tcp 포트 설정은 9202, 9302 를 사용하도록 설정되었습니다.
[o.e.d.HandshakingTransportAddressConnector] [node-3] ... handshake failed for ...
부분을 보면 같은 서버에서 실행중인 node-1, node-2 를 찾았지만 클러스터명이 es-cluster-2 로 다르기 때문에 node-3은 node-1, node-2 와 같은 클러스터로 바인딩 되지 않았습니다. 그리고 [o.e.c.s.MasterService ] [node-3] elected-as-master ... 부분에서 node-3 스스로 es-cluster-2 클러스터의 마스터 노드로 선출 된 것을 확인할 수 있습니다.
지금까지 실행한 노드들의 클러스터 구조를 그림으로 나타내면 아래 그림과 같습니다.
디스커버리 (Discovery)
노드가 처음 실행 될 때 같은 서버, 또는 discovery.seed_hosts: [ ] 에 설정된 네트워크 상의 다른 노드들을 찾아 하나의 클러스터로 바인딩 하는 과정을 디스커버리 라고 합니다. 디스커버리는 다음과 같은 순서로 이루어집니다.
discovery.seed_hosts 설정에 있는 주소 순서대로 노드가 있는지 여부를 확인
노드가 존재하는 경우 > cluster.name 확인
일치하는 경우 > 같은 클러스터로 바인딩 > 종료
일치하지 않는 경우 > 1로 돌아가서 다음 주소 확인 반복
노드가 존재하지 않는 경우 > 1로 돌아가서 다음 주소 확인 반복
주소가 끝날 때 까지 노드를 찾지 못한 경우
스스로 새로운 클러스터 시작
클러스터에 노드가 무수히 많아도 보통 discovery.seed_hosts 설정에는 처음에 탐색할 노드 3~5 개 정도만 설정 하면 큰 문제 없이 클러스터가 바인딩 됩니다. 보통은 마스터 후보 노드들을 지정하게 되며 처음 탐색하는 대상 노드는 반드시 먼저 가동중이어야 합니다.