무신사의 엘라스틱서치 MusE (Musinsa Elasticsearch) — 10분만에 만드는 엘라스틱서치 클러스터

HeeJung Jane Hwang
MUSINSA tech
Published in
23 min readDec 21, 2022

안녕하세요. 무신사 검색플랫폼팀 황희정입니다. 검색플랫폼팀은 검색 인프라와 주요 기능을 플랫폼화 및 고도화하여 무신사 개발 조직과 자회사에서 검색 기술과 기능을 잘 활용할 수 있도록 하는 업무를 하고 있습니다. 오늘은 제품 개발팀이 쉽게 엘라스틱서치를 사용할 수 있도록 하기 위해, 저희 팀이 만든 뮤즈(MusE, Musinsa Elasticsearch)라는 플랫폼에 대해서 소개드리려고 합니다.

엘라스틱에 대한 수요가 늘어나다!

엘라스틱 에코시스템은 데이터의 수집, 검색, 분석을 위한 검색 플랫폼입니다. 초당 수천/ 수만 건의 대용량 데이터를 준실시간(Near Real-Time)으로 수집, 분석하며 시각화까지 가능합니다. 분산 처리 기반으로 고가용성이 지원되며 쉬운 확장성이 있는 플랫폼입니다. 엘라스틱서치는 자연어 검색이 가능하여 무신사 서비스 내에서도 자연어 검색뿐만 아니라 검색 결과의 순위 집계 및 사용자 검색 기반 데이터를 활용한 인기 검색어, 이미지 검색, 애플리케이션 로그 검색 등에 다양하게 활용하고 있습니다.

무신사 내에서 엘라스틱서치 사용 예

무신사에서 검색엔진을 활용한 자연어 검색
무신사에서 검색엔진을 활용한 자연어 검색
무신사에서 검색엔진을 활용한 필터 내 복잡한 검색
무신사에서 검색엔진을 활용한 필터 내 복잡한 검색

이렇게 강력한 엘라스틱서치의 기능은 주로 무신사 내에서 통합 검색 및 어플리케이션 로그 검색을 위해서 무신사 내 일부 팀에서만 사용 했었습니다. 하지만, 무신사 내에서 회원 후기팀, 스냅팀 등 많은 팀에서도 엘라스틱서치의 기능을 이용해서 제품을 개발하고 싶어 하는 요구사항이 늘어가고 있었습니다.

무신사 검색 인프라 구성의 역사 및 한계

무신사 검색 인프라는 초기에 엘라스틱서치 5.x 버전부터 현재는 엘라스틱 8.x 버전까지 안정적인 검색 시스템을 만들기 위해서 계속 고민 하고 개선하면서 4개의 버전을 거쳐서 현재의 검색 시스템을 만들었습니다. 무신사의 검색 시스템 구성에 대한 역사에 대해서 간략히 설명하도록 하겠습니다.

v1 : 초기의 무신사의 엘라스틱서치 구성

무신사에서 초기 버전의 엘라스틱서치는 AWS EC2(Amazon Elastic Compute Cloud, EC2)에 설치해서 사용했습니다. 검색 서버는 총 3대의 서버(엘라스틱서치 노드)를 1개의 클러스터로 연결하여 사용했었습니다. 검색 클러스터는 총 3대의 검색 노드로, 데이터 노드에 마스터의 롤까지 정의하여 사용하였습니다.

당시 엘라스틱서치의 가비지 컬렉션의 기본 방식은 CMS GC(Concurrent Mark Sweep Garbage Collection)이었습니다. 가비지 컬렉션이란 쓸모 없어진 메모리를 자동으로 관리하는 방식이며 가능한 한 많은 메모리를 확보하기 위한 과정입니다. 가비지 컬렉션을 실행하기 위해서는 일시 중지(Stop The World)를 하고 GC 과정에 필요한 스레드를 제외한 모든 스레드가 작업을 중지한 후에 JVM에서 GC를 실행합니다. 이때 사용하던 검색엔진은 CMS GC(Concurrent Mark Sweep Garbage Collection)를 사용하는 검색엔진이다 보니 GC가 발생하면 Stop the world가 빈번하게 발생하였으며, 검색서비스에도 영향을 주어 검색의 결과가 잘 나오지 않는 문제를 해결해야만 했습니다.

무신사 초기 시절 엘라스틱서치 구성 예

v2: 역할에 맞는 엘라스틱서치 노드의 구성 및 형태소 분석기 적용

v2로 업그레이드하며 엘라스틱서치 7.x로 넘어가게 되었으며, 가비지 컬렉션 방식이 G1GC로 변경되어 GC를 수행하기 위해 JVM이 애플리케이션 실행을 멈추는 스탑더월드(STW, Stop The World) 시간이 많이 줄었습니다.

또한 엘라스틱서치 클러스터의 구성을 노드(node)별 역할에 맞게 설정 했습니다.

엘라스틱서치의 노드(node)란 서버 1대라고 생각하면 쉽습니다. 엘라스틱서치의 노드별 역할은 다음과 같습니다.

  • 마스터(master) 노드 : 클러스터의 전반적인 작업을 처리하는 역할을 하는 노드입니다. 예를 들면, 엘라스틱서치의 데이터를 담고 있는 인덱스 생성 및 삭제 및 물리적으로 데이터를 적절하게 분산해서 저장하도록 샤드 분배를 결정합니다.
  • 데이터(data) 노드 : 데이터를 가진 노드입니다. 데이터 저장(색인)하거나 검색(쿼리) 기능을 수행(CRUD 작업)을 하며 및 집계 작업이 가능하도록 하는 노드입니다.
  • 코디네이팅(coordinating) 노드 : 클러스터의 상태를 확인해서 사용자의 요청을 적절한 노드로 보내도록 라우팅을 하는 로드밸런서(LB) 역할을 하는 노드입니다. 엘라스틱서치의 노드에 모든 데이터 노드에 검색을 분산하고 결과를 집계해서 사용자에게 검색 결과를 반환을 합니다.

하나의 클러스터에 마스터 노드, 데이터 노드, 코디네이팅 노드로 역할을 분담해서 엘라스틱서치의 클러스터를 효율적으로 운영할 수 있게 구성했습니다. 또한, 정교한 자연어 검색 기능을 지원하기 위해서 무신사의 커스텀 형태소 분석기를 AWS EC2(Amazon Elastic Compute Cloud, EC2)에 설치했습니다.

역할에 맞는 엘라스틱서치 노드의 구성 및 형태소 분석기 적용 예

v3 : EC2기반의 서비스별 클러스터 분리

무신사의 규모가 커지면서 서비스별로 클러스터를 분리하기 시작했습니다. 예를 들면, 무신사 스토어, 무신사 통합 검색, 애플리케이션 로그 전용 엘라스틱서치 클러스터로 분리를 했습니다. 이렇게 서비스별 독립적인 클러스터를 만들면서 하나의 클러스터에 이상이 있어도 다른 클러스터에는 영향을 끼치지 않게 구성할 수 있었고, 엘라스틱서치의 클러스터의 CPU나 메모리 등을 트래픽 및 각 용도에 맞게 독립적으로 세팅할 수 있었습니다. 또한 노드 속성으로 데이터를 저장하는 샤드의 위치를 사용자가 직접 할당을 지정할 수 있는 속성(shard allocation awareness)을 사용하여 검색엔진 내에서도 검색 노드의 용도를 나누고, 특정 서비스의 트래픽이 증가 시 다른 서비스에 영향이 가지 않도록 하였습니다. AWS의 Lambda 서비스를 활용하여 오토스케일링을 구현함으로써 코디네이팅 노드 및 데이터 노드의 유연하게 동작하는 형태로 운용했습니다.

엘라스틱서치 생성 방법에 대한 고민

검색 인프라 시스템 구성을 직접 구성하는 것은 서비스별로 엘라스틱서치 클러스터들을 만들기 위해서 인프라 작업 및 엘라스틱서치 설정을 여러 서버에 반복적으로 작업을 해야 하는 불편한 점이 있고, 시간이 많이 들었습니다. 하나의 엘라스틱서치 클러스터를 생성하기 위해서는 AWS 인프라 와 엘라스틱서치의 설정 작업이 필요했습니다. AWS 인프라 작업은 AWS EC2 서버 생성, 도메인 설정, 방화벽 설정, 로드밸런서(LB) 설정이 있습니다. 엘라스틱서치 설정 작업은 한국어 형태소 분석기 및 커스텀 엘라스틱서치 분석기 설치, 동의어 사전 설정 등의 추가적인 작업이 필요했습니다. 하나의 클러스터는 여러 대의 노드로 구성해서 사용하기 때문에 하나의 엘라스틱서치를 구성하기 위해서는 여러 대의 서버에 설정이 필요했습니다. 이때문에 하나의 엘라스틱서치 클러스터를 만들기 위해서는 약 2주 간의 시간이 필요했습니다. 내부적으로 엘라스틱서치를 사용하고 싶은 팀의 엘라스틱서치 세팅에 대한 요구사항은 많아짐에 따라, 효율적인 엘라스틱 서치 클러스터 생성 방안이 필요해졌습니다.

직접 호스팅을 하기 보다는, 각 클라우드(AWS, Elasticsearch, ECK)가 제공하는 클러스터 처리 과정을 생성할 수 있는 방법을 활용해보기로 했습니다. 각 클라우드(AWS, Elasticsearch, ECK)에서 제공하는 엘라스틱서치에 대한 장단점을 비교 분석해서 무신사에서 사용할 적합한 케이스를 찾아 보았습니다.

AWS OpenSearch

AWS(Amazon Web Services, 아마존에서 제공하는 클라우드)에서 제공하는 엘라스틱서치입니다.

Amazon OpenSearch Service는 인프라 관리, 모니터링 및 유지 관리를 클러스터 운영에 대해서 쉽게 할 수 있는 AWS에서 제공하는 관리형 서비스입니다.

  • 장점 : Amazon OpenSearch Service 콘솔을 클릭하면 새로운 도메인을 생성하고, 도메인에 할당할 인스턴스 수, 인스턴스 유형 및 EBS 볼륨을 지정할 수 있습니다.
  • 단점 : 한국어 오탈자 및 자소분해 등을 위한 커스텀 플러그인 적용이 불가합니다. 예를 들면 초성 검색 등의 기능을 제공하려면 커스텀 플러그인을 설치 해야 합니다. 또한 AWS OpenSearch Service에서는 한국어 분석기의 경우 엘라스틱사에서 제공하는 공식 한국어 플러그인인 nori를 제공하지 않고, 은전한닢이라는 분석기를 기본적으로 제공하고 있습니다. 또한, AWS OpenSearch Service의 경우 엘라스틱서치 버전에 대해서 제약이 있습니다. 2022년 11월 기준으로, 엘라스틱서치의 클러스터를 신규로 생성 시 엘라스틱서치 버전을 6.8과 7.10만 제공하고 있습니다 엘라스틱서치의 OSS 버전의 7.10을 마지막으로 자체적으로 구축이 되었으며, 벡터 검색 및 엘라스틱사에서 제공하는 유료 기능의 일부를 무료로 사용할 수 있습니다. 현재는 OpenSearch 2.4 버전까지 출시되어 안정화 단계에 들어갔습니다.

엘라스틱 클라우드 (Elastic Cloud)

엘라스틱 클라우드는 엘라스틱사에서 제공하는 공식 SasS 형태의 엘라스틱서치입니다.

  • 장점 : 엘라스틱서치의 클러스터 운영을 오버헤드(어떤 처리를 하기 위해 들어가는 간접적인 처리 시간 · 메모리 등)가 없이 엘라스틱 클라우드에서 쉽게 엘라스틱서치를 운영할 수 있습니다. 또한, 시스템에 문제가 있을 경우 엘라스틱사의 공식 기술 지원이 가능하다는 점입니다.
  • 단점 : 직접 엘라스틱서치를 설치해서 사용하는 것 보다는 비용이 비싸다는 점입니다. 또한, 무신사 내부적으로 조금 더 유연하게 운영하기에는 한계점이 있었습니다.

ECK (Elastic Cloud on Kubernetes)

엘라스틱서치사에서는 쿠버네티스(Kubernetes, K8s) 환경에서 엘라스틱서치(Elasticsearch)와 키바나(Kibana)를 설정하고 관리하도록 지원하는 ECK(Elastic Cloud on Kubernetes)라는 플랫폼을 제공하고 있습니다. 쿠버네티스(Kubernetes, K8s)는 컨테이너화된 애플리케이션 배포 및 확장 관리를 자동화하기 위한 오픈소스 기반의 플랫폼입니다. 쿠버네티스를 활용하면 컨테이너화된 애플리케이션을 원하는 장소와 시간에 실행할 수 있고 자동화된 롤아웃 및 롤백, 서비스 검색 및 로드 밸런싱, 수평적 확장 등의 기능을 사용할 수 있습니다. ECK를 사용하면 쿠버네티스 환경에서 엘라스틱서치 및 키바나 등의 솔루션을 보다 쉽게 배포하고 실행할 수 있습니다.

ECK를 사용하면 AWS, GCP, Azure 등 원하는 클라우드에서 직접 쿠버네티스에 엘라스틱서치를 구성해서 사용하는 것이 가능합니다. 비용적인 측면에서 AWS OpenSearch Service 엘라스틱 클라우드보다는 저렴하며, 빠르게 확장 가능하고 플러그인 설치, 사전 동기화 등 무신사 내에서 필요한 엘라스틱서치에 대한 기능을 쉽게 하게 사용할 수 있습니다. 이러한 장점 덕분에 무신사에서 엘라스틱서치 클러스터를 구성하기 위해 ECK가 가장 적합한 방법이었습니다.

무신사에서는 이미 AWS를 사용하고 있고, 또한 Amazon EKS라는 관리형 Kubernetes 서비스를 사용하고 있었기 때문에 최종적으로는 ECK (Elastic Cloud on Kubernetes)를 사용하기로 결정했습니다.

ECK (Elastic Cloud on Kubernetes)

엘라스틱서치 생성 방법 비교

위에서 언급했던 엘라스틱서치 생성 방법들을 아래의 표로 간략하게 아래와 같이 비교했습니다.

클라우드별 엘라스틱 서치 생성방법 비교
클라우드별 엘라스틱서치 생성 방법 비교

MusE(Musinsa Elasticsearch) 검색 플랫폼 소개

패션용어인 Muse(뮤즈)는 특정 디자이너가 자신의 옷을 입히기에 가장 이상적으로 생각하는 모델을 의미합니다. 검색플랫폼팀에서는 ECK라는 기술을 사용하여, 각 제품팀이 원하는 요구사항을 충족하는 이상적인 검색엔진을 구축했고, 이 검색 엔진의 이름을 MusE, 즉 Musinsa Elasticsearch로 지었습니다. MusE 플랫폼은 무신사 전사 로그 적재, 검색 시각화, 후기, 비슷한 스타일 등 여러 제품팀에서 비즈니스의 요구사항에 맞게 사용하고 있습니다.

MusE 플랫폼의 특징

  • 빠른 클러스터 구성 : 엘라스틱서치 클러스터 구성은 약 10분 정도 걸리고, 엘라스틱서치 도메인 생성, LB 생성, 키바나 설치 등도 함께 구성됩니다.
  • 여러 클러스터 관리 및 모니터링 : 여러 개의 엘라스틱서치 클러스터도 실시간으로 관리 및 모니터링이 가능합니다.
  • 클러스터 구성 변경 : 엘라스틱 서치 클러스터의 경우 원하는 노드별로 cpu, 메모리 조정이 가능하며 원하는 스토리지의 사이즈도 확장해서 사용이 가능합니다.
  • 롤링 업그레이드를 통한 안전한 엘라스틱서치 구성 변경 : ECK 설정을 변경해서 적용 하는 경우 엘라스틱서치 노드가 하나씩 순차적으로 배포가 되는 롤링 업그레이드가 되며 안전하게 구성 변경이 가능합니다.
  • 클러스터 생성 시 사용자 정의 플러그인 자동 설치 : 클러스터 생성 시 nori, 커스텀 분석기 등 커스텀 플러그인을 자동 설치하도록 설정이 가능합니다.
  • 사전 동기화 : AWS S3라는 저장소에 사용자 사전, 동의어 사전, 금칙어 사전을 저장하면, AWS S3 저장소에 있는 사전 파일들과 엘라스틱서치 노드에 사전 동기화가 가능해서 커스텀한 사전 설정이 가능합니다.
  • 스냅샷을 이용한 백업 및 복구 : 엘라스틱서치 데이터의 백업 및 복구를 위해서 엘라스틱서치에서 스냅샷을 이용하는데, AWS S3라는 저장소를 사용해서 스냅샷을 사용할 수 있습니다.
  • 엘라스틱서치 버전 업그레이드 : 엘라스틱서치 버전을 ECK 설정 파일을 수정을 하면 롤링 업데이트가 가능합니다.

ECK를 활용한 무신사 검색엔진 MusE 구축 과정

ECK를 활용해서 MusE를 어떻게 구축했는지 쿠버네티스 설정 파일에 대해서 간략하게 소개하고자 합니다.

ECK 사용하기 전 사전 작업

ECK를 사용하기 위해서는 사용자 리소스 정의(CRD, Custom Resource Definition)를 쿠버네티스에 설치를 해야 합니다. 쿠버네티스 커스텀 리소스를 활용하면 사용자가 정의한 오브젝트를 직접 구현해서 사용하거나 여러 종류의 리소스를 추상화해서 관리할 수 있습니다. 엘라스틱서치사에서는 커스텀 리소스를 제공을 하고 있고 ECK를 사용하기 위해서는 커스텀 리소스 정의를 쿠버네티스에 생성 해야 합니다. 아래와 명령어를 통해서 설치를 하면 Elastic사에서 만든 리소스인 elasticsearch, kibana, beats, enterprise search 의 커스텀 리소스를 생성할 수 있습니다.

kubectl create -f https://download.elastic.co/downloads/eck/2.5.0/crds.yaml

쿠버네티스 오퍼레이터(Operator)는 개발자를 대신해서 복잡한 애플리케이션의 인스턴스를 생성, 설정 및 관리하는 애플리케이션별 컨트롤러입니다. 오퍼레이터는 사용자 정의 리소스(CR)를 사용하여 애플리케이션과 그 구성 요소를 관리하는 역할을 합니다. 아래와 명령어를 적용하면 ECK 를 사용할 준비가 완료되었습니다.

kubectl apply -f https://download.elastic.co/downloads/eck/2.5.0/operator.yaml

설정 파일의 템플릿화

위에서 설치한 쿠버네티스 오퍼레이터는 엘라스틱서치 클러스터가 쿠버네티스 설정 파일에 정의한 상태를 만들기 위해 쿠버네티스 리소스를 자동으로 생성하고 관리합니다. 이제 엘라스틱서치 관련 쿠버네티스의 설정 파일을 만들어야 합니다. ECK에서 엘라스틱서치의 설정 파일의 가장 간략한 예는 아래와 같습니다.

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: quickstart
spec:
version: 8.5.2
nodeSets:
- name: master
count: 3
config:
node.roles:
- master
- name: data
count: 5
config:
node.roles:
- data
- name: coordinating
count: 2
config:
node.roles: []

설정 파일을 하나씩 살펴보도록 하겠습니다. kind는 Elasticsearch라고 정의하는데, 사전 작업에서 생성한 CRD 중 Elasticsearch를 사용하겠다는 것입니다. apiVersion은 현재 안정 버전인 ‘elasticsearch.k8s.elastic.co/v1’ 을 사용합니다. metadata에는 name이라는 필드가 있는데 엘라스틱서치 클러스터 명입니다. spec 하위에는 쿠버네티스의 오브젝트를 정의합니다. spec에 version에는 어떤 버전의 엘라스틱서치를 사용할 것인지 정의하면 되는데 여기 설정 파일에서는 8.5.2 버전을 사용하겠다는 것입니다. nodeSets에는 엘라스틱서치에서의 노드들을 배열 형태로 정의를 할 수 있습니다. nodeSets에서 name은 노드 그룹의 이름인데, 예를 들어 첫 번째 배열에서는 master라는 이름의 노드 그룹을 만들고, count는 3이라 3개의 엘라스틱서치 노드를 만들고, config에는 node.roles가 있는데 master의 role을 사용하겠다는 것입니다. 이런 식으로 노드마다 필요한 설정을 추가한 후에 아래와 같이 쿠버네티스 명령어를 통해서 엘라스틱서치 클러스터를 생성할 수 있습니다.

kubectl apply -f elasticsearch.yaml

이렇게 쿠버네티스의 설정 파일을 적용하면, quickstart 라는 이름의 엘라스틱서치 클러스터가 생성되며, 마스터 노드는 3대, 데이터 노드는 5대, 코디네이팅 노드는 2대 이렇게 설정이 됩니다. 참고로, ECK의 설정 파일을 정교하게 설정하면 CPU, memory 설정, 스토리지 설정, 엘라스틱서치 커스텀 플러그인 설치, 사전 동기화 기능 설정 등도 가능합니다.

여러 클러스터가 생긴다고 하더라도 클러스터 명, CPU 설정, 메모리 설정, 노드의 수 제어 등을 제외하고는 거의 비슷한 ECK의 설정을 가지고 있었습니다. 여러 쿠버네티스 설정 파일을 쉽게 관리하기 위해서 ECK 설정 파일을 템플릿화가 필요했습니다. 이해를 돕는 예시를 들자면, 팥 붕어빵, 슈크림 붕어빵 등 다양한 붕어빵이지만 하나의 붕어빵 틀 안에서 만드는 것입니다. 붕어빵 틀을 템플릿이라고 하고, 들어가는 속 재료를 설정값이라고 부르도록 하겠습니다. 아래 예시에 보면 quickstart라는 엘라스틱서치 클러스터 이름의, 마스터 노드는 4대, 데이터 노드는 6대, 코디네이팅 노드는 7대로 만들고 싶다고 하면 아래에 붉은색으로 표시된 부분만 변경하면 됩니다.

elasticsearch.yaml 파일 예

ECK 설정 파일을 템플릿화해서 쉽게 관리하기 위해서 Helm를 이용해서 만들었습니다. Helm은 복잡한 쿠버네티스 애플리케이션을 정의하고 설치 및 업그레이드를 쉽게 해주는 기술입니다. Helm을 이용해서 여러개의 클러스터를 생성해야 할 때 공통된 템플릿이 존재하기 때문에 쉽게 ECK 설정 파일을 빠르게 만들 수 있습니다. 설정 파일을 템플릿화했기 때문에 원하는 설정만 변경하면 10분 안에 엘라스틱서치 클러스터를 쉽게 만들 수 있습니다.

커스텀 플러그인 자동 설치

엘라스틱서치에서 한국어 분석기의 경우 기본 분석기가 아니기 때문에 추가로 커스텀 플러그인을 설치해야 합니다. 엘라스틱서치 노드가 초기화 시 엘라스틱사에서 공식적으로 제공하는 nori 분석기를 포함해서 무신사에서 커스텀 한 자연어 분석을 위해서 만든 커스텀 분석기를 자동 설치하도록 설정했습니다. ECK에서 엘라스틱서치 노드를 초기화 시에 여러 플러그인들을 한 번에 설치하도록 아래와 같이 설정했습니다.

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: quickstart
spec:
version: 8.5.2
nodeSets:
- name: data
count: 3
config:
node.roles:
- data
podTemplate:
spec:
initContainers:
- name: install-plugins
command:
- sh
- '-c'
- >-
bin/elasticsearch-plugin install analysis-icu analysis-nori https://s3.ap-northeast-2.amazonaws.com/musinsa-analyzer.zip

사용자 사전 동기화

사용자 사전은 각 제품개발팀별로 AWS S3라는 저장소에 사용자 사전, 동의어 사전, 금칙어 사전에 대한 사전 텍스트 파일을 AWS에 업로드를 해서 사용합니다. 예를 들어 동의어 사전의 텍스트 파일 예제는 아래와 같습니다.

  • synonym.txt (동의어 사전 파일)
가디건, 카디건

이렇게 텍스트 파일을 설정하면 가디건 / 카디건으로 검색하더라도 엘라스틱서치에서 단어를 분리하는 토큰화 작업 시에 동의어로 처리할 수 있습니다. 동의어 사전뿐만 아니라 사용자 사전, 금칙어 사전도 동일한 방법으로 처리할 수 있습니다.

이렇게 만든 동의어 사전을 사용하기 위해서는 엘라스틱서치 노드별로 에서 사전 파일을 가지고 있어야 합니다. 모든 엘라스틱서치 노드별로 재배포 없이 사전 파일을 동기화하기 위해서 AWS S3라는 저장소에 사전을 업로드 한 후 1분마다 엘라스틱서치 노드별로 동기화하도록 설정했습니다. ECK에서의 엘라스틱서치의 노드 설정 부분은 아래와 같습니다.

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: quickstart
spec:
version: 8.5.2
nodeSets:
- name: data
count: 3
config:
node.roles:
- data
podTemplate:
spec:
containers:
- command:
- bash
- '-c'
- >-
while sleep 60; do aws s3 sync
s3://k8s-cluster/elasticsearch/dictionary
/usr/share/elasticsearch/config/dictionary --endpoint-url
https://s3.ap-northeast-2.amazonaws.com; done;
image: 'amazon/aws-cli:2.7.24'
name: init-sync-config
volumeMounts:
- mountPath: /usr/share/elasticsearch/config
name: elastic-internal-elasticsearch-config-local

aws cli 명령어 중 aws에서 제공하는 저장소와 동기화를 하는 기능을 하는 aws s3 sync를 사용해서 특정 위치의 사전 파일들을 엘라스틱서치 노드 내에 config/dictionary 파일에 동기화를 해서 따로 사전이 변경된다고 하더라도 다시 노드를 재 배포를 하지 않고도 사용자 사전을 사용할 수 있도록 했습니다.

메모리 및 CPU 설정

엘라스틱서치의 클러스터는 마스터, 데이터, 코디네이팅 노드가 역활별로 여러 개의 노드로 구성되어 있습니다. 엘라스틱서치의 노드별로 맡는 역활이 다르기 때문에 서버 사양을 적절하게 조절하는 것이 필요했습니다. 예를 들어 코디네이팅 노드의 경우 연산을 하지 않기 때문에 많은 메모리가 필요 없고, 데이터 노드의 경우 연산 작업이 많이 필요하기 때문에 메모리가 상대적으로 많이 필요합니다.

노드별로 서버 사양을 조정하기 위해서 쿠버네티스 설정 파일 옵션 중 request, limit을 사용했습니다. 쿠버네티스에서는 리소스 할당과 관리를 하기 위해서 request, limit 을 사용합니다. 쿠버네티스에서 request는 컨테이너가 생성될 때 요청하는 리소스 양이고, limit은 컨테이너가 생성된 후에 실행되다가 CPU/메모리가 더 필요한 경우 추가로 더 사용할 수 있는 부분입니다.

예를 들어서 코디네이팅 노드의 경우 8Gi를 사용하고, cpu core 2개로 사용하고 싶다면 아래와 같이 request, limit에 memory: 8Gi, cpu: 2로 설정하고, ES_JAVA_OPTS의 경우 서버 사양의 ½ 값인 4Gi로 설정했습니다. 데이터 노드의 경우 memory: 16Gi, cpu: 2로 설정하고, ES_JAVA_OPTS의 경우 서버 사양의 ½ 값인 8Gi로 설정했습니다. 이렇게 노드별로 역활에 맞는 적절한 서버 사양 설정을 통해 리소스를 효율적으로 사용하고 있습니다.

apiVersion: elasticsearch.k8s.elastic.co/v1
kind: Elasticsearch
metadata:
name: quickstart
spec:
version: 8.5.2
nodeSets:
- name: coordinating
count: 3
config:
node.roles:
- []
podTemplate:
spec:
containers:
- env:
- name: ES_JAVA_OPTS
value: -Xms4g -Xmx4g
resources:
requests:
memory: 8Gi
cpu: 2
limits:
memory: 8Gi
- name: data
count: 3
config:
node.roles:
- data
podTemplate:
spec:
containers:
- env:
- name: ES_JAVA_OPTS
value: -Xms8g -Xmx8g
resources:
requests:
memory: 16Gi
cpu: 2
limits:
memory: 16Gi

이렇게 탄생한 ECK 기반으로 구축한 MusE 플랫폼을 통해 무신사의 제품개발팀은 엘라스틱서치 클러스터를 보다 쉽게 운영하고 안정적으로 확장할 수 있게 되었고 장애 복구 또한 더욱 효율적으로 대응할 수 있게 되었습니다.

맺으며

지금까지 무신사의 엘라스틱서치 인프라 구성 변천사와 ECK를 사용해서 엘라스틱서치 클러스터를 만든 과정을 소개해 드렸습니다.

검색플랫폼팀에서는 검색 기술을 플랫폼화해서 효율적으로 쉽게 사용할 수 있는 여러 방법들을 고민하고 있습니다. 이 고민을 함께 할 미래의 동료를 기다리고 있습니다.

검색플랫폼팀 오픈 포지션 살펴보기

감사합니다.

--

--