데이터 엔지니어( 실습 정리 )/elasticsearch

5. 서비스 환경에 클러스터 구성

세용용용용 2025. 1. 3. 15:35

[ 엘라스틱 서치 바이블 ] 공부한 후 정리한 내용 입니다!!!

 

 

1. es 운영 환경을 위한 설정과 클러스터 구성

 

(1-1) 노드 설정과 노드 역할

  • 클러스터 구성을 위해 노드 역할을 지정 (각 노드가 클러스터에서 어떤 역할을 담당할지 )

 

노드 역할

  • 마스터 후보 : 클러스터 관리 역할 ( 인덱스 생성 삭제, 어떤 샤드를 어느 노드에 할당할 것인지 )
  • 데이터 노드 : 실제 데이터를 가지고 있는 노드, 데이터와 관련된 작업 수행
  • 인제스트 노드 : 데이터 색인 전 전처리를 수행하는 인제스트 파이프라인 수행 노드
  • 조정 노드 : 요청을 받아 다른 노드에 요청을 분배하고 클라이언트에 최종 응답을 돌려주는 노드 ( 기본적으로 모든 노드 조정 역할 수행 )
  • 원격 클러스터 클라이언트 노드 : 다른 es 클러스터에 클라이언트로 붙을 수 있는 노드
  • 데이터 티어 노드 : 데이터 노드를 용도, 성능별로 ( hot, warm, cold, frozen ) 티어로 구분해 저장하는 데이터 티어 구조 채택 시 사용하는 역할

 

elasticsearch.yml

  • es 클러스터 구성을 위한 설정 파일
### elasticsearch.yml

# 노드 역할을 지정 ( 비워두면 조정 노드)
# master, data, ingest 등 0개 이상 조합해 지정
node.roles: [ master, data ]

# 클러스터 명 및 노드 이름
cluster.name: sy0218-cluster
node.name: ${HOSTNAME}

# 클러스터 네트워크 정보 및 http 통신을 위한 포트 지정
network.host: 192.168.56.10
http.port: 9200

# 클러스터 초기 노드 목록 지정
discovery.seed_hosts: ["apserver","slave1","slave2"]

# 클러스터 기동시 마스터 수행할 후보 노드 목록
cluster.initial_master_nodes: ["apserver","slave1"]

# 데이터 디렉터리 경로 지정
path.data: /data/esdata
path.logs: /var/log/elasticsearch

xpack.security.enabled: false # 엘라스틱 보안 기능 적용 모드
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false

 

 

(1-2) 그 외 필요한 주요 설정

  • 힙 크기, 스왑등 서비스 환경에서 es 운영 시 주요 설정

 

힙 크기

  • jvm.options를 열어 지정
  • 힙 크기는 운영 환경에 맞는 적절한 크기로 지정 
  • 운영 환경 메모리가 63기가 미만 이라면 :  힙 크기는 최소한 시스템 메모리 절반 이하로 지정 ( 나머지 절반은 os 캐시로 쓰도록 놔두는 것이 좋음, 루씬이 캐시를 많이 활용함 )
  • 운영 환경 메모리가 63기가 이상 이라면  : 힙 크기는 32GB 이상 지정하지 않아야함 ( 32GM 이내 힙 영역에만 접근하면 Compressed OOPs 라는 기능을 적용해 포인터를 32비트로 유지할 수 있음 )
java -Xmx32736m -XX:+PrintFlagsFinal 2> /dev/null | grep UseCompressedOops 값이 true가 되는 경계값으로 힙 크기 지정
    >>> bool UseCompressedOops	:= true	{lp64_product}

 

  • Compressed OOPs로 인코딩된 주소를 실제 주소로 디코딩 하려면 3비트 시프트 연산 후에 기본 주소를 더하는 작업이( 입 영역이 시작되는 ) 필요
  • Zero-based Compressed OOPs : 기본 주소를 0으로 바꿔 시프트 연산을 제외한 나머지 과정을 없앨 수 있음
  • Zero-based Compressed OOps 적용을 위한 힙 크기 경계값은 Compressed OOPs 적용에 필요한 크기보다 작음
java -XX:+UnlockDiagnosticVMOptions -Xlog:gc+heap+coops=debug -Xmx30720m -version

>>> [0.019s][info][gc,heap,coops] Heap address: 0x0000000080000000, size: 30720 MB, Compressed Oops mode: Zero based, Oop shift amount: 3

 

  • 힙 크기는 Zero-based Compressed OOPs 까지 적용되는 선까지 내려 설정하는 편이 성능상 이득이지만 반드시 그런건 아님, 하지만 최소한 Compressed OOPs 적용 되도록 힙 크기를 지정하는 것이 나음

 

 

스와핑

  • es는 스와핑을 사용하지 않는 것을 권고
  • 스와핑 끄기 : /etc/fstab에서 swap 부분 주석 후 운영체제 재시작

 

swapiness 설정스와핑을 완전히 끌 수 없는 상황에서 스와핑 경향성 최소화 하는 방법

### 스왑핑 민감도 확인
sysctl vm.swappiness
>> 0에 가까울수록 메모리 부족시 스왑사용 최소화
>> 100에 가까울수록 적극적 스왑 사용

### 엘라스틱서치 스왑 민감도 설정 ( 1로 설정 )
vim /etc/sysctl.d/98-elasticsearch.conf >>> vm.swappiness = 1

 

 

bootstrap.memory_lock 설정

  • elasticsearch.yml 파일에 bootstrap.memory_lock: true 설정을 지정해 프로세스 주소 공간을 메모리로 제한시켜 스와핑을 막아줌
### 노드 별 memory_lock 설정 확인
curl -XGET "http://192.168.56.10:9200/_nodes?pretty&filter_path=**.mlockall"

 

 

vm.max_map_count 설정

  • 프로세스가 최대 몇 개까지 메모리 맵 영역을 가질 수 있는지 지정 ( es는 최소 262144 지정 )
### max_map_count 갯수 확인
sysctl vm.max_map_count
>>> vm.max_map_count = 262144

### 만약 262144보다 낮다면 높여서 지정
vim /etc/sysctl.d/98-elasticsearch.conf >> vm.max_map_count = 262144

 

 

파일 기술자 : 현재 사용자가 열수있는 최대 파일 수

  • es는 많은 파일 기술자를 필요로 함 : 최소 65535 이상으로 지정
### 파일 기술자 확인
ulimit -a | grep "open files"
>>> open files                          (-n) 65536

### 파일 기술자 65535보다 작으면 늘려줘야됨
vim /etc/security/limits.conf >>> elasticsearch - nofile 65535

 

 

JVM 지정, 설정

  • 특별한 사유 없으면 내장 JDK 사용
### 굳이 설정을 변경해야하면
jvm.options를 직접 수정 밑 jvm.options.d 밑에 새 파일 작성

 

 

2. 클러스터 구성 전략

  • 어떻게 노드 역할을 배분해 클러스터 구성하면 좋을지??

 

(2-1) 마스터 후보 노드와 데이터 노드 분리

  • 마스터 노드는 클러스터 관리 중요한 역할을 수행..
  • es 운영시 상대적으로 데이터 노드가 죽을 확률이 높은데 마스터, 데이터 노드 분리를 해두지 않을시 마스터 역할이 재대로 수행되지 않아 클러스터 안정성이 떨어지게 됨
  • 즉, 일부 노드 문제 생기면 끝날 상황에 클러스터 전체 장애 상황으로 커짐.. ㅠㅠ
  • 마스터 노드는 데이터 노드보다 성능이 낮은 서버를 사용해도 됨

 

(2-2) 마스터 후보 노드와 투표 구성원

  • 마스터 노드를 선출하는 집단
  • 마스터 후보 노드는 홀수대를 분비하는 것이 비용대비 효율적

 

(2-3) 서버 자원이 많지 않은 경우

  • 최소 3대의 클러스터를 구성해야 의미가 있음 ( 마스터 3대, 데이터 3대 ), 샤드 복제본을 설정했다면 최소 1대의 서버 문제까지는 서비스 중단 없이 대응 가능
  • 6대 이상 클러스터 부터는 마스터 후보, 데이터 노드 완전히 분리 가능

 

(2-4) 서버 자원이 굉장히 많이 필요한 경우

  • 서버가 많은 경우 클러스터를 쪼갤 수 있는지 검토 ( 마스터 노드를 늘릴 수 없기에 클러스터 적절한 선에서 분리 필요 )
  • 클러스터 분리할수 없는 상황이면 마스터 후보 노드도 높은 사양의 서버로 준비

 

(2-5) 사양이 크게 차이나는 서버인 경우

  • 데이터 티어 구조 도입 고려 ( 높은 성능 서버 : data_content, data_hot 역할, 낮은 성능 서버 : data_warm, data_cold 역할 지정 )

 

(2-6) 조정 전용 노드

  • 조정 역할만 수행하는 노드 ( 안정적인 클러스터 운영을 위해 두는 것이 좋음 )
  • 엘라스턱서치 대량의 요청이 조정 전용 노드로 인입되기 에 최악의 상황을 막을수 있음
  • 조정노드는 데이터를 들고있지 않아 샤드 복구와 관련 걱정도 없음
  • 서버 여유가 되면 읽기작업 조정노드, 쓰기 작업 조정노드 분리하는 것도 좋음 ( 상황에 따라 유연한 대처가 가능하기 떄문 )

 

(2-7) 한 서버에 여러 프로세스 띄우기

  • 한 서버에 여러 프로세스를 띄우는 대상은 데이터 노드 여야함 ( 마스터 노드일 경우 클러스터 안정성이 떨어짐 )
  • 다중 프로세스 기동을 위해 cluster.name 같게, node.name 다르게 설정
  • 각 프로세스 독립적인 http, transport, path.logs, path.data 가지게 설정
  • clustre.routing.allocation.same_shard.host: true 지정
  • es는 코어 개수를 감지해 스레드 풀 크기를 조정하므로 CPU 자원 충분해야됨
  • 파일기술자, mmap max_map_count, 네트워크 대역폭 자원도 공유되기에 리스트 가 있음 ㅠㅠ

 

 

3. 보안 기능 적용

  • 엘라스틱서치는 클러스터, 노드 간 통신은 암호화 되지 않음.. 보안 기능을 적용해 보안 사고를 방지해야됨

 

(3-1) 보안 기능 미적용

  • elasticsearch.yml 설정파일 에서 xpack.security.enabled: false 지정시 엘라스틱서치 보안 기능 적용 안함..

 

(3-2) es 노드간 통신 TLS 적용

  • 노드간 transport 레이어, HTTP 레이어에 TLS 통신을 적용

 

1. CA, self-signed 인증서 생성

ca를 생성 ( 아무 노드 에서 한번만 )
./bin/elasticsearch-certutil ca
>>> 엔터를 쳐 기본 파일명 생성 후, 키스토어 암호를 지정 ( sy0218 )

이어서 해당 파일을 이용해 인증서 생성
./bin/elasticsearch-certutil cert --ca elastic-stack-ca.p12
>>> ca 키스토어 암호, 생성할 인증서 키스토어 파일 명 ( 엔터시 기본 파일명 ), 생성할 인증서 키스토어 암호 입력
>>> 인증서가 담긴 elastic-certificates.p12 파일을 모든 노드 config 디렉터리 밑으로 복사 ( config 없으면 설정파일과 같은 디렉토리 )
>>> scp [ 파일명 ] root@][ 서버ip ]:[ 경로 ]


엘라스틱서치 기존 설정
xpack.security.enabled: false
xpack.security.enrollment.enabled: false
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: false


엘라스틱서치 설정 변경
xpack.security.enabled: true
xpack.security.transport.ssl.enabled: true
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.verification_mode: certificate
xpack.security.transport.ssl.client_authentication: required
xpack.security.transport.ssl.keystore.path: elastic-certificates.p12
xpack.security.transport.ssl.truststore.path: elastic-certificates.p12


엘라스틱서치 설정 변경 이후
elastic-certificates.p12 키스토어 파일의 암호를 엘라스틱서치 키스토어에 추가
** 암호는 elastic-certificates.p12 생성시 추가한 패스워드 입력 **
/usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.keystore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.transport.ssl.truststore.secure_password

>>> 이후 클러스터 풀 리스타트 하면 노드 간 통신에 TLS 적용이 완료

 

 

2. 이제 엘라스틱서치 미리 만들어져 있는 계정을 활성화하고, es 접근시 기본 인증을 통해 계정 정보를 인증하도록 설정

내부 계정 초기 비밀번호 설정
/usr/share/elasticsearch/bin/elasticsearch-reset-password --auto -u kibana_system >>> 키바나가 엘라스틱서치와 통신할 떄 사용하는 계정 비밀번호 설정
>>> g7C1EC=CzPUZFQcaLKjq

/usr/share/elasticsearch/bin/elasticsearch-reset-password --interactive -u elastic
>>> sy0218
base64 인코딩 확인 >>> echo -n 'elastic:sy0218' | base64

es요청 헤더에 인증 관련 정보 담아 보내야함
curl -X GET "http://192.168.56.10:9200/_cat/indices?v&pretty" -H "Authorization: Basic ZWxhc3RpYzpzeTAyMTg="


이제 키바나 설정을 변경해 kibana_system 계정을 이용하도록 설정
kibana.yml 변경 해야됨 ( elasticsearch.username: "kibana_system", 패스워드는 키스토어 이용 )
/usr/share/kibana/bin/kibana-keystore create >>> 키스토어 생성
/usr/share/kibana/bin/kibana-keystore add elasticsearch.password >>> 키스토어에 elasticsearch.password 값을 추가

수동으로 REST API 호출에 TLS 적용
- 지금까지 노드간 TLS, 기본 인증 적용완료
- 하지만 계정과 비밀번호 평문 ,응답 데이터도 노출 되으로 HTTP 레이어도 TLS 적용하야됨

 

 

3. 엘라스틱서치 http 레이어에 TLS 적용

>>> es 클러스터, kibana 종료 후, 아무 노드에서 실습 실행

1. CSR 생성 : /usr/share/elasticsearch/bin/elasticsearch-certutil http
1-1 : 공인 CA가 서명한 인증서 발급해 사용하려면 'y', 실습에서는 직접 서명을 진행할 것이기에 'n' 선택
1-2 : 보유 중 ca사용할 것인지 ( 노드간 transport 통신에 TLS 적용시 발급 받은 CA가 있으므로 'y' 선택 )
1-3 : ca 파일의 경로 지정 ( elastic-certificates.p12 파일 경로 입력 ), 경로 지정후 키스토어 암호를 입력 >>> /usr/share/elasticsearch/elastic-stack-ca.p12
1-4 : 인증서 유효기간 지정 { 90일: 90D, 18개월: 18M, 5년: 5Y } 형식으로 지정
1-5 : 인증서 노드마다 발급할지 여부 ( 실습에서는 'y' 를 선택해 노드마다 다른 인증서 발급 )
1-6 : 노드 이름을 입력
1-7 : 호스트 이름 입력 ( 한줄씩 입력하며 모두 끝나면 빈줄을 입력 )
1-8 : ip 주소 입력 ( 노드 접속에 사용되는 모든 ip주소 입력 입력 모드 끝나면 빈줄 입력 )
1-9 : 최종 확인
1-10 : 최종 파일 출력 위치 지정 ( zip 파일료 생성됨 )

>>> 압축을 풀고 http.p12 파일을 각 노드 디렉토리에 복사

>>> elasticsearch.yml 설정 
xpack.security.http.ssl.enabled: true
xpack.security.http.ssl.keystore.path: http.p12

>>> 엘라스틱서치 키스토러에 http.p12 파일의 암호를 추가
/usr/share/elasticsearch/bin/elasticsearch-keystore add xpack.security.http.ssl.keystore.secure_password
/usr/share/elasticsearch/bin/elasticsearch-keystore list >>> 암호 추가 확인

>>> 이후 엘라스틱 기동시 http 레이어에 tls가 적용


키바나가 es 호출시 TLS 적용
>>> elasticsearch-ca.pem을 kibana 설정파일 디렉토리 하위에 복사

자체 서명 인증서이기에 curl 요청이 문제 발생 ( 임시 방편으로 -k 옵션을 통해 인증서 검증을 무시 )
curl -X GET "https://192.168.56.10:9200/_cat/indices?v&pretty" -H "Authorization: Basic ZWxhc3RpYzpzeTAyMTg=" -k



키바나 브라우저 사이 TLS 적용
/usr/share/elasticsearch/bin/elasticsearch-certutil csr -name kibana-server -dns example.com, www.example.com
>>> kibana-server.csr, kibana-server.key 두 파일이 나옴
>>> 자체 서명 인증서 발급 : openssl x509 -req -in kibana-server.csr -signkey kibana-server.key -out kibana-server.pem
>>> .pem, .key 파일 키바나 설정파일 디렉토리로 복사


>>> kibana.yml 설정
server.publicBaseUrl: "https://192.168.56.10:5601"
elasticsearch.hosts: ["https://192.168.56.10:9200","https://192.168.56.11:9200","https://192.168.56.12:9200"]
elasticsearch.ssl.certificateAuthorities: [ "/etc/kibana/elasticsearch-ca.pem" ] (elasticsearch-ca.pem 파일 경로 입력)


server.ssl.enabled: true
server.ssl.certificate: "/etc/kibana/kibana-server.pem"
server.ssl.key: "/etc/kibana/kibana-server.key"