ElasticSearch Clustering 방법

Halim Kim·2021년 5월 2일
4

ElasticSearch

목록 보기
1/4

이번 글은 ElasticSearch를 설치하는 방법과 Server 2대를 이용해 Cluster를 구성해보는 방법에 대한 글입니다.

ElasticSearch 설치

JDK 설치

아래의 명령어로 JDK의 Version을 확인할 수 있다. JDK가 없으면 Not Found 메세지가 뜸.

$ javac -version

만약에 설치가 안되어 있으면 아래의 apt install으로 JDK 설치할 수 있음. ES를 쓰는데 OpenJDK가 아닌 다른 것을 써도 될 것임.

$ sudo apt install openjdk-11-jdk

GPG 공개키

ElasticSearch는 GPG Key를 이용하여 무결성을 검증하기 때문에 GPG Key를 가져와야 한다. 아래의 명령어를 입력해 GPG Key를 받아올 수 있다.

$ wget -qO - https://artifacts.elastic.co./GPG-KEY-elasticsearch | sudo apt-key add -


OK가 뜨면 문제가 없음.

ElasticSearch Repository 등록

apt(Advanced Packaging Tool)에 Repository를 등록하면 apt를 이용하여 Elasticsearch를 설치할 수 있다.

직접 /etc/apt/sources.list.d Directory에서 만들어 주어도 되지만 아래의 명령어처럼 Shell Script를 실행하여 등록할 수도 있다.

$ sudo sh -c 'echo "deb https://artifacts.elastic.co/packages/7.x/apt stable main" > /etc/apt/sources.list.d/elastic-7.x.list'


elastic-7.x.list가 생긴 것을 확인할 수 있다.

ElasticSearch 설치

Repository를 등록했으니 이제 apt로 elasticsearch를 설치할 수 있다.
아래의 명령어를 실행해 Elasticsearch를 설치한다.

$ sudo apt update
$ sudo apt install elasticsearch

ElasticSearch 실행

ElasticSearch가 설치가 완료되었으면 실행할 수 있다. 참고로 이 Guide를 따라서 ES를 설치하면 /etc/elasticsearch Directory로 설치가 되었을 것이다.

아래의 명령어로 ES를 실행한다.

$ sudo systemctl start elasticsearch.service

참고로 부팅시 바로 실행하도록 설정할 수도 있다.

$ sudo systemctl enable elasticsearch.service

아래의 명령어로 ES instance의 상태를 확인할 수 있다.

$ sudo systemctl status elasticsearch.service

Service 내리는것은 아래의 명령어

$ sudo systemctl stop elasticsearch.service

Clustering 준비

ElasticSearch는 이미 Local에 설치가 되었다고 가정, ElasticSearch Cluster를 구성하려면 ElasticSearch의 환경설정 파일인 elasticsearch.yml 파일에 수정이 필요하다.

Local에 설치했다면 elasticsearch.yml 파일은 아래의 Directory에서 찾을 수 있다.
/etc/elasticsearch

Cluster 설정을 따로 하지 않고 처음 yml 파일을 열면 path, data, path.logs 외에는 모두 주석으로 처리가 되어 있다.

주석을 지우고 바꿔야 할 항목은 아래와 같다.

cluster.name (String) : 구성하려는 Cluster의 이름이다. Node들을 같은 Cluster에 넣기 위해서는 같은 Cluster name을 써야지 인식할 수 있다.

node.name (String) : Node의 이름, 당연한 이야기이지만 같은 Cluster 내에 추가할 Node의 이름은 각기 다르게 설정해야 한다.

node.master (bool) : true 혹은 false 값으로 이 ES instance를 master로 쓸지 아닌지 결정

node.data (bool) : true 혹은 false 값으로 이 ES instance를 data node로 쓸지 아닌지 결정

network.host (String) : Default로 ES는 Local에서만 접근이 가능하도록 설정이 되어 있다. 외부에서 접속 가능하도록 만들기 위해서는 network.host 값을 0.0.0.0으로 바꾸어주면 된다.

discovery.seed_hosts(String List) : ES node가 시작했을 때, Cluster에 구성되기 위해 찾아가는 Host의 주소의 List, IP주소를 직접 입력해도 되고, DNS 주소가 있다면 DNS를 입력해도 된다.

cluster.initial_master_nodes (String List) : Master Node가 될 수 있는 후보들의 List이다.

Clustering Test

Clustering 과정

2개의 각기 다른 Server를 이용하여 Test를 진행하였다. 위의 Clustering 준비 부분에서 언급한 Parameter들에게 각각 값을 설정해주었다.

Server 1 yml 파일

parametevalue
cluster.nametest-cluster
node.namenode-1
network.host0.0.0.0
node.mastertrue
node.datafalse
discovery.seed_hosts[“host1”, “host2”, “Server 2의 주소(IP or DNS)"]
cluster.initial_master_nodes[“node-1”]

Server 2 yml 파일

parametevalue
cluster.nametest-cluster
node.namenode-2
network.host0.0.0.0
node.masterfalse
node.datatrue
discovery.seed_hosts[“host1”, “host2”, “Server 1의 주소(IP or DNS)"]
cluster.initial_master_nodes[“node-1”]

2개의 yml 파일에서 확인할 수 있듯이 cluster의 이름은 ‘test-cluster’로 통일하였고 server 1의 node 이름은 node-1, server 2의 node 이름은 node-2이다.

network.host는 ES Instance가 외부로도 노출될 수 있도록 0.0.0.0으로 설정하였다.

node-1을 Master로 만들 것이기 때문에 node-1의 node.master를 true, node.data를 false로 설정해주었고 node-2는 그 반대로 설정하였다.

Test에서는 server 1의 IP주소는 192.168.156.145이므로 server 2의 discovery.seed_hosts에 이 주소를 추가시켜주었고 server 1의 discovery.seed_hosts는 반대로 server 2의 IP주소인 192.168.156.146을 추가시켜주었다. (host2는 원래 적혀있는 것이라 그냥 두었는데 이 Test에서는 의미가 없다. DNS Resolution 안됨.)

마지막으로 Cluster를 형성했을 때 node-1이 master가 되도록 양쪽 yml 파일 모두 cluster.initial_master_nodes를 [“node-1”]으로 설정해주었다.

참고: 모든 Node의 cluster.initial_master_nodes의 값은 같아야 한다.

yml 파일을 모두 설정을 완료하고 server 1의 ES instance와 server 2의 ES instance를 실행하였음.

Cluster가 구성되었는지 확인하는 방법은 Host에 request를 보내면 된다. Test에서는 Curl을 이용하였다.

먼저 server 2에 있는 node-2에 아래와 같은 Request를 보내보았다.

$ curl http://192.168.156.145:9200/_cluster/health?pretty

Node가 죽어 있다면 아래와 같은 메시지가 뜬다.

curl: (7) Failed to connect to 192.168.156.145 port 9200: Connection refused

Cluster 구성이 되었다면 아래와 같이 node의 개수가 2개인 것을 확인할 수 있을 것이다.

실제로 Master Node가 어떤 것인지 확인하기 위해서는 아래의 명령어를 활용했다.

$ curl http://192.168.156.146:9200/_cat/nodes?v


192.168.156.145의 IP주소를 가진 node-1의 Host가 Master인 것을 확인할 수 있다.

Test Issue

처음 Test를 진행했을 때는 모르고 cluster.initial_master_nodes의 값을 [“node-1”, “node-2”]로 설정해서 node-1, node-2 모두 Master Node가 될 수 있도록 하였다.

그렇게 하니 처음에는 Cluster가 잘 형성되었는데, 어느 순간 연결이 잠시 끊기면 원래의 Cluster로 다시 복구되지 않았다.

그래서 모니터링을 시도해서 변화를 지켜보았고, watch 명령어를 활용해 1초마다 Curl Request를 보내서 응답을 확인하였다.

$ watch -n 1 curl http://192.168.156.145:9200/_cat/nodes?v

Cluster가 잘 구성되어 있는 상태로 Master Node가 있는 Host에 Curl Request를 보내면 Cluster의 Node가 2개로 Clustering 된 것이 확인된다.

참고: Data Node에 Cluster API를 이용한 Request를 보내도 Cluster가 잘 구성되었다면 Master Node로 Routing되기 때문에 Data Node에 Request를 보내도 된다.

시간이 얼마 지나고 Cluster의 연결이 끊겨 Node가 분리되었고 각각의 Node가 각자의 Cluster에서 Master Node가 되었다. 정확히 얘기하면 떨어져 나간 node-2가 새로운 Cluster를 형성한 것이다.

이유를 찾고자 ES의 Log 파일을 뒤져보았다. elasticsearch.yml 파일에 log 파일의 Path가 명시되어 있으니 명시된 Directory로 가면된다. (/var/log/elasticsearch/)

필요한건 Cluster에 관련된 Log이기 때문에 처음에 cluster 이름으로 정했던 test-cluster.log 파일을 뒤져보았다.

아래의 Exception이 난 것을 확인했고..

Caused by: org.elasticsearch.cluster.coordination.CoordinationStateRejectedException: join validation on cluster state with a different cluster uuid LcitTe7KQFCEF8Ww_MuU_g than local cluster uuid sTdyHyX8SFSN5Mr5XH1E0A

이 Exception의 원인을 분석해보았는데 결과는 아래와 같다.

처음 Test에서는 node-1, node-2가 모두 Master Node가 될 수 있게 설정을 해놓았는데, Cluster 구성이 처음에는 잘 되었다가 연결이 어느 순간 끊기면 node-1, node-2가 각각의 Cluster를 새로 생성한다. 그런데 ES에서는 하나의 Cluster에 속해 있던 Datanode가 다른 Cluster로 편입되지 못하게 막아놓았고(Data Loss가 발생할 수 있기 때문에) 그렇기 때문에 각각의 서로 다른 Cluster를 형성해버린 node-1과 node-2가 다시 하나로 Clustering되지 못한 것이다. 이런 현상을 ‘Split Brain’이라고 부르기도 하는 것 같다.

그래서 Test를 node-1이 Master node, node-2가 Data node가 되도록 다시 했다. 제대로 다시 Test하기 위해서는 한가지 작업이 더 필요했는데, 각 Node의 data가 저장된 Directory를 지워서 등록된 Cluster에 대한 정보를 없애는 것이다.

Node의 Data가 저장될 파일 Path는 elasticsearch.yml 파일에서 확인할 수 있다. (/var/lib/elasticsearch)

nodes라는 Directory가 있는 것을 확인할 수 있는데 지운다.

$ sudo rm -rf nodes

읽어주셔서 감사합니다.

profile
나는 하림

0개의 댓글