RDS 장애 조치와 유지보수 창, 맡긴 대가로 오는 재부팅
RDS는 보안 패치를 몇 달에 한 번씩 유지보수 창에서 적용하고, 그때 데이터베이스가 잠시 내려가거나 대기 인스턴스로 넘어간다.
데이터베이스가 돌아와도 앱이 끊긴 연결과 옛 주소를 붙들고 있으면 장애가 이어진다.
이 글의 목차매주 돌아오는 유지보수 창7
RDS 콘솔의 데이터베이스 목록에는 ‘유지 관리’라는 열이 있다.
평소에는 비어 있다가 어느 날 운영체제 업데이트가 ‘필수(required)‘로 올라오고, 옆에 적용 날짜가 붙는다.
처음 보면 무시해도 되는지, 적용되는 날 서비스가 멈추는지부터 궁금해진다.
매주 돌아오는 유지보수 창
RDS에서는 데이터베이스 서버의 운영체제와 엔진 패치를 AWS가 대신 적용해 준다.
그 작업이 시작되는 시간대를 유지보수 창이라고 한다.
모든 DB 인스턴스에는 매주 돌아오는 유지보수 창이 하나씩 있다.
인스턴스를 만들 때 창을 따로 정하지 않았다면 RDS가 무작위로 고른 요일의 30분이 들어간다.
서울 리전이라면 한국 시간 밤 10시부터 아침 6시 사이에서 골라진다.
그 시간이 내 서비스의 한가한 시간과 맞는다는 보장은 없다.
창은 작업이 시작되는 때를 정할 뿐이다.
작업이 창 안에 끝난다는 보장은 없어서, 끝나는 시각을 넘겨 계속되기도 한다.
‘필수’ 업데이트는 끝까지 미룰 수 없다
유지 관리 열의 상태는 몇 가지로 나뉜다.
‘사용 가능(available)‘은 원할 때 직접 적용하는 선택 업데이트로, RDS가 알아서 적용하지 않는다.
‘필수(required)‘는 계속 미룰 수 없는 업데이트다.
필수 패치는 보안과 인스턴스 안정성에 관련된 것만 잡히고, 대개 몇 달에 한 번 생긴다.
적용 날짜가 지나면 RDS가 유지보수 창 가운데 하나에서 직접 적용한다.
창을 계속 다른 날로 옮겨서 피할 수도 없다.
그렇게 미루는 사이 적용 날짜가 지나면, RDS는 원하는 창 밖에서도 업그레이드를 적용할 수 있다.
패치하는 동안 데이터베이스는 어떻게 되는가
운영체제나 엔진 패치 같은 일부 작업은 인스턴스를 잠깐 오프라인으로 내려야 한다.
인스턴스가 한 대뿐이라면 그동안 데이터베이스에 접속할 수 없다.
그래서 운영 서비스에서는 Multi-AZ 배포를 많이 쓴다.
다른 가용 영역(AZ)에 대기 인스턴스를 하나 더 두는 구성이고, 가용 영역은 한 리전 안에서 물리적으로 떨어진 데이터센터 구역이다.
대기 인스턴스는 주 인스턴스의 변경을 동기식으로 받아 두기만 하고, 읽기 요청은 받지 않는다.
주 인스턴스에 문제가 생기면 대기 인스턴스가 주 인스턴스 역할을 넘겨받는데, 이 전환을 장애 조치(failover)라고 한다.
이름이 비슷한 Multi-AZ DB 클러스터는 다른 구성이다.
대기 인스턴스를 둘 두고 읽기 요청까지 받게 한다.
여기서는 대기 인스턴스가 하나인 구성을 기준으로 한다.
Multi-AZ에서 운영체제 패치는 순서가 정해져 있다.
대기 인스턴스를 먼저 고치고, 그 대기 인스턴스를 주 인스턴스로 올린 다음, 물러난 옛 주 인스턴스를 마저 고친다.
가운데 단계가 장애 조치다.
그래서 AWS가 정리한 장애 조치 사유 목록에도 유지보수 창의 운영체제 패치가 올라 있다.
Multi-AZ라도 연결이 한 번은 끊긴다.
데이터베이스 엔진 업그레이드는 또 다르다.
이때는 주 인스턴스와 대기 인스턴스를 동시에 고쳐서, 업그레이드가 끝날 때까지 둘 다 쓸 수 없다.
Multi-AZ가 모든 중단을 막아 주지는 않는다.
장애 조치가 바꾸는 것은 DNS 이름의 목적지다
앱은 엔드포인트라는 도메인 이름 형태의 주소로 데이터베이스에 접속한다.
RDS가 인스턴스마다 만들어 주는 주소다.
이 이름을 실제 IP 주소로 바꿔 주는 체계가 DNS다.
장애 조치가 일어나면 RDS는 인스턴스의 DNS 레코드를 대기 인스턴스 쪽으로 바꾼다.
이름은 그대로이고 그 이름이 가리키는 IP만 바뀐다.
그래서 기존 연결은 모두 다시 맺어야 한다.
전환 자체는 보통 60초에서 120초 걸린다.
큰 트랜잭션이 돌고 있었다면 더 길어질 수 있다.
문제는 전환이 끝난 뒤에도 앱이 예전 상태를 붙들고 있을 때 생긴다.
앱이 붙들고 있는 두 가지
첫째는 이름 조회 결과다.
이름을 IP로 바꾼 값은 TTL이라는 유효 시간 동안 캐시에 남는다.
DNS와 TTL의 기초는 DNS 글에서 다뤘다.
그 시간 동안 앱은 이미 물러난 인스턴스의 IP로 접속을 시도한다.
AWS는 자바 실행 환경(JVM)이 설정에 따라 재시작 전까지 조회 결과를 새로 고치지 않을 수 있다며, 이 값을 60초 이하로 두라고 권한다.
둘째는 커넥션 풀이다.
데이터베이스 연결을 매번 새로 맺으면 느리기 때문에, 앱은 맺어 둔 연결을 모아 두고 돌려 쓴다.
그런데 풀에 있던 연결은 옛 주 인스턴스와 맺은 그대로 남아 있다.
그래서 독특한 증상이 나온다.
콘솔에서 데이터베이스는 멀쩡한데 앱만 계속 실패하다가, 앱을 재시작하면 갑자기 낫는다.
재시작하면서 이름 조회 결과와 커넥션 풀이 함께 비워졌기 때문이다.
이름의 목적지가 바뀌어도 이미 맺은 연결은 따라가지 않는다.
대기 DB로 전환한 뒤 앱의 기존 연결이 어떻게 되는지 보여 준다.
DB 이름의 목적지
DB A앱의 연결
DB A와 연결 중DB 이름의 목적지
DB B앱의 기존 연결
DB A · 끊김새로 조회한 목적지
DB B앱의 새 연결
DB B와 연결Multi-AZ 전환은 DB 이름의 목적지를 바꾸지만 기존 연결을 옮기지는 않는다. 바뀐 목적지로 다시 연결해야 한다.
이름과 현재 연결이 모두 DB A로 이어져 있다.
RDS Multi-AZ DB instance의 예시다. DNS 캐시 갱신과 연결 재생성은 함께 필요하며, 실제 전환 시간은 표시하지 않는다.
다시 연결할 때 조심할 것
연결이 끊긴 요청을 다시 보내는 것까지는 자연스럽다.
조회는 몇 번을 다시 보내도 결과가 같으니 문제가 없다.
쓰기는 조금 다르다.
응답을 받지 못했어도 데이터베이스에는 이미 저장됐을 수 있다.
그 상태에서 같은 결제 요청을 다시 보내면 결제가 두 번 일어난다.
이럴 때 쓰는 개념이 멱등성이다.
같은 요청을 다시 보내도 추가 효과가 생기지 않는 작업을 멱등하다고 한다.
요청마다 고유한 번호를 붙여 이미 처리한 번호는 건너뛰는 식으로 만든다.
유지보수 날을 미리 준비하는 법
| 일어나는 일 | 앱이 겪는 것 | 미리 해 둘 것 |
|---|---|---|
| 유지보수 창의 패치 | 짧은 중단이나 전환 | 창을 한가한 시간대로 옮기기 |
| 장애 조치 | 이름이 새 IP를 가리킴 | 이름 조회 캐시를 짧게 두기 |
| 연결 재사용 | 끊긴 연결로 계속 실패 | 쓰기 전에 연결 상태 확인하기 |
AWS의 유지보수 문서도 창은 사용량이 가장 적은 시간에 두라고 권한다.
백업 시간대와 겹치게는 정할 수 없으니 둘을 함께 보고 정한다.
장애 조치는 실제로 한 번 겪어 보는 것이 가장 확실하다.
Multi-AZ 인스턴스에는 재부팅할 때 장애 조치를 함께 일으키는 옵션이 있다.
한가한 시간에 이 옵션으로 전환을 일으키고, 앱이 재시작 없이 다시 붙는지 확인한다.
RDS의 이벤트 구독을 걸어 두면 장애 조치가 시작될 때 이메일이나 문자로 알림이 온다.
그러면 앱 오류가 늘어난 시각과 전환 시각을 바로 맞춰 볼 수 있다.
연결 관리를 앱 밖으로 빼고 싶다면 RDS Proxy도 있다.
RDS Proxy는 앱과 데이터베이스 사이에서 연결을 모아 관리하고, 장애 때 앱의 연결을 유지한 채 대기 인스턴스로 다시 붙는다.
프록시는 데이터베이스 인스턴스의 vCPU 수에 따라 시간당 요금이 따로 붙는다.
연결 문제가 실제로 잦을 때 검토해도 늦지 않다.