Tagged: 엘라스틱서치

Elasticsearch 보안 – 인증서

Elasticsearch 가 버전이 높아짐에 따라 인증서에 대한 이해가 필요하게 되었다. 사실 이 인증서가 필요한 이유가 Elastic 에서 배포하는 X-Pack 중에 Security 플러그인 때문인데, 이 Security 를 활성화 하게 되면 TCP, HTTP 통신을 TLS 통신을 하도록 강제하고 있다.

문제는 Elasticsearch 자바 기반이며, 따라서 생성하는 파일이 여느 다른 인증서와는 다른 면도 있다. ‘다른 면도 있다’ 라고 표현한 이유는 일반적인 PEM 형식의 보안키와 인증서를 모두 지원하지만 여전히 자바 세계에서만 통용되는 방법을 여전히 고수하고 있기 때문이다.

keystore 파일

최신 버전의 Elasticsearch 7 을 설치하게 되면 /etc/elasticsearch/elasticsearch.keystore 파일 하나만 생성되게 된다.

이 파일은 key/value 형식으로 계정 정보가 들어가 있다. 이 내용을 적는 이유는 Java Keystore 파일과는 다르다는 것을 말하기 위함이다. Elasticsearch 을 설치하고 나서 Security 를 활성한 후에 계정에 대한 패스워드를 작성하는 절차를 밟는다.

계정에 대한 패스워드를 자동 생성하도록 한 것인데, 이렇게 생성된 내용들은 elasticsearch.keystore 파일에 key/value 형식으로 저장된다.

이렇게 저장된 key 값들은 elasticsearch-keystore 명령어를 통해서 볼 수 있다.

PKCS#12(확장자 p12) 파일

확장자가 p12 파일을 보게 된다. 이 파일은 PKCS#12 형식의 파일인데, 인증서와 개인키를 포함한 형태의 데이터 파일이다. Elasticsearch 7 에서는 루트 인증서(CA 인증서) 와 서버 인증서를 다음과 같이 제작해 사용 한다.

elastic-stack-ca.p12 은 CA 인증서 인데, openssl 을 이용해서 PKCS12 파일을 읽어볼 수 있다.

패스워드를 입력하지 않았기 때문에 패스워드 입력 문구에서는 그냥 Enter 를 치면 된다. 그러면 위와같이 Private Key, Certificate 내용이 나온다. Certificate 부분을 따로 때어내서 파일로 저장하고 Openssl 명령어를 이용해 인증서를 읽으면 다음과 같다.

CA:TRUE 라고 명백하게 나오고 있다.

그러면 CA 인증서를 가지고 만들어진 /usr/share/elasticsearch/elastic-certificates.p12 파일도 내용을 확인해 보자.

위 내용을 보면, Private Key 1개, Certificate 2개 로 나온다. 이건 인증서 체인 파일인게 분명하다. Certificate 부분만 따로 때어서 보면 다음과 같다.

확인 결과, 하나는 인증서이고 하나는 CA 인증서인 것으로 확인된다. 그러니까 elastic-certificate.p12 파일은 Private Key, CA 인증서, 서버 인증서 이렇게 3가지를 모두 가지는 파일이다.

PEM 형식 파일

Elasticsearch 에서는 PEM 형식의 파일도 함께 지원 한다. PEM 형식은 가장 흔하게, 널리 사용되는 인증서 파일 포맷 형식이다. elasticsearch-certutil 명령어를 이용해서 작성할 수 있다.

위와같이 zip 파일 형태로 생성된다. 압축을 해제하면 다음과 같이 파일이 생성된다.

ca 디렉토리가 생성되는데, 보면 Private Key 파일과 CA 파일이 별도로 생성된 것을 알 수 있다.

이렇게 작성된 파일을 가지고 서버 인증서를 다음과 같이 생성할 수 있다.

역시나 압축된 형태의 파일로 출력이 된다. 압축을 해제해 보자.

instance.crt 인증서 파일의 내용을 살펴보자

서버 인증서임을 알수 있다.

인증서 활용

PKCS#12 형식과 PEM 형식의 인증서를 활용하는 방법은 다르다.

PKCS#12 형식은 다음과 같이 설정 한다.

PEM 형식은 다음과 같다.

SAN 인증서

지금까지 설명한 방법으로 인증서를 작성할 경우에 한가지 문제가 있을 수 있다. 이 인증서들은 SAN 인증서가 아니기 때문에 모든 도메인에서 통용될 수 있다. 앞에 인증서 내용을 보면 SAN 이 없다. 하지만 SAN 인증서라야만 하는 보안성을 요구된다면 SAN 인증서를 만들어 사용해야 한다.

SAN 인증서를 작성할때에 주의 사항은 Elasticsearch Stack 에서 사용할 모든 도메인, 혹은 IP 주소를 기재해야 한다. 그렇지 않으면 절대로 통신을 할 수가 없게 된다.

먼저, CA 인증서가 필요하다. 이 CA 인증서는 앞에 PEM 형식의 CA 인증서를 만들고 압축을 해제해 놓는다. 그리고 다음과 같이 instance.yml 파일을 작성한다.

이 파일에서 ip, dns 항목이 보이는데, 둘 중 하나만 있어도 된다. 어짜피 인증서에서 SAN 항목에서 IP Address, DNS 둘중하나가 들어가 있고 매칭이되면 인증서를 쓸 수 있다.

이제 다음과 같이 인증서를 작성해 생성한다.

정상적으로 생성이 되었을 것이다. 압축을 해제해 보자

instance.yml 파일에서 이름부분이 디렉토리로 생성되면서 각각 인증서와 key 값이 생성되어 있다. 이 인증서들은 SAN 부분이 instance.yml 에 따라서 하나의 IP, 하나의 DNS 만 들어가 있다.

SAN 이 뭔지를 안다면 굳이 이렇게 다 분리할 필요는 없다는 생각을 하게 된다. 멀티도메인 인증서를 사용하면 도메인에 *.systemv.local 처럼 생성하면 될 것이고, 그러면 하나의 인증서를 가지고 여러곳에서 함께 사용이 가능해 진다. 위 예제에서는 각각의 용도에 맞게 딱 1개의 도메인과 IP 에 한해서 허용하도록 작성되었을 뿐이다.

PEM 형식의 Key 는 PKCS#12 형식으로 사용해야할 때가 있다. 이때는 다음과 같이 openssl 명령어를 이용해서 변환할 수 있다.

로그 저장과 트래킹

로그(log) 는 각종 시스템과 소프트웨어 프로그램의 정보를 담고 있다. 한 사람이 하나의 시스템, 하나의 소프트웨어 프로그램을 다루거나 관리를 한다면 별 문제가 없겠지만 요즘 처럼 분산형 시스템과 소프트웨어를 사용하는 시대에 로그를 하나씩 다 들여다 본다는 건 불가능이다.

거기다 로그를 본다는 것도 여간 쉬운일이 아니다. 매우 지루하고 많은 시간을 허비해야 하는데, 수 많은 로그속에서 내가 필요로하는 정보를 찾기란 매우 어렵다.

그래서 이것을 손쉽게 처리할 수 있도록 도와주는 프로그램 그룹이 만들어졌는데, 다음과 같은 것이다.

Splunk

스플렁크(Splunk) 는 사용 소프트웨어다. 대량으로 로그를 저장하고 분석하도록 해주는 소프트웨어를 판매하는 회사다. 상용제품이다 보니까 이 제품을 익히는게 중요하다. Splunk Search Processing Language, 줄여서 SPL 을 이용해서 로그에서 필요한 정보를 뽑아 낼 수 있다.

ELK(Elasticsearch, Logstash, Kibana)

Elastic 제품군이다. 엘라스틱서치(Elasticsearch) 검색 소프트웨어로 유명한 Elastic 에서 만드는 것인데, 로그스태쉬(Logstash) 는 실시간으로 로그를 전달 받아서 처리하고 이것을 엘라스틱서치에 저장한다. 키바나(Kibana) 는 엘라스틱서치에 저장한 로그들을 특저한 쿼리를 이용해 시각화 해준다.

로그스태쉬(Logstasch) 대신 플로언트디(FluentD) 를 사용하기도 한다. 로그스태쉬로그스태쉬(Logstasch)보다 메모리를 덜 먹으면서도 가용성이 좋다.

로그 처리를 위한 ELK 를 스택(Stack) 이라고 명명하고 ELK Stack, EFK Stack 이라고 부른다.

ELK stack components

TICK(Telegraf, InfluxDB, Chronograf, Kapacitor)

InfluxDB 와 Telegraf 로 유명한 InfluxData 에서 만든 것이다. Kapacitor 는 ELK 에서 로그스태쉬에 해당한다. Chronograf 는 ELK 의 키바나에 해당된다.

개인적으로 Telegraf, InfluxDB, Grafana 를 이용한 시스템 모니터링은 여러번 사용해본 경험이 있다. InfluxDB 는 마치 RDBMS 처럼 SQL 문을 이용해서 데이터를 조회할 수 있다.

ElasticSearch 7.13 기반 책 리뷰

오래전에 “시작하세요! 엘라스틱서치” 라는 책을 구매해 본적이 있다. 지금도 소장하고 있는데, 엘라스틱서치에 대한 기본적인 개념을 익히는데 손색이 없는 책이라 평가하고 싶다. 단, 내가 볼때에 엘라스틱서치에 버전이 6.4 이다 보니 없어져버린 기능들은, 예를들어 펫싯, 볼 필요가 없었다.

오늘은 최신의 ElasticSearch 7.13 버전에서 이 책에 내용을 한번 살펴보고자 한다. 엘라스틱서치는 버전이 올라감에 따라 변경된 부분이 상당히 많아진다는 점을 생각해보면 꽤 도움이 될법한 내용들이라 생각한다.

엘라스틱서치의 데이터 구조 – 타입(Type) 없어짐

엘라스틱서치의 데이터 구조를 설명에서 인덱스(Index), 타입(Type), 도큐먼트(Document) 단위로 이루어진다고 설명했다. 하지만 엘라스틱서치 7.x 로 버전이 높아짐에 따라 타입은 이제 없다. 이에 대해서 엘라스틱서치 개발사에서 다음과 같은 페이지를 제공해 설명해 주고 있다.

위 문서를 보면 예를들어서 타입이 뭔지 설명하고 있으며 왜 없앴는지 타입을 이용했던 방법의 대안은 무엇인지 상세히 설명해 주고 있다.

그런데, 과연 타입(Type) 은 없어졌을까?

PUT 메소드 대신 POST 그리고 Content-Type 지정

책에 다음과 같은 예제가 나온다.

하지만 위와 같이 오류가 발생한다.

다음과 같이 Header 에 json 컨텐츠 타입을 지정해 줘야 한다.

앞서 매핑 타입이 없어졌다고 했지만 데이터를 입력하면 잘 들어 간다. GET 메소드를 이용한 조회도 잘 된다. 하지만 이것은 한가지 트릭과 같은데, 매핑에는 타입이 안나온다.

매핑 결과를 보면 타입(Type) 이 안나온다.

hotels 매핑 오류

책에는 hotels 인덱스 생성을 위해서 매핑(Mapping) 을 먼저 작성해 주는데 다음과 같다.

“Root mapping definition has unsupported parameters” 위와같이 오류가 발생 한다. 타입이 문제가 되는 경우라고 볼 수 있다. 위 내용을 수정하면 다음과 같다.

  • 매핑 타입 제거
  • string 타입을 제거하고 text 로 대체
  • not_analyzed 를 false 로 대체
  • dateOptionalTime 을 date_optional_time 으로 변경

성공적으로 생성 됐다.

Bulk 데이터 임포트

대량의 데이터를 엘라스틱서치에 입력할때에는 벌크(Bulk) api 를 이용한다. 매핑의 타입이 없기 때문에 타입을 제거해야 한다.

그리고 벌크 API 를 이용할때에는 다음과 같은 Content-Type 을 입력해줘야 한다.

위와같이 application/x-ndjson 을 지정해 줘야 한다.

ElasticSearch Nodes

ElasticSearch 는 노드(node) 로 불리운다. Node 는 ElasticSearch 의 독립된 인스턴스다. 그런데, 이 Node 에는 역할이 있으며 어떻게 Node 에 역할을 부여하는지에 해서 알아본다.

Node Type

Master Node

마스터 노드(Master Node) 는 ElasticSearch 의 클러스터(Cluster) 전체를 총괄하는 역할을 맡는다. ElasticSearch 는 분산검색엔진이며 각 노드들은 특정한 일을 하기 위한 하나의 그룹내의 멤버들로 관리되는데 이렇게 ‘하나의 그룹’ 을 클러스터라고 한다.

클러스터내에 노드들의 상태를 점검하고 이들의 유기적인 통제를 해야할 필요가 있는데, 이러한 역할을 하는 것이 바로 마스터 노드이다.

ElasticSearch 의 공식 문서에 보면 ‘Master Eligible Node’ 라는 말이 나온다. ‘마스터를 수행할만한 노드’ 정도로 해석되는데, 쉽게말하면 ‘마스터 후보군’ 이다. 이는 마스터 후보군이 존재하며 여기서 단 하나의 마스터가 선출되어 동장하고 만일 선출된 마스터가 장애를 겪는다면 마스터 후보군중에서 다른 마스터를 선출하게 된다.

Data Node

ElasticSearch 클러스터에서 실질적인 데이터를 저장하고 데이터 관련 연산을(Search, Aggregation 등) 수행하는 노드다.

샤드(Shard) 라는 개념이 바로 이 노드에 존재한다.

Ingest Node

파이프라인 스트림(Pipeline Stream) 이라고 한다. 문서를 인덱싱하기 전에 문서를 변형하는 역할을 수행 한다. 만일 각 노드에 대한 모니터링 기능을 켜게되면 반드시 Ingest Node 가 필요하게 된다.

Coordinating Node

코디네이팅 노드는 외부의 요청을 받아서 내부의 마스터 노드에 전달해준다. 벌크 인덱싱, 검색단계 줄이기등의 역할을 수행하기도 한다.

하나의 노드가 여러개의 역할을 중복해서 수행 가능하다. 그래서 개발을 위한 ElasticSearch 는 오직 하나의 노드만으로 모든 것을 할 수 있다.

 

Communication with Nodes

ElasticSearch 내에 노드들끼리는 TCP 통신을 기반으로 한다. 외부에 검색 쿼리(Query) 요청은 Http 통신을 기반으로 한다.

이제 여기서 생각을 해보자. 코디네이텅 노드의 역할을 분리해서 별도로 운영해야하느냐 하는 문제이다. 만일 코디네이텅 노드가 없을 경우에는 마스터 노드가 검색쿼리 요청을 받아야 하는 상황이 된다.

ElasticSearch 아키텍쳐1
ElasticSearch 아키텍쳐1

하지만 만일 코디네이팅 노드가 추가 된다면 다음과 같다.

ElasticSearch 아키텍쳐2
ElasticSearch 아키텍쳐2

뭘 하던간에 동작하는데에는 아무런 문제가 없지만 첫번재 아키텍쳐에서는 ELB 가 마스터 노드의 상태를 체크하고 잘못된 마스터 노드에 대해 제외를 시켜줘야 한다.

두번째 아키텍쳐에서는 ELB가 마스터 노드를 직접 제어하는 대신에 코디네이팅 노드를 제어한다.

유연성 측면에서 봤을때는 두번째 아키텍쳐가 더 좋아보이지만 그렇다고 딱히 아키텍쳐1번도 유연성에 문제가 있어보이지는 않는다.

Kibana 를 포함한 전체 아키텍쳐

Kibana 를 포함한 전체 아키텍쳐
Kibana 를 포함한 전체 아키텍쳐

Kibana 를 운영하기 위해서는 Ingest 노드가 필요하게 된다. 코디네이팅 노드를 포함하면 적어도 8개, Kibana 를 포함하면 9개 노드가 필요하게 된다.