Search
Duplicate
5️⃣

5장. 클러스터 구축하기 (1)

elasticsearch.yml 파일을 통해 설정할 수 있는 항목들
jvm.options 파일을 통해 설정할 수 있는 항목들
클러스터 구축을 위해 노드들의 역할을 설정하는 방법
고가용성을 고려하여 설계된 클러스터를 사용하고 검증하는 방법

5.1 elasticsearch.yml 설정 파일

: elasticsearch.yml 파일은 ElasticSearch를 구성하기 위해 기본이 되는 환경 설정 파일이다.
: 영역별로 elasticsearch.yml 파일의 영역들을 확인해보자.
5.1.1 Cluster 영역
cluster.name: my-application ---- 1
YAML
복사
: 클러스터 전체에 적용되는 설정, 1번은 클러스터의 이름을 설정하는 항목으로, 클러스터를 구성하는 모든 노드들은 동일한 클러스터 이름을 사용해야 한다.
: 클러스터 이름을 변경하려면 노드를 재시작해야 하기 때문에 처음부터 신중하게 설정해야 하며, 기본값은 elasticsearch다.
5.1.2 Node 영역
node.name: node-1 ---- 1 node.attr.rack: r1 ---- 2
YAML
복사
: Node 영역은 해당 Node에만 적용되는 설정이다.
1.
번은 노드의 이름을 설정하는 항목으로 노드의 이름은 클러스터 내에서 유일해야 한다. ElasticSearch에는 ${HOSTNAME}이라는 노드의 호스트명을 인식할 수 있는
변숫값을 미리 정의해 놓았기 때문엥 위와 같이 설정하면 노드의 이름이 호스트명과 같아져서 다른 노드들과 겹치지 않게 설정할 수 있다.
: 노드 이름 또한 운영 중에는 변경이 불가능하며 변경하려면 노드를 재시작해야 한다. 클러스터에서는 노드 하나가 서비스에서 제외된다고 큰 문제가 생기는 것은 아니지만
이름을 변경하기 위해서는 불필요하게 재시작해야 하기 때문에 신중하게 설정하는 것이 좋다. 주석처리된 상태로 Node를 실행하면 ElasticSearch가 랜덤으로 선언한다.
2.
번은 각 노드에서 설정할 수 있는 커스텀 항목으로 사용자 정으된 rack 값을 통해 HA 구성과 같이 샤드를 분배할 수 있게끔 해주는 기능이다.
5.1.3 Pathb 영역
path.data: /var/lib/elasticsearch path.logs: /var/log/elasticsearch
YAML
복사
: Paths 영역은 데이터와 로그의 저장 위치와 관련된 설정이다.
1.
노드가 가지고 있을 문서들을 저장할 경로를 설정하는 항목이다. 4장에서 살펴본 것처럼 색인이 완료된 문서들은 세그먼트에 파일로 저장되는데 이 파일들이 위치할 경로
: path.data: /var/lib/elasticsearch/data1, /var/lib/elasticsearch/data2와 같이 여러 개의 경로를 지정하는 것도 가능하다.
⇒ 이 경우, 어떤 문서는 data1에 어떤 문서는 data2에 저장되며 여러 개의 디스크를 가진 노드에서 사용할 경우 디스크에 분산해서 저장하는 효과를 통해 성능상 이점이 있지만 관리가 복잡해지고 두 개의 경로 중 하나의 경로에서 문제가 발생했을 때, 어떤 문서들이 영향을 받게 되는지 파악하기 힘들다.
2.
ElasticSearch에서 발생하는 로그를 저장할 경로를 설정하는 항목이다.
: Paths 영역은 elasticsearch.yml의 기본값들 중에서 유일하게 주석 처리가 없는 영역이다.
: 사용자가 색인한 문서와 ElasticSearch에서 발생하는 애플리케이션 로그를 저장하기 위해 반드시 설정되어 있어야 하는 값들이기 때문이다.
: 이 항목들의 설정값이 없으면 애플리케이션이 실행되지 않는다.
5.1.4 Memeory 영역
: Memory 영역에는 ElasticSearch 프로세스에 할당되는 메모리 영역을 어떻게 관리할 것인지 간략하게 설정할 수 있다.
bootstrap.memory_lock: true
YAML
복사
1.
시스템의 스왑 메모리 영역을 사용하지 않도록 하는 설정이다. ElasticSearch는 최대한 스왑 메모리 영역을 사용하지 않도록 권고하고 있다.
이 설정을 통해 스왑 영역을 사용하지 않으면 성능을 보장할 수 있지만 메모리가 부족할 경우에는 Out Of Memory 에러를 일으켜 노드의 장애로 이어질 수 있다.
대부분의 경우에는 큰 문제가 없지만 JVM 힙 메모리의 용량이 시스템 메모리 용량의 절반 이상이 된다면 Out OF Memory 에러를 일으킬 수 있기 때문에 조심해서 사용해야 한다.
이 설정을 사용하기 위해서는 elasticsearch.yml 파일을 설정해주는 것 뿐만 아니라 OS의 /etc/security/limits.conf 파일도 수정해야 한다.
5.1.5 Network 영역
: Network 영역은 ElasticSearch 애플리케이션이 외부와 통신할 때 사용하게 될 IP 주소를 설정하는 항목
: 외부와의 통신뿐 아니라 노드 간의 통신에도 Network 영역에서 설정한 값들을 토대로 동작하기 때문에 주의해서 설정해야 한다.
network.host: 192.168.0.1 ---- 1 http.port: 9200 ---- 2
YAML
복사
1.
ElasticSearch 애플리케이션이 외부와 통신할 때 사용하게 될 IP 주소를 설정, 다양한 IP를 애플리케이션에서 사용할 수 있음.
외부에 노출시키지 않고 서버 내부에서만 사용할 수 있는 127.0.0.1과 같은 로컬 IP를 설정할 수도 있고, 외부와의 통신을 가능하게 하기 위해 서버에서 사용하고 있는
IP를 사용할 수도 있다. 만약 두 가지 경우를 모두 사용하고자 한다면 0.0.0.0의 IP 주소를 사용하면 된다.
network.host 설정은 network.bind_host와 network.publish_host 두 개로 나눌 수 있다.
network.host 설정 → network.bind_host, network.publish_host 자동 설정
network.host 설정 x → network.bind_host, network.publish_host 설정
⇒ 클러스터를 실제로 구축할 때는 대부분 network.host 항목을 설정하기보다 두 개의 항목을 각각 설정하는 경우가 많음
: 먼저 IP가 10.10.10.10인 노드가 있을 때, 이를 host로 설정하게 되면 외부 클라이언트의 요청도 받고 클러스터 내의 다른 노드와 통신도 하게 된다.
이는 얼핏 보기에 아무런 문제가 없어 보이나, 다만 이슈가 될 부분이 하나 있다, 노드 A 내부에선 localhost를 통한 사용이 불가능하다는 것
2.
ElasticSearch 애플리케이션이 사용하게 될 포트 번호를 설정한다.
: API를 여러 개의 IP로 호출하고 싶다면 분리해야 한다. 클라이언트의 요청은 자신의 IP뿐만 아니라 localhost 내부 도메인의 주소인 127.0.0.1로 받아야 하고
클러스터 내부에서 노드 간 통신은 자신의 IP를 사용해야 한다는 것을 알 수 있다.
: 즉 클라이언트의 요청을 처리하기 위한 IP인 network.bind_host는 0.0.0.0으로 publish_host는 노드 자신의 IP로 설정해야 한다.
5.1.6 Discovery duddur
: Discovery 영역은 노드 간의 클러스터링을 위해 필요한 설정이다.
discovery.zen.ping.unicast.hosts: ["host1", "host2"] ---- 1 discovery.zen.minimum_master_nodes: ---- 2
YAML
복사
1.
클러스터링을 위한 다른 노드들의 정보를 나열한다. 배열의 형식으로 설정할 수 있기 때문에 한 대만 해도 되고, 두 대 이상을 나열해도 된다.
2.
클러스터를 구축하기 위해 필요한 최소한의 마스터 노드 대수를 설정한다.
: 클러스터링할 때 Discovery 영역에 설정한 값은, 어떤 노드들과 클러스터링을 구축하게 되는지 확인하는 데 사용된다.
discovery.zen.ping.unicast.hosts: ["10.10.10.10"] discovery.zen.minimum_master_nodes: 2
YAML
복사
: 위와 같은 설정일 때, 애플리케이션이 실행되면 IP가 10.10.10.10인 서버에 현재 ElasticSearch 애플리케이션이 동작중인지 확인한다.
: 그리고 10.10.10.10의 서버로부터 현재 구축되어 있는 클러스터의 정보를 받아온다.
: 만약 10.10.10.10 서버가 이미 다른 클러스터에 합류한 상태라면 해당 클러스터에 대한 모든 정보를 받아온다.
: 그리고 이 정보들 중에서 마스터 노드의 갯수가 2개가 맞는지 확인하고 2개 이상이 맞다면 성공적으로 해당 클러스터에 합류한다.
: split brain 현상을 방지하기 위한 discovery.zen.minimum_master_nodes라는 설정이 존재한다. 이 값은 클러스터를 유지하기 위한 최소한의 마스터 노드 갯수다.
: split brain이란 3대의 마스터 노드와 3대의 데이터 노드가 존재하는 클러스터가 있다고 할 때, 이 상황에서 네트워크 장애가 발생하여 마스터 노드 간의 연결이 끊어진다면, 서로 다른 마스터 노드를 가지고 3개의 데이터 노드는 다른 두 개의 클러스터 노드에 모두 종속되는 상황이 발생할 수 있다. 즉 최소한의 마스터 노드 갯수를 설정하여 새로운 클러스터가 생기지 않도록 하기 위함.
5.1.7 Gateway 영역
: Gateway 설정은 클러스터 복구와 관련된 내용들을 포함
gateway.recover_after_nodes: 3 ---- 1
YAML
복사
1.
ElasticSearch 클러스터 내의 노드를 전부 재시작할 때 최소 몇개의 노드가 정상적인 상태일 때 복구를 시작할 것인지 설정
: ElasticSearch의 버전 업그레이드를 진행하거나 전체 노드 장애로 클러스터 내의 모든 노드를 다시 시작해야할 때가 있다.
: 이런 작업을 Full Cluster Restart라고 부르며 이렇게 재시작한 노드들은 순차적으로 클러스터링을 진행한다.
: 클러스터링을 시작하면 클러스터 내의 인덱스 데이터를 복구하기 시작하는데, 이때 사용자가 지정한 노드의 수만큼 클러스터에 노드가 복귀하였을 때부터 인덱스 데이터에 대한 복구를 시작할 수 있게하는 설정이다.
5.1.8 Various 영역
action.destructive_requires_name: true
YAML
복사
: 클러스터에 저장되어 있는 인덱스를 _all이나 wildcard 표현식으로 삭제할 수 없도록 막는 설정
5.1.9 노드의 역할 정의
: 상기 항목들을 어떻게 정의하느냐에 따라 클러스터의 성격이 바뀐다. ElasticSearch가 기본으로 해둔 설정 외에도 굉장히 많은데 이중, 노드의 역할을 정의하는 항목은 다음과 같다.
노드 역할
항목
기본 설정값
마스터 노드
node.master
TRUE
데이터 노드
node.data
TRUE
인제스트 노드
node.ingest
TRUE
코디네이트 노드
x
TRUE
: 모든 역할의 기본값은 true이다. 즉 아무런 설정을 하지 않은 노드는 모든 노드의 역할을 수행할 수 있다는 이야기다.

5.2 jvm.options 설정 파일

: ElasticSearch는 Java로 만들어진 애플리케이션이기 때문에 힙 메모리, GC 방식 등과 같은 JVM 관련 설정이 필요하다.
-Xms1g -Xmx1g ## GC configuration -XX:+UseConcMarkSweepGC -XX:CMSInitiatingOccupancyFraction=75 -XX:+UseCMSInitiatingOccupancyOnly ## GIGC Configuration
YAML
복사
1.
JVM에서 사용하게 될 힙 메모리의 최솟값
2.
JVM에서 사용하게 될 힙 메모리의 최대값, 일반적으로 두 값을 같게 유지하는 것을 추천
3.
CMS라는 GC 방식을 사용한다는 설정, 대부분의 경우에 좋은 성능을 내기 때문에 특별한 경우가 아니라면 유지하는 것을 추천
4.
CMS GC를 사용할 경우 힙 메모리 사용량이 어느정도가 되면 old GC를 수행할 것인지에 대한 설정
5.
CMS GC를 수행할 때, GC 통계 데이터를 근거로 하지 않고 위의 설정값만을 기준으로 동작한다는 의미
6.
CMS GC가 아닌 G1 GC에 대한 설정
힙 메모리의 영역을 32GB 미만으로 제한하는 이유
: JVM은 연산을 위한 데이터들을 저장하기 위한 공간으로 힙 메모리를 사용하며 이때 힙 메모리에 저장되는 데이터들을 오브젝트라고 부른다.
: 이 오브젝트에 접근하기 위한 메모리상의 주소를 OOP(Ordinary Object Pointer)라는 구조체에 저장한다.
: 각각의 OOP는 시스템의 아키텍처에 따라 32비트 혹은 64비트의 주소 공간을 가리킬 수 있는데 32비트라면 최대 4GB까지 주소 공간을 가리킬 수 있다.
: 64비트의 경우 최대 16EB까지의 주소 공간을 가리킬 수 있게되는데, 64비트의 경우 32비트보다 더 넓은 주소 공간을 가리키기 위한 연산과 메모리 공간이 필요함
: 이때문에 성능 측면에서 32비트보다 떨어질 수 밖에 없다. 그래서 JVM은 시스템 아키텍처가 64비트라고 하더라도 확보해야할 힙 메모리 영역이 4GB보다 작다면
: 32비트 기반의 OOP를 사용해서 성능을 확보한다.
JVM은 64비트 기반의 OOP를 사용하지 않고 Compressed OOP를 사용하여 32 비트 기반의 OOP를 사용하되 4GB 이상의 영역을 가리킬 수 있도록 구현했다.
: Native OOP는 1번 값을 1번 주소에 2번 값을 2번 주소에 Compressed OOP는 1번 값을 8의 배수인 8번에, 2번 값을 16번에 저장한다.
: 이 덕분에 기존 4GB에서 32GB까지 힙 메모리 영역이 증가한다.
그렇기 때문에 힙 메모리 할당을 32GB 미만으로 하게 되면 32 비트 기반의 OOP를 계속 사용할 수 있다.
힙 메모리의 영역을 전체 메모리의 절반 정도로 설정하는 이유
: 다음으로 전체 메모리의 절반 정도를 힙 메모리로 사용하는 이유는 ElasitcSearch는 색인된 데이터를 세그먼트라는 물리적인 파일로 저장한다.
: 파일로 저장하기 때문에 I/O가 발생할 수 밖에 없는 구조인데, 이 작업은 시스템 전체로 봤을 때 가장 느린 작업에 해당하기 때문에 잦을 경우 성능 저하가 발생한다.
: OS에서는 이런 성능 저하를 방지하기 위해 파일의 내용을 메모리에 저장해놓는 페이지 캐시 기법을 사용한다. 하지만 페이지 캐시는 애플리케이션들이 사용하지 않는
미사용 메모리를 활용해서 동작하기 때문에 페이지 캐시를 최대한 활용하기 위해서는 애플리케이션이 사용하는 메모리를 줄이는 것이 좋다.
: 특히 ElasticSearch와 같이 빈번한 I/O 작업이 발생해야 하는 경우 가급적 많으 메모리를 페이지 캐시로 활용하여 I/O 작업이 모두 메모리에서 끝낼 수 있도록 하는
것이 좋다. 이런 이유로 공식 문서에서는 물리 메모리의 절반 정도를 힙 메모리로 할당할 것을 권고한다.

5.3 클러스터 사용하기

: 고가용성의 ElasticSearch를 구성하여 데이터를 인덱싱해보자.
실습 부분은 이후에 진행

5.4 마치며

1.
ElasticSearch는 클러스터로 운영되는 애플리케이션이며 각 노드의 설정에 정의된 역할을 수행하며 운영된다.
2.
마스터 노드는 클러스터 전체의 메타데이터를 관리하며 클러스터를 구축하기 위해 반드시 한 대 이상으로 구성되어야 한다. 하지만 클러스터의 안정성을 위해서는
minimum_master_nodes를 과반수로 설정할 수 있도록 두 대 이상의 홀수 값으로 지정하는 것이 좋다.
3.
데이터 노드는 사용자의 데이터를 저장하고 검색 요청을 처리하는 노드이다.
4.
minimum_master_nodes는 마스터 노드 개수의 과반수로 설정해야 split brain 현상을 방지할 수 있다.
5.
향후 확장성을 위해서 마스터 노드와 데이터 노드는 가급적 분리해서 구축하는 것이 좋다.