-
Notifications
You must be signed in to change notification settings - Fork 5
ELK 스택 설정
키워드 검색을 구현하고자, 프로젝트에 엘라스틱 서치, 로그스태시, 키바나를 도입해주었다.
Spring Data Elastic Search의 설정법이 버전별로 상이하므로 어떻게 설정했는지 공유하고자 한다.
스프링 부트 3.0.5에서 진행하였고, 엘라스틱 서치 싱글 노드 기준이다.
FROM docker.elastic.co/elasticsearch/elasticsearch:8.5.3
COPY plugin/hanhinsam-0.1.zip /plugin/hanhinsam.zip
RUN bin/elasticsearch-plugin install analysis-nori && elasticsearch-plugin install file:///plugin/hanhinsam.zip
도커 파일을 통해, 한글 형태소 분석기 플러그인 nori, 초성 필터 플러그인 hanhinsam이 빌드 시 설치되게 해주었다.
플러그인이 필요하지 않다면 도커파일을 작성하지 않고 엘라스틱 서치 이미지를 그대로 사용해도 무방하다.
-
도커 이미지 빌드
docker build -t el:0.1 .
여기서 el:0.1은 임의로 지정한 도커 이미지 이름이다.
한글 초성 검색이 필요하지 않다면 플러그인 설정은 하지 않아도 괜찮다.
이때 한글 초성 검색 기능을 구현하고자 [hanhinsam 플러그인](https://github.com/yainage90/hanhinsam)을 사용하였다.
그런데 스프링부트 3.0.5 기준 Elastic Search 플러그인 코드 일부가 Deprecated 되어 호환문제가 발생했다.
- Hanhinsam 플러그인 기존 코드
public class ChosungFilterFactory extends AbstractTokenFilterFactory {
public ChosungFilterFactory(IndexSettings indexSettings, Environment env, String name,
Settings settings) {
super(indexSettings, name, settings);
}
@Override
public TokenStream create(TokenStream tokenStream) {
return new ChosungFilter(tokenStream);
}
}
- 호환 문제 해결 코드
public class ChosungFilterFactory extends AbstractTokenFilterFactory {
public ChosungFilterFactory(IndexSettings indexSettings, Environment env, String name,
Settings settings) {
super(name, settings); // indexSettings를 제거해줘야 한다
}
@Override
public TokenStream create(TokenStream tokenStream) {
return new ChosungFilter(tokenStream);
}
}
[엘라스틱 서치 플러그인 공식 깃허브](https://github.com/elastic/elasticsearch/commit/02568210bafae6d0e5af49e3020fb405f327e15a(https://github.com/elastic/elasticsearch/commit/02568210bafae6d0e5af49e3020fb405f327e15a) 를 참고하여 오픈소스의 코드를 수정한뒤, hanhinsam 플러그인을 직접 빌드하여 호환 문제를 해결했다.
version: '3.7'
services:
es:
image: el:0.1 # 플러그인과 함께 빌드한 도커 이미지 사용
container_name: es
environment:
- node.name=es-node
- cluster.name=search-cluster
- discovery.type=single-node
- xpack.security.enabled=false
- xpack.security.http.ssl.enabled=false
- xpack.security.transport.ssl.enabled=false
ports:
- 9200:9200 # https
- 9300:9300 # tcp
networks:
- es-bridge
kibana:
image: docker.elastic.co/kibana/kibana:8.5.3
container_name: kibana
environment:
SERVER_NAME: kibana
ELASTICSEARCH_HOSTS: http://es:9200
ports:
- 5601:5601
# Elasticsearch Start Dependency
depends_on:
- es
networks:
- es-bridge
logstash:
image: docker.elastic.co/logstash/logstash:8.5.3
container_name: logstash
volumes:
- ./logstash/config/bingterpark.conf:/usr/share/logstash/pipeline/logstash.conf
ports:
- 5000:5000
- 9600:9600
environment:
- xpack.monitoring.enabled=false
networks:
- es-bridge
networks:
es-bridge:
driver: bridge
name: es-bridge
xpack과 관련된 기능은 필요하지 않아 설정 용이성을 위해 모두 꺼두었다.
- 로그스태시 연동 로그백 파일
// build.gradle 추가
implementation 'net.logstash.logback:logstash-logback-encoder:6.6'
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<!-- Console -->
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{10} - %msg%n</pattern>
</encoder>
</appender>
<!-- Logstash -->
<appender name="LOGSTASH" class="net.logstash.logback.appender.LogstashTcpSocketAppender">
<destination>localhost:5000</destination>
<encoder class="net.logstash.logback.encoder.LogstashEncoder">
</encoder>
</appender>
<root level="info">
<appender-ref ref="CONSOLE" />
<appender-ref ref="LOGSTASH" />
</root>
</configuration>
- 로그스태시 파이프라인 conf
input{
tcp {
port => 5000
codec => json_lines }
}
output {
elasticsearch {
hosts => ["es:9200"]
index => "logstash-%{+YYYY.MM.dd}"
}
}
로그스태시 파이프라인은 도커 볼륨으로 파일을 지정해주었다.
- 도커 컴포즈 실행 결과
- build.gradle 추가
// elasticsearch
implementation "org.springframework.boot:spring-boot-starter-data-elasticsearch"
- ElasticSearchConfig
@Configuration
public class ElasticSearchConfig extends ElasticsearchConfiguration {
@Override
public ClientConfiguration clientConfiguration() {
return ClientConfiguration.builder()
.connectedTo("localhost:9200") // elastic search 서버 주소
.build();
}
}
이것으로 ELK 스택 실행의 기본적인 준비는 끝마쳤다.