Elasticsearch
Elasticsearch는 Apache Lucene(아파치 루씬) 기반의 Java 오픈소스 분산 검색 엔진이다.
JSON 기반의 문서를 저장하고 검색할 수 있으며 문서들의 데이터를 기반으로 분석 작업도 할 수 있다.
Elasticsearch를 통해 루씬 라이브러리를 단독으로 사용할 수 있게 되었으며, 방대한 양의 데이터를 신속하게, 거의 실시간(NRT, Near Real Time)으로 저장, 검색, 분석할 수 있다.
Elasticsearch와 Relational DB 비교
MySQL과 같은 RDBMS는 테이블을 만들고 테이블에 각 필드를 미리 정의해야하지만, Elasticsearch는 스키마를 미리 정의할 필요가 없고 자동으로 해당 document를 분석한 뒤 document에 맞는 스키마를 동적으로 생성한다. 또한 새로운 필드가 추가될 경우에도 새로운 필드에 대한 스키마를 자동으로 생성해준다.
Relational DB | Elasticsearch |
Database | Index |
Table | Type |
Row | Document |
Column | Field |
Index | Analyze |
Primary key | _id |
Schema | Mapping |
Physical partition | Shard |
Logical partition | Route |
Relational | Parent/Child, Nested |
SQL | Query DSL |
Elasticsearch 특징
1. Scale out
- 샤드를 통해 규모가 수평적으로 늘어날 수 있음.
- 여기서 샤드는 Elasticsearch 데이터 저장공간과 같다. 인덱스는 기본적으로 샤드(shard)라는 단위로 분리되고, 각 노드에 분산되어 저장된다.
2. 고가용성
- 한 대 이상의 노드를 클러스터로 구성하고 Replica를 통해 데이터의 안정성을 보장
3. Schema Free
- Json 문서를 통헤
4. Restful
- 데이터 CURD 작업은 HTTP Restful API를 통해 수행하며, 각각 다음과 같이 대응한다.
Relational DB | Elasticsearch |
SELECT | GET |
INSERT | PUT |
UPDATE | POST |
DELETE | DELETE |
Elasticsearch 아키텍처와 기본 용어
1. 클러스터(Cluseter)
클러스터란 Elasticsearch에서 가장 큰 시스템 단위를 의미하며, 하나 이상의 노드로 이루어진 노드들의 집합이다. 서로 다른 클러스터는 데이터의 접근, 교환을 할 수 없는 독립적인 시스템으로 유지되며, 여러 대의 서버가 하나의 클러스터를 구성할 수 있고, 한 서버에 여러 개의 클러스터가 존재할수도 있다.
2. 노드(Node)
Elasticsearch를 구성하는 하나의 단위 프로세스이다.
역할에 따라 Master-eligible, Data, Ingest, Tribe 노드로 구분할 수 있다.
1) master-eligible node
클러스터를 제어하는 마스터로 선택할 수 있는 노드를 말합니다.
master 노드가 하는 역할은 인덱스 생성, 삭제 / 클러스더 노드들의 추적, 관리 / 데이터 입력 시 어느 샤드에 할당할 것인지 등이 있다.
2) Data node
데이터와 관련된 CRUD 작업과 관련있는 노드이다.
이 노드는 CPU, 메모리 등 자원을 많이 소모하므로 모니터링이 필요하며, master 노드와 분리되는 것이 좋다.
3) Ingest node
데이터를 변환하는 등 사전 처리 파이프라인을 실행하는 역할을 한다.
4) Coordination only node
data node와 master-eligible node의 일을 대신하는 이 노드는 대규모 클러스터에서 큰 이점이 있다.
즉 로드밸런서와 비슷한 역할을 한다고 보면 된다.
3. 인덱스(index), 샤드(Shard), 복제(Replica)
Elasticsearch에서 index는 RDBMS에서 database와 대응하는 개념이다.
shard와 replica는 Elasticsearch에만 존재하는 개념이 아니라, 분산 데이터베이스 시스템에도 존재하는 개념이다.
샤딩(sharding)은 데이터를 분산해서 저장하는 방법을 의미한다. 즉, Elasticsearch에서 Scale out을 위해 index를 여러 shard로 쪼갠 것이다. 기본적으로 1개가 존재하며, 검색 성능 향상을 위해 클러스터의 샤드 갯수를 조정하는 튜닝을 하기도 한다.
replica는 또 다른 형태의 shard라고 할 수 있다. 노드를 손실했을 경우 데이터의 신뢰성을 위해 샤드들을 복제하는 것이다. 따라서 replica는 서로 다른 노드에 존재할 것을 권장한다.
ElasticSearch 설치
Elasticsearch를 사용하기 위해선 java가 설치되어있어야 한다.
$ yum install java
$ java -version
CentOS일 경우 RPM을, 우분투와 같은 데비안 계열일 경우 https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.1.3-amd64.deb
를 활용한다.
$ wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-8.1.3-x86_64.rpm
$ rpm -ivh ./elasticsearch-8.1.3-x86_64.rpm
$ systemctl start elasticsearch
$ systemctl enable elasticsearch
$ systemctl status elasticsearch
elasticsearch.yaml 파일을 수정하지 않아도 아래 curl 명령이 잘 되는 경우 설정 파일을 굳이 수정하지 않아도 된다.
$ vi /etc/elasticsearch/elasticsearch.yaml
network.host: localhost
http.port: 9200
xpack.security.enabled: false
$ systemctl restart elasticsearch
curl로 Elasticsearch 실행이 잘 되는지 확인한다.
$ curl -s http://localhost:9200
Elasticsearch PUT, GET, POST, DELETE
1. 인덱스 생성
$ curl -X PUT "localhost:9200/[Index 이름]?pretty"
## example ##
$ curl -X PUT "localhost:9200/dabi?pretty"
2. 인덱스 조회, 인덱스 목록 확인
$ curl -s 'http://localhost:9200/_cat/indices?v'
3. PUT, POST: document 색인
일반적으로 생성에는 POST, 갱신에는 PUT 메소드를 사용하지만 ElasticSearch에서는 둘을 모호하게 사용한다.
## 데이터 직접 입력 ##
$ curl -X PUT 'localhost:9200/[Index 이름]/_doc/[document id]?pretty' -H 'Content-Type: application/json' -d '{[key]: [value]}'
$ curl -X POSTT 'localhost:9200/[Index 이름]/_doc/[document id]?pretty' -H 'Content-Type: application/json' -d '{[key]: [value]}'
## 데이터가 파일에 저장되어 있을 경우 ##
$ curl -X PUT 'localhost:9200/[Index 이름]/_doc/[document id]?pretty' -H 'Content-Type: application/json' -d @<파일명.json>
$ curl -X POST 'localhost:9200/[Index 이름]/_doc/[document id]?pretty' -H 'Content-Type: application/json' -d @<파일명.json>
## 예시 ##
$ curl -X PUT 'localhost:9200/dabi/_doc/1?pretty' -H 'Content-Type: application/json' -d '{"postname" : "elasticsearch", "category" : "IT"}'
$ curl -X POST 'localhost:9200/dabi/_doc/2?pretty' -H 'Content-Type: application/json' -d @test.json
• Index 이름 : 관계형 DB에서의 데이터베이스 이름과 같다.
• _doc : Type에 해당하며, 관계형 DB에서의 테이블과 같다. Elasticsearch 버전 5 이하에서는 멀티 type을 지원해서 하나의 인덱스 안에 다양한 Type의 데이터를 저장할 수 있었지만, 버전 6 이상에서는 하나의 인덱스에 하나의 타입만 저장할 수 있다. 따라서 고정자 _doc으로 접근해야한다.
• document id : id는 유일해야하며, 동일한 id가 입력되면 해당 document를 수정한다고 인식한다.
• -d : 추가할 데이터를 json 포맷으로 전달
• -H : 헤더 설정. json으로 전달하기 위해 application/json으로 설정함.
• ?pretty : 결과를 예쁘게 보여주도록 요청
4. GET: document 조회
## document 조회 ##
$ curl -X GET 'localhost:9200/[Index 이름]/[Type]/[document id]?pretty'
## example ##
$ curl -X GET 'localhost:9200/dabi/_doc/1?pretty'
5. PUT, POST: document 수정
PUT 사용 시 이미 존재하는 ID가 입력되면 해당 document를 update한다.
$ curl -X PUT 'localhost:9200/dabi/_doc/1?pretty' -H 'Content-Type: application/json' -d '{"postname" : "kibana", "category" : "IT"}'
다시 POST를 사용해서 kibana로 update한 postname을 elasticsearch로 변경해보자.
$ curl -X POST 'localhost:9200/dabi/_doc/1?pretty' -H 'Content-Type: application/json' -d '{"postname" : "elasticsearch", "category" : "IT"}'
6. mapping 확인
$ curl -s http://localhost:9200/[Index 이름]/_mappings?pretty
## examle ##
$ curl -s http://localhost:9200/dabi/_mappings?pretty
결과를 확인해보면 properties 내부에 색인한 document에 있었던 "category"와 "postname" 필드가 잘 정의되어있는 것을 확인할 수 있다. 그리고 둘 다 "text" 타입으로 정의된 것을 볼 수 있다.
"date" 필드를 새롭게 가진 document를 색인한 뒤, 스키마를 확인해보자
date 타입의 "date" 필드가 추가된 것을 볼 수 있다. 즉, 새로운 필드가 추가되면 동적으로 해당 필드가 색인되고 스키마도 추가로 정의되는 것을 알 수 있다.
하지만, 만약 정의되어있는 필드와 다른 타입의 값을 입력하게 되면 스키마 충돌이 일어나고, 에러가 나게 된다. 예를 들어, text 타입의 "postname" 필드에 숫자 값을 입력하면 스키마 충돌이 일어난다.
7. DELETE: 인덱스, 스키마 삭제
## 인덱스 삭제 ##
$ curl -X DELETE 'http://localhost:9200/user?pretty'
## document 삭제 ##
$ curl -X DELETE 'http://localhost:9200/user/_doc/1?pretty'
'ETC > ELK' 카테고리의 다른 글
Docker를 활용한 Filebeat, ELK stack 설치 및 Suricata 연동 (0) | 2021.10.08 |
---|---|
Docker를 활용한 filebeat, ELK stack 설치하기 (AWS EC2 Ubuntu 20.04) (0) | 2021.10.07 |