brunch

You can make anything
by writing

C.S.Lewis

by 강진우 Nov 29. 2020

ElasticSearch 스냅샷을 S3글래셔로 저장하기

ElasticSearch를 기반으로 로그 수집 및 조회 시스템을 운영하다 보면 법적인 요건 등 다양한 이유로 오랜 시간 로그를 보관하고 있어야 할 경우가 있습니다. 하지만 언제 조회하게 될지도 모를 로그들을 저장하기 위해 많은 수의 데이터 노드를 운영한다는 건 배보다 배꼽이 더 커지는 경우가 됩니다. ElasticSearch에서는 이런 경우를 위해 스냅샷이라는 기능을 제공하고 있습니다. 스냅샷은 외부 저장소에 인덱스를 백업할 수 있는 기능입니다. 그리고 AWS S3AWS 환경에서 ElasticSearch를 운영할 경우에 사용할 수 있는 가장 효율적인 스냅샷 저장소입니다. 그렇지만 이 경우에도 보관해야 하는 스냅샷의 크기가 커진다면 무시할 수 없는 비용이 발생하게 됩니다. 그래서 이번 글에서는 이런 단점을 극복하고자 고민했던 방법들 중 스냅샷을 S3의 글래셔로 저장하는 방법에 대해 이야기해보려고 합니다. 언제나 그렇지만 이 글에 제시된 방법이 최선의 방법은 아닙니다. 그저 같은 고민을 하고 있는 분들에게 이런 식으로도 문제를 해결할 수 있다는 것을 공유하기 위한 글입니다. 그럼 시작해 보겠습니다.


S3 레포지터리 플러그인의 한계


앞서 이야기한 것처럼 ESS3 레포지터리 플러그인을 통해 간편하게 인덱스의 스냅샷을 S3에 저장하는 기능을 제공하고 있습니다.

S3 레포지터리 설정

위 그림과 같이 저장할 버킷, 리전, 디렉터리(base_path), 스토리지 클래스를 정의해주면 끝입니다. 그 후 IAM을 통해 필요한 권한들을 부여해 주고 snapshot API를 통해 스냅샷을 생성하고 복원하는 작업들을 하면 됩니다. 

하지만 ES의 S3 레포지터리 플러그인이 가지고 있는 가장 큰 한계 중 하나는 바로 스냅샷을 저장할 스토리지 클래스에 글래셔를 지원하지 않는다는 것입니다.
S3 레포지터리 플러그인이 지원하는 스토리지 클래스 (출처 : 공식 홈페이지)

위에 언급된 것처럼 스탠다드 외에 다양한 스토리지 클래스를 지원하지만 글래셔는 지원하지 않기 때문에 기본적인 기능만을 이용해서는 스냅샷을 글래셔로 변경할 수 없습니다. 그렇다면 어떤 추가 작업들을 해주어야 할까요?


글래셔로 변경하기 위한 과정


스냅샷을 글래셔로 변경하기 위한 과정은 아래와 같이 진행됩니다.

스냅샷을 글래셔로 변경하기 위한 과정

먼저 ES에서 S3로 스냅샷을 저장합니다. 이 작업은 snapshot API를 통해 이뤄집니다. 그리고 별도의 스크립트를 통해서 S3에 생성된 스냅샷 백업 파일을 글래셔로 변경하는 과정을 거칩니다. 사실 스냅샷 백업 파일을 글래셔로 변경하는 과정은 크게 어렵지 않습니다. 스냅샷 백업 파일이 저장된 디렉터리를 확인하고 그 디렉터리 내에 있는 파일들을 글래셔로 변경해주기만 하면 됩니다. 하지만 글래셔로 변경된 스냅샷을 ES에서 조회하기 위해 복원할 때 문제가 됩니다. 글래셔로 변경해 놓은 파일을 그대로 snapshot API를 통해 복원할 수 없기 때문입니다. 그래서 스냅샷을 복원하는 과정은 아래와 같이 진행됩니다.

스냅샷을 복원하기 위한 과정

먼저 복원하고자 하는 인덱스의 스냅샷 백업 파일을 찾은 후 스크립트를 사용해서 스탠다드로 다시 복원합니다. 그리고 복원이 완료되면 ESsnapshot API를 통해서 인덱스를 다시 ES에 적재합니다. 이 과정에서 가장 많은 시간이 소요되는 부분은 글래셔로 변환된 백업 파일을 다시 스탠다드로 변경하는 과정입니다. S3에서 글래셔를 스탠다드로 다시 복원하는 과정은 최소 수분에서 최대 수시간 정도 소요됩니다. 

그래서 스냅샷 백업 파일을 글래셔로 변경하게 되면 기존보다 S3 저장 비용은 줄일 수 있는 반면 인덱스를 ES로 복원하는데 상당한 시간이 소요되게 됩니다. 

시간과 비용이라는 분명한 트레이드오프가 존재하는 만큼 환경에 맞춰서 적용하는 것이 필요합니다.

그럼 실제 스크립트는 어떻게 구성되어 있는지 살펴보겠습니다.


스냅샷이 저장된 위치 찾기


S3에 스냅샷을 저장하게 되면 레포지터리 설정에 사용했던 버킷과 디렉터리에 index_XXX라는 메타데이터 파일이 생성됩니다.

메타데이터 파일

이 파일은 현재 백업되어 있는 스냅샷의 리스트와 그 스냅샷에 어떤 인덱스들이 포함되어 있는지 그리고 각 인덱스들의 스냅샷 백업 파일들이 S3의 어느 위치에 존재하는지 등의 정보를 저장하고 있습니다.

스냅샷 메타데이터의 일부

그중에서도 indices 리스트가 가장 중요합니다. indices 리스트는 인덱스 이름이 키이고 그 안에 idsnapshots라는 두 개의 키를 더 가지고 있습니다. 그중에서도 id 값이 해당 인덱스의 백업 파일들이 저장된 S3의 디렉터리를 가리키고 있습니다. 위 스크린샷의 예제에서 보이는 것처럼 S3의 스냅샷이 저장되는 버킷의 indices 디렉터리에 들어가면 1P6jhuxyQqqxn9gzQxOEOw 디렉터리가 생성되어 있는 것을 볼 수 있습니다.

인덱스의 백업 파일들이 저장된 디렉터리

우리가 글래셔로의 변경 작업을 해야 할 파일들이 바로 이 디렉터리에 있는 파일들입니다. 


글래셔 변경 소스 코드 구현


먼저 스크립트의 실제 코드들 중 글래셔로 변경하는 부분을 살펴보겠습니다.

글래셔로 변경하는 코드의 핵심 부분

앞에서 언급했던 것처럼 메타데이터 파일을 통해 인덱스의 스냅샷 백업 파일들이 저장된 위치를 찾아서 getObjects() 함수를 통해 오브젝트 리스트를 가져옵니다. 그리고 스토리지 클래스가 글래셔가 아니라면 글래셔로 변경해 줍니다. getObjects() 함수는 한 번에 최대 1000개의 오브젝트까지 밖에 안 가져오기 때문에 1000개가 넘을 때를 대비해서 더 가져와야 할 오브젝트가 있을 경우 계속 오브젝트를 가져와서 글래셔로 변경하도록 로직이 구성되어 있습니다. transitObject() 함수는 아래와 같이 AWS Go SDK에서 제공하는 CopyObject() 함수를 이용해서 오브젝트를 글래셔로 복사합니다.

transitObject() 함수

이 과정까지 마치면 스탠다드 클래스로 생성된 인덱스의 스냅샷 백업 파일들은 모두 글래셔로 변경됩니다.


복원을 위한 소스 코드 구현


다음으로 글래셔로 저장된 인덱스를 ES로 복원하기 위한 소스 코드를 살펴보겠습니다.

복원을 위한 소스 코드

글래셔로 변경할 때와 마찬가지로 메타데이터를 통해 복원해야 할 인덱스들이 저장된 파일의 위치를 찾은 후 스토리지 클래스가 글래셔로 되어 있다면 스탠다드로 변경해 줍니다. 스탠다드로의 변경은 restoreObject() 함수를 이용합니다.

restoreObject() 함수

restoreObject() 함수는 글래셔 상태의 오브젝트들을 스탠다드로 복원하는 역할을 합니다. 아직 글래셔 상태라면 AWS Go SDK에서 제공하는 RestoreObject() 함수를 통해서 복원 요청을 날리고, 이미 복원 요청 중인 오브젝트들이라면 복원이 완료되었다는 메타데이터가 있으면 오브젝트를 스탠다드로 복사해서 복원시킵니다.

복원 과정에서 주의해야 할 것은 모든 파일이 전부 스탠다드로 변경되어야 ES로의 인덱스 복원이 가능하다는 것입니다. 그래서 마지막에 모든 오브젝트들이 스탠다드 상태인지를 확인하는 로직이 추가됩니다. 하지만 스탠다드로 복구하는 작업은 최소 수분에서 수시간이 소요되기 때문에 스크립트를 한 번 실행하는 것으로는 완료되지 않습니다. 우선 첫 번째 실행을 통해서 글래셔 오브젝트들의 복원 요청을 날린 후 어느 정도 시간이 지난 후에 다시 한번 돌려서 스탠다드로의 복원이 완료되었는지를 확인하는 과정을 거쳐야 합니다. 이 부분까지 모두 자동화될 수 있다면 더 완성도 높은 스크립트가 될 수 있겠죠 ^^;;


마치며


글래셔로의 변경 작업은 ES의 스냅샷 저장 비용을 최소화해보기 위한 고민으로 시작한 작업이었습니다. 글래셔로 변경하는 작업은 생각보다 쉽게 되었지만, 복원하는 과정이 스크립트 한 번으로 끝나지 않고 여러 번 수행해야 하며, 복원에 많은 시간이 소요되는 등 깔끔하지는 않았습니다. 하지만 결과적으로 GB당 $0.025의 비용이 $0.005로 줄어들게 되면서 절반 이상의 비용 절감을 확인할 수 있었습니다. 또한 로그 복원 작업이 아주 급하게 필요한 경우는 매우 드물기 때문에 이 정도의 트레이드오프는 충분히 효과적이었다고 생각됩니다.

아마도 이 글에서 언급한 방법 외에 더 좋은 방법들이 있을 수 있습니다. 이 글이 고민의 시작이 되었으면 합니다.


매거진의 이전글 nginx no live upstream 에러 이해하기
브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari