Rocky Linux Elasticsearch 설치

설치 환경 및 구성

  • Rocky Linux 9.2 (Blue Onyx)
  • Java 17
  • Elasticsearch 8.7.1 (for spring boot 3.1.x, spring data elasticsearch 5.1.x)
    • Cluster: Master Node 1대, Data Node 2대
  • Kibana

Elasticsearch를 설치하기전에 Supported OS 확인하기

https://www.elastic.co/kr/support/matrix

기본 설정

hostnamectl set-hostname elastic-master-node-1
hostnamectl set-hostname elastic-data-node-1
hostnamectl set-hostname elastic-data-node-2

vim /etc/hosts 
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.10.177 elastic-master-node-1
192.168.10.178 elastic-data-node-1
192.168.10.179 elastic-data-node-2
# timedatectl set-timezone Asia/Seoul
# timedatectl
# useradd elastic
# passwd elastic
test1234

JVM 설정

Elasticsearch에 포함되어 있는 OpenJDK 있지만 사용하길 원하는 Java 버전을 ES_JAVA_HOME 환경 변수로 설정하여 사용할 수 있다.

AdoptOpenJDK 17 을 설치 후 설정

https://adoptium.net/temurin/releases/

https://adoptium.net/blog/2021/12/eclipse-temurin-linux-installers-available/

cat <<EOF > /etc/yum.repos.d/adoptium.repo
[Adoptium]
name=Adoptium
baseurl=https://packages.adoptium.net/artifactory/rpm/centos/8/$(uname -m)
enabled=1
gpgcheck=1
gpgkey=https://packages.adoptium.net/artifactory/api/gpg/key/public
EOF
yum update         # update if you haven't already

yum install temurin-17-jdk

java -version
openjdk version "17.0.3" 2022-04-19
OpenJDK Runtime Environment Temurin-17.0.3+7 (build 17.0.3+7)
OpenJDK 64-Bit Server VM Temurin-17.0.3+7 (build 17.0.3+7, mixed mode, sharing)

vim /etc/profile 맨 아래 추가

export JAVA_HOME=/usr/lib/jvm/temurin-17-jdk/
export ES_JAVA_HOME=/usr/lib/jvm/temurin-17-jdk/
export PATH=$PATH:$JAVA_HOME/bin
export PATH=$PATH:$ES_JAVA_HOME/bin

Elasticsearch 설치

https://www.elastic.co/guide/en/elasticsearch/reference/current/install-elasticsearch.html

설치 방법은 다음과 같다.

  • Archive
  • zip for windows
  • debian package
  • RPM
  • Docker

현재 Linux를 사용하고 있기 때문에 RPM으로 설치해도 무방하나 Archive로 설치를 진행해보기로 했다.

mkdir /elastic

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.7.1-linux-x86_64.tar.gz

wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.7.1-linux-x86_64.tar.gz.sha512

yum install perl-Digest-SHA -y

shasum -a 512 -c elasticsearch-8.7.1-linux-x86_64.tar.gz.sha512 

tar -xzf elasticsearch-8.7.1-linux-x86_64.tar.gz

cd elasticsearch-8.7.1/ 

chown -R elastic:elastic /elastic

Elasticsearch Heap 설정

일반적으로 최대 힙 크기는 RAM의 50%까지 설정해야 하지만 32GB를 넘지 않아야 한다.

또한 최대 및 최소 힙 크기 값이 동일할 것을 권장함.

elasticsearch-8.7.1/ config/jvm.options

-Xms4g
-Xmx4g

elasticsearch.yml 설정

cluster.name: elastic-cluster

node.name: master-node-1

node.roles: [master]

path.data: elasticsearch-8.7.1/data
path.logs: /elastic/elasticsearch-8.7.1/logs

bootstrap.memory_lock: true

network.host: 192.168.10.177
http.port: 9200

discovery.seed_hosts: ["elastic-master-node-1", "elastic-data-node-1", "elastic-data-node-2"]

cluster.initial_master_nodes: ["master-node-1"]


xpack.security.enabled: true
xpack.security.enrollment.enabled: true
xpack.security.http.ssl.enabled: false
xpack.security.transport.ssl.enabled: true
xpack.security.transport.ssl.keystore.path: certs/node.p12
xpack.security.transport.ssl.truststore.path: certs/node.p12

node.roles

배열 형태로 master, data, ingest 등의 역할을 지정한다.

data노드는 node.roles: [data]라고 지정하면 된다.

만약 여러개의 역할을 하는 노드를 만들려면 node.roles: [data, ingest]와 같은 형식으로 지정할 수 있다.

bootstrap.memory_lock: true

​ ES 프로세스가 메모리 만으로 한정되게 설정 (Swap 메모리를 사용하게 되면 성능이 저하된다.)

discovery.seed_hosts

​ 다른 ES 노드들과 Cluster를 형성할 수 있도록 해준다.

cluster.initial_master_nodes

​ master node 들을 지정하는 옵션이며 node.name과 일치해야 한다.

xpack.security.enabled

​ 보안 설정 여부이며 true로 설정 시 보안 관련 설정을 해야 한다.

​ 보안 관련 설정 참고: https://www.elastic.co/guide/en/elasticsearch/reference/current/targz.html#targz-running

mkdir /elastic/elasticsearch-8.7.1/config/certs/
/elastic/elasticsearch-8.7.1/bin/elasticsearch-certutil ca
vim /elastic/elasticsearch-8.7.1/config/instances.yml

instances:
  - name: master-node-1
    dns:
      - elastic-master-node-1
    ip:
      - 192.168.10.177

  - name: data-node-1
    dns:
      - elastic-data-node-1
    ip:
      - 192.168.10.178

  - name: data-node-2
    dns:
      - elastic-data-node-2
    ip:
      - 192.168.10.179

master node

# cd /elastic/elasticsearch-8.7.1
# bin/elasticsearch-certutil cert --silent --in config/instances.yml --out certs.zip --ca elastic-stack-ca.p12 --days 3000
# unzip certs.zip

# cp elastic-stack-ca.p12 data-node-1/
# cp elastic-stack-ca.p12 data-node-2/
# mv elastic-stack-ca.p12 config/certs/
# cp master-node-1/master-node-1.p12 config/certs/node.p12

# chown -R elastic:elastic /elastic

# systemctl restart elasticsearch

# scp -r /elastic/elasticsearch-8.7.1/data-node-1/* elastic@192.168.10.178:/elastic/elasticsearch-8.7.1/config/certs/

# scp -r /elastic/elasticsearch-8.7.1/data-node-2/* elastic@192.168.10.179:/elastic/elasticsearch-8.7.1/config/certs/

elastic-data-node-1에 접속하여 아래 명령 수행

# cd /elastic/elasticsearch-8.7.1/config/certs
# mv data-node-1.p12 node.p12

# systemctl restart elasticsearch

elastic-data-node-2에 접속하여 아래 명령 수행

# cd /elastic/elasticsearch-8.7.1/config/certs
# mv data-node-2.p12 node.p12

# systemctl restart elasticsearch

maste node 비밀번호 설정

# /elastic/elasticsearch-8.7.1/bin/elasticsearch-setup-passwords interactive

[root@elastic-master-node-1 certs]# /elastic/elasticsearch-8.7.1/bin/elasticsearch-setup-passwords interactive
******************************************************************************
Note: The 'elasticsearch-setup-passwords' tool has been deprecated. This       command will be removed in a future release.
******************************************************************************

Initiating the setup of passwords for reserved users elastic,apm_system,kibana,kibana_system,logstash_system,beats_system,remote_monitoring_user.
You will be prompted to enter passwords as the process progresses.
Please confirm that you would like to continue [y/N]y


Enter password for [elastic]: test1234
Reenter password for [elastic]:
Enter password for [apm_system]:
Reenter password for [apm_system]:
Enter password for [kibana_system]:
Reenter password for [kibana_system]:
Enter password for [logstash_system]:
Reenter password for [logstash_system]:
Enter password for [beats_system]:
Reenter password for [beats_system]:
Enter password for [remote_monitoring_user]:
Reenter password for [remote_monitoring_user]:
Changed password for user [apm_system]
Changed password for user [kibana_system]
Changed password for user [kibana]
Changed password for user [logstash_system]
Changed password for user [beats_system]
Changed password for user [remote_monitoring_user]
Changed password for user [elastic]

서버 Swap 비활성화

elasticsearch에서 JVM 메모리 이외 swap을 사용하게 되면 성능이 저하될 수 있기 때문에 swap을 비활성화 해주는 것이 좋다.

sudo swapoff -a

/etc/fstab에 swap 관련 설정을 모두 주석 처리

/dev/mapper/rl-root     /                       xfs     defaults        0 0
UUID=9b8eabba-3216-4699-a02f-319950c1b97a /boot                   xfs     defaults        0 0
#/dev/mapper/rl-swap     none                    swap    defaults        0 0

만약 실제 RAM을 초과해도 속도는 느려지지만 시스템 다운을 막는 방법을 사용하고 싶다면 swappiness 설정으로 swap 사용을 최소화해서 사용할 수도 있다.

아래 swappiness 설정은 swap을 비활성화 하지 않은 상태에서 사용하는 방법이다.

vm.swappiness는 메모리 영역을 스왑 영역으로 옮기는 비율을 결정하는 파라미터이다.

이 값이 높아지면 캐시 영역이 여유가 있음에도 불구하고 스왑 영역을 사용하게 되므로 불필요한 스와핑이 발생하고 Disk I/O가 발생하므로 성능에 영향을 끼친다.

처리량이 높은 어플리케이션에서 vm.swappiness = 1로 설정하는 이유는 메모리 재할당 과정 속에서 불필요한 스와핑을 줄이고, 가능한 캐시영역을 비우고 스왑을 사용하고자 함이다.

0이 아닌 1로 설정하는 이유는

0으로 설정하면 1로 설정했을 때보다 훨씬 더 많은 page cache를 해제하게 되는데, page cache를 지나치게 버리면 I/O가 높아지고 시스템의 load를 상승시킬 수 있다고 한다.

/etc/sysctl.conf 파일에서 다음 속성을 지정한다.

vm.swappiness=1

ES에서 페이지 캐시를 사용하는 이유

  • 객체는 메타데이터, 포인터 등이 추가 되므로 실제 데이터보다 많은 메모리를 사용한다.
  • GC는 Heap 영역에 저장되는 데이터가 증가함에 따라 점점 느려진다.
  • Full GC로 인해 발생하는 STW(Stop-the-world) 패널티
  • 애플리케이션이 시작될 때에는 JVM에 캐싱된 데이터가 없으므로 느리다. (Warm Up 필요)

오픈 가능한 파일 최대 개수 & 메모리 LOCK 설정

elasticsearch는 동시에 많은 파일 액세스가 발생하기 때문에 ulimit이 작으면 data loss가 발생할 수 있음.

Elasticsearch를 실행하는 사용자에게 메모리를 잠글 권한이 없기 때문에 mlockall이 실패할 수 있음.

/etc/security/limits.conf에서 다음 행을 추가

모든 사용자 설정

* soft nofile 65536
* hard nofile 65536
* soft memlock unlimited
* hard memlock unlimited

또는

elasticsearch 서비스 계정 설정

elasticsearch soft nofile 65536
elasticsearch hard nofile 65536
elasticsearch soft memlock unlimited
elasticsearch hard memlock unlimited
ulimit -a 또는 ulimit -n 으로 확인

만약 elasticsearch를 systemd로 구동하는 경우에는 위의 ulimit 값이 적용되지 않는다. limits.conf 파일은 사용자 레벨에서 로그인한 사용자 세션에만 영향을 주기 때문이다. systemd로 구동 시에는 service 파일에 다음과 같이 LimitNOFILE, LimitMEMLOCK 옵션을 적용해야 한다.

/etc/systemd/system/elasticsearch.service

[Unit]
Description=Elasticsearch
Documentation=https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html
Wants=network-online.target
After=network-online.target

[Service]
Type=simple
User=elastic
Group=elastic
LimitNOFILE=65536
LimitMEMLOCK=infinity
Environment=ES_HOME=/elastic/elasticsearch-8.7.1
Environment=ES_JAVA_HOME=/usr/lib/jvm/temurin-17-jdk
ExecStart=/elastic/elasticsearch-8.7.1/bin/elasticsearch
Restart=on-failure
RestartSec=5
StartLimitInterval=60
StartLimitBurst=3

[Install]
WantedBy=multi-user.target
systemctl enable elasticsearch
systemctl daemon-reload

systemctl status elasticsearch

systemctl start elasticsearch

가상 메모리 설정

Elasticsearch는 mmapfs기본적으로 디렉토리를 사용하여 인덱스를 저장하는데 mmap 수에 대한 기본 운영 체제 제한이 너무 낮아 메모리 부족 예외가 발생할 수 있다.

sysctl -w vm.max_map_count=262144

영구 적용하려면 /etc/sysctl.conf에서 vm.max_map_count를 변경해야 한다.

sysctl -n vm.max_map_count
262144

스레드 수 설정

Elasticsearch 사용자가 생성할 수 있는 스레드 수가 4096개 이상인지 확인합니다.

# ulimit -u
30588

#ulimit -a
...
max user processes                  (-u) 30588

만약 proc 값이 4096보다 작으면 /etc/security/limits.conf 파일에서 아래 내용을 추가한다.

elasticsearch soft nproc 4096
elasticsearch hard nproc 4096

systemd로 Elasticsearch가 실행된다면 프로세스의 스레드 수를 자동으로 구성하기 때문에 추가 구성이 필요하지 않다.

TCP 재전송 시간 초과

Elasticsearch 는 노드간 TCP 연결을 통해 통신한다.

대부분의 Linux 배포판에서 TCP는 통신 할 때 일시적인 네트워크 중단이 발생하면 손실된 패킷을 최대 15번까지 재전송하게 된다. 이는 네트워크 파티션이나 실패한 노드를 감지하는 데 몇 분까지도 걸리게 된다. 이는 ES 클러스터가 노드 장애를 감지하는 시간을 지연시키기 때문에 샤드 할당 및 검색 경로를 다시 지정하는 것도 늦어 진다. 따라서 노드 장애를 빨리 감지할 수 있도록 최대 TCP 재전송 횟수를 줄여야 한다.

다음 명령으로 최대 TCP 재전송 수를 5번으로 변경할 수 있다. (약 6초의 타임아웃)

sysctl -w net.ipv4.tcp_retries2=5

영구 적용하려면 /etc/sysctl.confnet.ipv4.tcp_retries2 값을 지정하면 된다.

재 시작 후 sysctl net.ipv4.tcp_retries2 명령어를 통해 확인할 수 있다.

sysctl -n net.ipv4.tcp_retries2
262144

기타

 SELinux는 /usr/lib/systemd/systemd execute에서 파일가 /elastic/elasticsearch-8.7.1/bin/elasticsearch 액세스하지 못하게 합니다.
sudo setenforce 0

vim /etc/selinux/config
SELINUX=disabled


위 설정들을 변경하고 재시작을 해주자…

방화벽 설정

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="22" protocol="tcp" accept'

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="9100" protocol="tcp" accept'

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="9200" protocol="tcp" accept'

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="9300" protocol="tcp" accept'

firewall-cmd --permanent --remove-service=ssh

firewall-cmd --reload
firewall-cmd --list-all

Cluster 확인

master node 서버에서 master node 를 실행하고 logs/elastic-cluster.log를 보면 다음과 같이 Warnning이 발생하는데,

이것은 elasticsearch.yml에서 설정한 discovery.seed_hosts: [“elastic-master-node-1”, “elastic-data-node-1”, “elastic-data-node-2”] 부분의 elastic-data-node-1 또는 elastic-data-node-2가 실행되지 않아 단일 노드 클러스터로 실행중이라는 로그이다.

[2023-07-26T15:53:59,302][WARN ][o.e.c.c.Coordinator      ] [master-node-1] This node is a fully-formed single-node cluster with cluster UUID [ilpozfn3ToWEFxLPzylzGg], but it is configured as if to discover other nodes and form a multi-node cluster via the [discovery.seed_hosts=[elastic-master-node-1, elastic-data-node-1, elastic-data-node-2]] setting. Fully-formed clusters do not attempt to discover other nodes, and nodes with different cluster UUIDs cannot belong to the same cluster. The cluster UUID persists across restarts and can only be changed by deleting the contents of the node's data path(s). Remove the discovery configuration to suppress this message.

data node를 실행하면 다음과 같이 로그가 찍힌다.

[2023-07-26T15:54:28,291][INFO ][o.e.c.s.MasterService    ] [master-node-1] node-join[{data-node-1}{CQ-Lxm4oTpusU4m0QgRIjQ}{cUXa6jMoS-uvCVaKo0lqbA}{data-node-1}{192.168.10.178}{192.168.10.178:9300}{d}{8.7.1} joining], term: 1, version: 26, delta: added {data-node-1}{CQ-Lxm4oTpusU4m0QgRIjQ}{cUXa6jMoS-uvCVaKo0lqbA}{data-node-1}{192.168.10.178}{192.168.10.178:9300}{d}{8.7.1}
[2023-07-26T15:54:28,448][INFO ][o.e.c.s.ClusterApplierService] [master-node-1] added {data-node-1}{CQ-Lxm4oTpusU4m0QgRIjQ}{cUXa6jMoS-uvCVaKo0lqbA}{data-node-1}{192.168.10.178}{192.168.10.178:9300}{d}{8.7.1}, term: 1, version: 26, reason: Publication{term=1, version=26}
[2023-07-26T15:54:28,456][INFO ][o.e.c.c.NodeJoinExecutor ] [master-node-1] node-join: [{data-node-1}{CQ-Lxm4oTpusU4m0QgRIjQ}{cUXa6jMoS-uvCVaKo0lqbA}{data-node-1}{192.168.10.178}{192.168.10.178:9300}{d}{8.7.1}] with reason [joining]

다음 명령으로 cluster 상태를 확인한다.

elastic-master-node-1# curl -X GET http://192.168.10.177:9200/_cat/nodes -u elastic:test1234

192.168.10.178 4 75 2 0.04 0.13 0.08 d - data-node-1
192.168.10.179 3 74 0 0.00 0.05 0.02 d - data-node-2
192.168.10.177 5 94 0 0.13 0.12 0.10 m * master-node-1

Nori Analysis 설치

각 노드에서 아래 명령 실행

/elastic/elasticsearch-8.7.1/bin/elasticsearch-plugin install analysis-nori

-> Installing analysis-nori
-> Downloading analysis-nori from elastic
[=================================================] 100%  
-> Installed analysis-nori
-> Please restart Elasticsearch to activate any plugins installed

elasticsearch 재시작

systemctl restart elasticsearch

dictionary나 synonyms 파일이 있다면 서버로 전송

scp -r /your_file_path/* root@192.168.10.177:/elastic/elasticsearch-8.7.1/config

Kibana 설치

elasticsearch와 마찬가지로 설치는 여러 방법이 있고, 이번에는 rpm으로 설치를 진행한다.

kibana는 master node에 설치한다.

# cd /elastic

wget https://artifacts.elastic.co/downloads/kibana/kibana-8.7.1-x86_64.rpm

wget https://artifacts.elastic.co/downloads/kibana/kibana-8.7.1-x86_64.rpm.sha512

shasum -a 512 -c kibana-8.7.1-x86_64.rpm.sha512 

sudo rpm --install kibana-8.7.1-x86_64.rpm

경고: kibana-8.7.1-x86_64.rpm: Header V4 RSA/SHA512 Signature, key ID d88e42b4: NOKEY
Creating kibana group... OK
Creating kibana user... OK
Created Kibana keystore in /etc/kibana/kibana.keystore

/etc/kibana/kibana.yml 설정

server.port: 5601
server.host: 192.168.10.177
server.publicBaseUrl: "http://192.168.10.177:5601"

Kibana systemd 설정 및 시작

systemctl daemon-reload
systemctl enable kibana.service

systemctl start kibana.service

systemctl status kibana.service

kibana 관련 파일 위치

image-20230726165006151

kibana start log

journalctl -u kibana.service

7월 26 16:46:57 elastic-master-node-1 systemd[1]: Started Kibana.
...
7월 26 16:47:17 elastic-master-node-1 kibana[2885]: i Kibana has not been configured.
7월 26 16:47:17 elastic-master-node-1 kibana[2885]: Go to http://localhost:5601/?code=376188 to get started.

방화벽 설정

firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="192.168.10.0/24" port port="5601" protocol="tcp" accept'

firewall-cmd --zone=public --add-service=http --add-service=https --permanent

firewall-cmd --reload
firewall-cmd --list-all

Kibana 접속하기

image-20230726210432982

Configure manually를 클릭한다.

http://Kibana설치노드 IP:9200 입력후 Check address 클릭

image-20230726210818073

위에서 master node 비밀번호 설정한 값을 넣어준다.

image-20230726210901753

인증 코드를 넣어라고 나온다.

image-20230726210916506

설치 노드로 가서 위에서 안내한 명령어를 실행한다.

/usr/share/kibana/bin/kibana-verification-code
Your verification code is:  069 123

결과 코드를 화면에 입력하고 Verify을 클릭하면 설정이 진행된다.

image-20230726211220858

설정이 완료되면 다시 로그인하라고 하는데 아이디(elastic)와 비밀번호를 입력하고 로그인하면 kibna에 접속이 완료된다.

image-20230726211415616

좌측 상단 메뉴 아이콘을 클릭하고 Dev tool을 들어가서 간단한 테스트를 해보자

image-20230726211722661

References

https://www.elastic.co/guide/en/elasticsearch/reference/current/important-settings.html#unicast.hosts

https://www.elastic.co/guide/en/kibana/current/install.html#_hosted_kibana

https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/

https://brewagebear.github.io/fundamental-os-page-cache/

댓글남기기