MEMO

[Docker] docker-compose 를 이용해 ELK 구축하기 ( + mySql, Nori) 본문

Docker

[Docker] docker-compose 를 이용해 ELK 구축하기 ( + mySql, Nori)

by_dev 2020. 3. 20. 19:55

회사에서 개발하고 있는 서비스에 사용자가 늘어나다 보니 검색엔진의 구축의 필요성이 증가하면서, Elasticsearch 를 도입해보기로 하였다. 한번도 Elasticsearch 를 사용해본적이 없어서 조금이나마 간편하게 구축할 방법인 docker 를 이용해서 구축한 후 local 에서 테스트를 해보기로 하였다.

 

1. ELK ?

Elasticsearch, Logstash, Kibana 오픈 소스 프로젝트 3개를 합쳐서 ELK 라고 한다. Elasticsearch 는 검색 및 분석 엔진으로 무료버전으로도 기본적인 기능은 충분히 사용가능하다. Logstash는 여러 소스에서 동시에 데이터를 수집하여 변환한 후 Elasticsearch 와 같은 곳에 'stash'로 전송하는 서버 사이드 데이터 처리 파이프라인을 말한다. Kibana 는 사용자가 Elasticsearch 를 시각화하여 사용할수 있는 툴이다.

여기서는 이미 사용하고 있는 docker 기반 mySql 을 Elasticsearch 에 logstash 를 이용해 동기화 하고, 검색하는 부분만 포스팅할 예정이다.

 

2. Nori ?

한글 검색을 올바르게 수행하기 위해서는 형태소 분석기 plug-in 을 Elasticsearch 에 따로 설치해주어야 하는데, 다른 다양한 형태소 분석기들도 많지만 필자는 Elasticsearch 공식문서를 보면서 작업하기 수월하기 위해 Nori 형태소 분석기를 사용하기로 하였다. nori는 elasticsearch 가 실행된 상태에서 해당 bash 에 접속해 설치하면 된다.

$ docker exec -it elasticsearch /bin/bash 
$ bin/elasticsearch-plugin install analysis-nori #elasticsearch container 에서 명령

nori를 이용한 검색을 해야하는 데이터 컬럼에 대해서는 반드시 mapping analyzer 셋팅을 해주어야 한다. 예를들어 'name'이라는 column 에 형태소 분석을 이용한 한글검색이 가능하게 하고자 한다면 mapping 은 다음과 같은 형태일 수 있다.

 "name": {
          "type": "text",
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          },
          "analyzer":"nori_analyzer"
        }

 

3. docker-compose

version: '3.2'
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.6.1 #기본 이미지 사용
    container_name: elasticsearch
    environment:
      ES_JAVA_OPTS: "-Xmx256m -Xms256m"
      discovery.type: single-node #간단한 local 테스트를 위해 single-node로 구성
    volumes:
      - /usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elk
  logstash:
    container_name: logstash
    image: docker.elastic.co/logstash/logstash:7.6.1
    environment:
      LS_JAVA_OPTS: "-Xmx256m -Xms256m"
    volumes:
      - type: bind
        source: ./config/logstash/config/logstash.yml
        target: /usr/share/logstash/config/logstash.yml
        read_only: true
      - type: bind
        source: ./config/logstash/pipeline
        target: /usr/share/logstash/pipeline
        read_only: true
      - ./jar/mysql-connector-java-8.0.18.jar:/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-8.0.18.jar #mysql 사용을 위한 jdbc-connector 다운
    networks:
      - elk
    depends_on:
      - elasticsearch #elasticsearch 가 실행된 이후 logstash 실행되도록 depends_on 설정
  kibana:
    container_name: kibana
    image: docker.elastic.co/kibana/kibana:7.6.1
    ports:
      - 5601:5601
    networks:
      - elk
    depends_on:
      - elasticsearch #elasticsearch 가 실행된 이후 kibana 실행되도록 depends_on 설정
    
networks:
 elk:
  external:
    name: mysql-network #이미 사용하고 있는 db와 연결을 위해 mysql-docker network 와 연결이 되도록 external 설정을 따로 해주었다. 

volumes:
 elasticsearch: #volume container 사용
    

 

이미 떠있는 mysql container 와의 연결을 위해 external network 설정을 따로 해주었으나, 만약 elk 구축과 함께 database 를 실행한다면 external 연결은 해줄필요가 없다. 기본적인 ELK 설정을 거이 따르고 있으며 여기서는 mysql 연결을 위한 부분과 single-node 사용하는 부분만 수정하였다.

4. mysql 과 동기화 작업 설정

동기화 하고 싶은 데이터가 있다면 logstash.conf 파일에서 설정해주면 된다. 여기서는 crontab 과 수정일을 이용하여 마지막 데이터를 동기화해 가지고 오도록 작업하였다.

input {
  jdbc {
    jdbc_driver_library => "/usr/share/logstash/logstash-core/lib/jars/mysql-connector-java-8.0.18.jar"
    jdbc_driver_class => "com.mysql.jdbc.Driver"
    jdbc_connection_string => "jdbc:mysql://[mysql-container-name]:[mysql-container-host]/allpal?useUnicode=true&characterEncoding=utf8&serverTimezone=Asia/Seoul&autoReconnect=true"
    jdbc_user => "[mysql-id]"
    jdbc_password => "[mysql-password]"

    columns_charset => {
      "[한글데이터를 가지고 있는 column 명]" => "UTF-8"
    }

    statement => "SELECT *, UNIX_TIMESTAMP(modification_time) as unix_ts_in_secs FROM [table name] WHERE 
    (UNIX_TIMESTAMP(modification_time) > :sql_last_value AND modification_time < NOW())"

    jdbc_paging_enabled => true
    use_column_value => true
    tracking_column => "unix_ts_in_secs"
    tracking_column_type => "numeric"
    clean_run => true
    schedule => "*/5 * * * * *"  # crontab 표기법의 스케쥴 설정
  }
}

output {
  elasticsearch {
    hosts => "elasticsearch:9200"
    index => "[index명]"
    document_id => "%{_id}"
  }
  stdout {
    codec => rubydebug
  }
}

[대괄호]안에 있는 부분들은 해당 상황에 맞게 입력하면 되는 값이며, 여기서는 위에서 언급한것처럼 modification_time 이라는 수정일 컬럼을 이용하여 동기화하였다. 새로 추가되거나, 수정/삭제 된 경우에도 데이터가 자동으로 동기화 되기 위해서 다음과 같이 작업을 진행하였다.

 

각 환경에 맞게 수정한 docker-compose.yml 파일과 logstash.conf 등 설정파일들 준비가 완료되었다면 docker-compose.yml 파일이 있는 디렉토리에서 docker-compose up 을 통해 해당 파일이 실행되는것을 확인할 수 있으며, localhost:5601 에 접속하여 kibana 에서 편하게 실제 index가 들어간 모습과, mapping 등을 확인할 수 있다.

 

 

 

Reference

1 :: https://github.com/deviantony/docker-elk

2.1 :: https://docs.docker.com/compose/compose-file/

2.2 :: https://docs.docker.com/compose/reference/overview/

3 :: https://www.elastic.co/kr/blog/nori-the-official-elasticsearch-plugin-for-korean-language-analysis

3.1 :: https://www.elastic.co/guide/en/elasticsearch/plugins/6.4/analysis-nori.html

4 :: https://www.elastic.co/guide/en/logstash/current/plugins-inputs-jdbc.html

5.1 :: https://www.elastic.co/guide/en/elasticsearch/client/java-rest/current/java-rest-high-search.html

기본적인 elastic search query :: https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl.html

Comments