궁금한게 많은 개발자 노트

[ k8s ] elasticsearch설치 시 vm.max_map_count값 변경 본문

DevOps

[ k8s ] elasticsearch설치 시 vm.max_map_count값 변경

궁금한게 많은 개발자 2023. 4. 24. 15:46

Elasticsearch를 위한 Pod생성 시 Statefulset을 구성할 때, 안정적인 동작을 위해서는 vm.max_map_count값을 변경해주어야 한다고 한다. 그 이유는 무엇이며 해당 값이 나타내는 의미가 무엇인지 궁금해서 찾아봤습니다.

 

 

리눅스 커널 공식 문서에 기술된 /proc/sys/vm 아래에 위치한 max_map_count파일에 대한 정보는 아래와 같습니다.

==============================================================

max_map_count:

This file contains the maximum number of memory map areas a process
may have. Memory map areas are used as a side-effect of calling
malloc, directly by mmap, mprotect, and madvise, and also when loading
shared libraries.

While most applications need less than a thousand maps, certain
programs, particularly malloc debuggers, may consume lots of them,
e.g., up to one or two maps per allocation.

The default value is 65536.

=============================================================

해당 파일은 프로세스가 가질 수 있는 최대 메모리 맵 영역 수를 나타냅니다. 메모리 영역은 mmap, mprotect, madvice에 의한 malloc호출의 side-effect로 사용되며, 공유 라이브러리를 로드할 때도 사용됩니다. 대부분의 애플리케이션이 천 개 미만의 메모리 맵을 필요로 하지만, 특정 프로그램은 더 많은 메모리 맵을 소비할 수 있습니다. 라고 설명되어 있습니다.

 

vm.max_map_count는 변수로서, /proc/sys/vm/max_map_count 파일을 가리킵니다. 이 파일은 Linux kernel의 메모리 맵* 영역의 최대 개수를 조작할 수 있습니다. 메모리 매핑 작업이 많이 일어나는 프로세스일수록 가상 메모리에서의 주소 공간인 가상 주소 공간을 더 많이 필요로 합니다.

더보기

💡 Memory mapping: 파일을 프로세스의 메모리에 매핑하는 것. 즉 프로세스에 전달할 데이터가 저장된 파일을 직접 프로세스의 가상 주소 공간으로 매핑. read와 write 함수를 사용하지 않고도 프로그램 내부에서 정의한 변수를 사용해 파일에서 데이터를 읽거나 쓸 수 있음.

 

 

이러한 값은 linux의 경우 default value가 65,530입니다. Elasticsearch가 안정적으로 동작하기 위해서 권장되는 값은 262,144이라고 하는 걸 보면 Elasticsearch는 많은 메모리 맵을 필요로 하는 것 같습니다.

https://www.elastic.co/guide/en/elasticsearch/reference/current/vm-max-map-count.html

 

Virtual memory | Elasticsearch Guide [8.7] | Elastic

Elasticsearch uses a mmapfs directory by default to store its indices. The default operating system limits on mmap counts is likely to be too low, which may result in out of memory exceptions. On Linux, you can increase the limits by running the following

www.elastic.co

 

Elasticsearch uses a  mmapfs directory by default to store its indices. The default operating system limits on mmap counts is likely to be too low, which may result in out of memory exceptions.

위에서 설명하듯 Elasticsearch는 기본적으로 mmapfs 디렉터리를 사용하여 인덱스를 저장합니다. 기본 운영 체제에서 설정한 mmap 개수의 제한은 너무 낮기 때문에 메모리 부족 예외가 발생할 수 있다고 설명하고 있습니다.

여기서 mmapfs와 mmap은 어떤 용어일까요?

mmapfs

mmapfsThe MMap FS type stores the shard index on the file system (maps to Lucene MMapDirectory) by mapping a file into memory (mmap). Memory mapping uses up a portion of the virtual memory address space in your process equal to the size of the file being mapped. Before using this class, be sure you have allowed plenty of virtual address space.

MMapFS유형은 파일에 메모리를 매핑하여(mmap)파일 시스템(Lucene의 MMapDirectory에 대응)에 샤드 인덱스를 저장합니다. 메모리 매핑은 매핑되는 파일과 동일한 크기의 프로세스 내 가상 메모리 주소 공간의 일부를 사용합니다.

이 클래스를 사용하려면 충분한 가상 공간을 허용했는지 확인해야 합니다라고 가이드되어 있습니다.

즉, MMapFS는 Elasticsearch가 샤드 인덱스를 저장하는데 사용되는 여러 저장 유형 중 하나라는 사실을 알 수 있습니다.

더보기

위에서 언급되는 샤드와 인덱스에 대한 설명입니다.

Elasticsearch에서는 단일 데이터 단위를 도큐먼트(document) 라고 하며 이 도큐먼트를 모아놓은 집합을 인덱스(Index) 라고 합니다. 인덱스라는 단어가 여러 뜻으로 사용되기 때문에 데이터 저장 단위인 인덱스는 인디시즈(indices) 라고 표현하기도 합니다. 이 책에서는 데이터를 Elasticsearch에 저장하는 행위는 색인, 그리고 도큐먼트의 집합 단위는 인덱스 라고 하겠습니다. 인덱스는 기본적으로 샤드(shard)라는 단위로 분리되고 각 노드에 분산되어 저장이 됩니다. 샤드는 루씬의 단일 검색 인스턴스 입니다

 

그렇다면, Elasticsearch가 mmapfs유형의 저장소를 통해 샤드 인덱스를 저장하는 과정에서 mmap시스템 콜을 이용한 많은 수의 메모리 매핑 작업이 발생할 수 있고, 그 결과로 많은 메모리 맵 파일이 생성되어 MMapFS에 저장될 수 있습니다.

 

 

이 과정에서 Lucene의 MMapDirectory에 대응된다는 것은 무엇일까해서 Lucene라이브러리에 대해 찾아봤습니다.

Elasticsearch는 검색 엔진으로 검색 요청에 대해 빠르게 결과를 반환하기 위해 다양한 기술과 라이브러리를 사용합니다. 그 중에서 가장 핵심적인 기술인 Lucene을 기반으로 만들어졌고, MMapDirectory는 Lucene의 인덱스를 저장 및 관리하는 디렉터리 구현입니다.

MMapDirectory는 해당 메모리에 직접 액세스 하기 위해 필요한 파일을 가상 메모리에 매핑하도록 운영 체제에 요청하여 파일 시스템 캐시를 활용한다. Elasticsearch에게는 모든 파일이 메모리에서 사용 가능한 것처럼 보이지만 반드시 그럴 필요는 없다. OS는 저장될 인덱스 크기가 사용 가능한 실제 메모리보다 크면 운영 체제는 기꺼이 캐시에서 사용하지 않는 파일을 제거하고 새로 읽어야 할 파일을 위한 공간을 만든다. Elasticsearch는 캐시에서 삭제한 파일이 다시 필요한 경우, 필요로하는 파일은 메모리에 로드되고 다른 사용되지 않는 파일은 제거된다. MMapDirectory에서 사용하는 가상 메모리는 시스템의 가상 메모리 (swap)와 유사하게 작동한다. swap에서 운영 체제는 디스크를 사용하여 여러 응용 프로그램을 지원할 수 있도록 사용되지 않은 메모리를 페이징 한다.

 

즉, Lucene의 MMapDirectory에 대한 설명과 함께 결론지어 보면 Elasticsearch는 운영 체제를 이용하여 인덱스 파일들을 가상 메모리에 가상으로 매핑하고 파일 시스템 캐시를 생성합니다. 덕분에 검색 요청이 들어오면 디스크(보조 기억 장치)에 접근할 필요 없이 캐시에 들어 있는 데이터를 가져와 신속하게 응답합니다.

이러한 방식으로 인덱스를 관리하는 것은 굉장히 빠른 성능을 보장합니다. 그러나 Linux의 경우 응용 프로그램이 한 번에 너무 많은 파일을 열거나 너무 많은 메모리를 매핑하는 것을 방지하는 제한이 있는데, 그게 바로 vm.max_map_count 값이므로 이 값을 증가 시켜 원활하게 Elasticsearch가 동작할 수 있도록 설정합니다.

 

추가로, Elasticsearch에서 매핑을 통해 많은 파일을 사용하므로 이를 위한 file descriptor도 필요한데, 이를 위해 ulimit을 통해 fd의 수를 늘려주는 작업 또한 필요합니다.

Comments