AWS Aurora 도입전에 알아야 할 몇가지 사실

처음 AWS Aurora DB를 사용하기 전에 알아두면 좋은 것들

AWS 위에서 웹서비스 개발할때 DB는 뭘로 쓰는가? 나라면 당연히 RDS를 쓸 것이다. 수년전에 처음 AWS를 접했을때 RDS가 비싸다는 이유로 잠시 주저한적이 있었다. 하지만 숙련된 DB 운영자 1명의 역할을 대신한다는 말을 듣고 선택했고 그 선택에 여지껏 후회는 없었다.

RDS는 훌륭한 관리형 RDB 서비스이다. 그러나 지원하는 엔진들(MySQL 등등)이 클라우드 환경에 최적화 되었다고 보긴 어렵다. 이들 엔진은 과거 베어메탈 시절에 설계되고 만들어졌기 때문에 클라우드 환경에 맞게 성능과 가용성을 끌어내기 어렵다.

그래서 AWS, MS등의 퍼블릭 클라우드 벤더들은 자사의 클라우드 환경에 최적화된 새로운 RDB를 만들게 되었다. Aurora(오로라) DB는 AWS가 쏟은 이러한 노력의 결과이다. 아래 논문에선 Aurora DB가 Storage와 Computation의 분리/Instance 중심이 아닌 Cluster 중심의 구성/S3의 적극적인 활용을 통해 기존 MySQL의 한계를 어떻게 뛰어넘었는지 잘 설명하고 있다. 이런데 관심이 많다면 일독을 권한다.


우리회사는 RDS MySQL를 수년이상 메인 DBMS로 사용해 왔다. 우리회사나 고객사나 이를 이용함에 있어 별 문제가 없었다. 그러던 와중에 Aurora가 등장했고 이에 대한 이해와 운영 경험이 필요하게 되었다. 우리는 안정화 되기를 기다렸고 때가 왔기에 도입을 하게 되었다. 그러나 악마는 디테일에 있듯 도입과정서 알게된 문제들이 좀 있다.

오로라는 멀티 AZ를 지원하지 않는다?

RDS는 가용성을 높이기 위해서 물리적으로 떨어진 Availability Zone들에 인스턴스를 생성할수 있다. 따라서 한개의 AZ가 망가져도 다른 AZ가 살아있다면 서비스에 장애가 생기지 않는다. 이 기능을 멀티 AZ라 부르며 이 기능이 적용되면 콘솔상에선 1개의 DB 인스턴스처럼 보이더라도 실제론 여러개의 인스턴스가 생기게 된다. (그만큼 비용이 증가되는건 덤)

하지만 오로라는 이 멀티 AZ를 지원하지 않는다. AWS CLI 에서 억지로 생성하려고 하면 다음 에러가 나타난다.

VPC Multi-AZ DB Instances are not available for engine: aurora

이렇게 된 이유는 오로라의 컨셉 때문이다. 오로라는 Read Replica를 Failover에 사용한다. 여러 RR이 같은 클러스터로 묶여 있고 Write 권한이 있는 마스터가 다운되면 RR중 하나를 마스터로 자동 승격시켜 대응한다. 이 과정은 수초내로 기존 RDB 대비 굉장히 빨리 이루어진다. 이는 Storage가 Computation Unit과 물리적으로 분리되어 있으며 DNS 차원에서 연결을 승격된 RR로 바로 틀수 있기 때문이다. (EB의 CNAME Swap 기능을 생각하면 쉽다.)

기존의 RDS는 Computation과 Storage를 단일 VM내에 모두 지닐수밖에 없어 빠르게 Failover 하는것이 힘들었다. (장애상황에서 데이터를 보호하고, 이전하는 일들이 베어본을 쓰는 것보다 쉽긴 했지만 그래도 여전히 어려운 일이었다.) 그리고 DB의 Endpoint는 master instance에 직접 연결되어 있는 주소였기 때문에 master에 장애가 생기면 이를 수동으로 RR과 교체해줄때까지 서비스에 문제가 생기는건 감내해야 했다.

하지만 Aurora의 Storage는 Computation과 물리적으로 분리되어 여러 AZ에 걸쳐서 복제되어 있다. 따라서 Aurora에선 Computation instance는 언제든 문제가 생기면 클러스터 내에 있는 다른것으로 빨리 갈아 버리면 그만이다. 기존 RDS 엔진들 처럼 무조건 24/365 master 인스턴스를 조마조마하게 유지하고 있을 이유가 없는 것이다. 따라서 Aurora에선 Storage의 Multi AZ는 있으나 Instance의 Multi AZ는 RR을 하나이상 만들어 다는 것으로 대체되었다고 보면 된다. 아래 Reddit에 좀더 자세한 설명이 나와 있다.

그렇기 때문에 Aurora Instance에 안정적으로 접속하고 싶다면 마스터 외에 1개 이상의 RR을 붙여주는게 필수적인 일이 되었다. 설정상에선 다소 불편할수 있지만 오히려 명시적으로 인스턴스를 관리할수있다는 장점이 있다고 본다.

클러스터와 인스턴스는 따로국밥

이렇게 Aurora 에선 Failover와 관련된 Operation 부터 클러스터 기반으로 돌아간다. 따라서 클러스터를 쓸건지 인스턴스만 쓸건지를 정할수 있는 다른 엔진과 달리 반드시 클러스터를 생성해야 한다. 다만 AWS CLI 한정으로 인스턴스가 하나도 없는 클러스터 생성이 가능하다. 우리회사처럼 CLI로 프로비저닝을 운영하는 고객들은 클러스터와 인스턴스를 각각 생성해 줘야 한다. 이는 관리의 기능이 클러스터 단위로 많이 올라왔으며, 인스턴스는 언제든지 부수고 버릴수 있는 수준으로 독립이 이루어진것으로 보인다. 이런 독립성을 보여주는 또다른 사례 있다. Cluster Endpoint와 Instance Endpoint가 각각 주어지며, 인스턴스가 하나도 없어도 Cluster Endpoint가 존재한다는 것이다.

사용자들이 Write Query를 날리고 싶다면 Cluster Endpoint에 날려야 하며 이 End point는 master = primary instance로 연결된다. 인스턴스 레벨의 Endpoint는 각각의 인스턴스에 접근할수 있는 것처럼 보이지만 장애시 CNAME Swapping을 위해서 존재하는 주소로서의 역할이 더 크다. 또한 Reader Endpoint라는 Endpoint도 클러스터 레벨에서 지원하는데 이 Endpoint로 들어온 트래픽은 클러스터 내의 여러 Read Replica에게 Load Balancing 된다. 따라서 웹 서버에서는 Write는 Cluster Endpoint로 설정하고 Read Replica 접근은 Reader Endpoint로만 가도록 만들면 된다. Aurora 클러스터 아래 어떻게 구성되어 있는지는 웹서버에서 신경쓰지 않아도 된다.

클러스터 레벨에선 Cluster Endpoint와 Reader Endpoint를 제공
인스턴스 Endpoint도 따로 존재. RR이 하나 달렸기 때문에 Mutli-AZ가 2 Zone 으로 나온다.

일부 높은 MySQL 버전을 지원하지 않는다.

사실 이 부분이 오늘 이야기 하고 싶은 메인 주제이다. 기존에 RDS MySQL 을 쓰다가 이를 Aurora로 이전하기 위해서 처음엔 DMS (Database Migration Service)를 써볼까 했었다. 그러나 DMS는 AWS 외부의 이기종 DB에서 RDS로 데이터를 이전하기 위해서 사용하는 서비스였다. 예를들어 데이터센터에 Oracle이 있는데 이를 Aurora로 이전하고 싶다면 DMS가 답이다. DMS를 사용하면 데이터를 지속적으로 이전시켜 주는 DMS Instance를 DMS 서비스 내에 하나 띄우게 되고 이 인스턴스가 원본 DB에서 지속적으로 데이터를 Crawling 해서 목적지 DB에 맞게 정의된 매핑으로 변환후 삽입해 준다. 이전이 끝나면 DMS Instance를 끄면 된다.

하지만 RDS MySQL을 Aurora로 옮긴다면 굳이 DMS를 사용할 필요는 없다. RDS MySQL의 Read Replica로 Aurora클러스터 & 인스턴스를 하나 띄우고, MySQL에 Write 요청이 들어오지 않도록 웹서버 패치후 Aurora의 mysql console에서 Replica Lag이 0에 다다르면 Aurora를 메인 DB로 승격시킨 후 기존 MySQL 인스턴스를 내리면 된다. 이 방법은 서비스 중단을 최소화 해야 할때 유용하며 중단해도 된다면 다른 방법을 써도 된다.

하지만 여기에 복병이 하나 있는데, MySQL 엔진 버전이 Aurora에서 지원하지 않을 경우 Read Replica가 생성되지 않는다. 이는 호환성 때문이다.

MySQL 5.6.x 계열에서는 UNIQUE KEY의 최대 길이가 767 bytes 이다. 5.7.x 부턴 이 제약이 innodb_large_prefix가 켜져있을 경우 3072 bytes 까지 늘어난다.

문제는 RDS Aurora는 5.6.x의 767 bytes를 사용하고 있다. 이 때문에 5.7.x의 RDS MySQL에서 쓰던 DDL을 쓸수가 없었다. 결국 UNIQUE KEY DDL을 바꿔야 되고 데이터도 이에 맞게 재 주입해야 한다. 결국 호환성 문제로 깔끔하게 Migration 할수 없는 문제가 생기게 된다. 가장 좋은 방법은 Aurora가 5.7.x 로 업그레이드 되는 것이지만 언제 지원이 될지는 미지수이다. 2017년 8월 현재는 5.6.10a만 지원한다. 따라서 5.7.x 엔진을 쓰던 유저들은 당장 문제가 없다면 마이그레이션을 좀 미뤄야 할 상황이다. (2018년 4월 현재 5.7.x가 나온 상태이기 때문에 바로 5.7.x로 가면 됩니다 :) )


AWS Aurora는 기존 RDB의 한계를 클라우드 인프라에 맞도록 엔진을 재 설계함으로서 Production 레벨에서 뛰어넘었다는 점에서 매우 흥미로운 Product이다. (이런 설계를 할수 있는 엔지니어가 되는게 개인적인 꿈중 하나이다.) 그리고 그 기반에 Amazon CTO Weiner Vogles가 이야기 하는 AWS의 설계 철학 “Fail Fast, Recovery Fast” 가 잘 녹아 있는것도 훌륭하다고 생각한다.

그러나 아직 나온지 얼마 안된만큼 부족한 부분들이 내부에 존재한다. (버그도 있다.)여기에 더 비싼 비용(Oracle의 그것보다는 낫다…)과 AWS 종속에 대한 Risk 또한 존재한다. 그럼에도 당사가 도입한 이유는 AWS에 집중하는 회사의 전략적 경험 때문이었다. 나머지는 이 글을 읽는 독자분이 보수적으로 잘 판단하시리라 믿는다.

HB Smith는 AWS Aurora외에도 다양한 AWS 서비스들에 대한 수년이상의 개발 및 운영경험을 지니고 있다. 그리고 이를 기반으로 DevOps 팀을 위한 API 모니터링 툴을 만들고 있으니 관심있는 분은 아래 사이트를 방문해 주세요 :)