Jungseob's Note
포스트

백업이 단순하지 않은 이유, 복사부터 복구 검증까지

백업을 설계할 때 복사본, 과거 시점, 보존 주기, 데이터베이스 일관성, 오프사이트 저장과 실제 복구 검증이 차례로 필요한 이유를 정리한다.

백업이 단순하지 않은 이유, 복사부터 복구 검증까지

TL;DR

  • 다른 디스크에 파일을 옮기는 것만으로는 백업이 되지 않는다. 별도 복사본이 있어도 삭제나 랜섬웨어가 그대로 반영되면 과거 상태를 되찾기 어렵다. 복사본의 위치와 복구할 시점을 함께 설계해야 한다.
  • RPO와 보존 기간은 서로 다른 요구다. 백업 간격은 감당할 데이터 손실을 결정하고 보존 기간은 뒤늦게 발견한 손상에 대응할 범위를 정한다. 최근에는 촘촘하게, 오래전에는 성기게 남기는 GFS 방식으로 저장 부담을 줄일 수 있다.
  • 파일이 복사됐다고 애플리케이션까지 복구되는 것은 아니다. Docker 파일 권한, 데이터베이스 일관성, 객체 저장소의 메타데이터와 요청 비용이 각각 문제를 만든다. 신뢰할 만한 도구를 쓰더라도 실제 복원을 시험해야 한다.
  • 3-2-1은 복사본 수뿐 아니라 함께 실패할 가능성을 줄이는 원칙이다. 매체와 장소를 분산하고 백업 주기·보존·복원 시험을 함께 운영해야 한다. 일정 실행에 사용하는 시간대와 서머타임도 확인 대상이다.

가족사진을 옮긴 외장 디스크는 유일한 원본이었다

Aleksandar Filipovski의 가족은 컴퓨터 공간을 비우려고 사진을 외장 하드 하나로 모았다. 이후 아버지가 그 디스크를 TV 셋톱박스에 연결했고 포맷 안내를 받아들인 순간 사진에 접근할 수 없게 됐다. 다행히 사진은 복구했지만 문제를 사용자의 실수 하나로 설명할 수는 없었다. 복사본 없이 데이터를 한곳에 몰았고 기기는 포맷의 결과를 충분히 경고하지 않았다.

별도 복사본은 디스크 고장이나 도난, 저장 매체의 데이터 손상에 대비하는 출발점이다. 그러나 계속 연결된 장치에는 랜섬웨어가 접근할 수 있고 잘못된 삭제나 덮어쓰기도 일어날 수 있다. RAID 1처럼 현재 상태를 그대로 복제하는 방식은 디스크 하나의 고장에는 도움이 되지만 잘못된 변경을 이전으로 되돌릴 이력을 제공하지는 않는다. 과거 시점으로 돌아가려면 스냅샷과 그 이력을 보존하는 별도의 설계가 필요하다.

얼마나 잃어도 되는지와 얼마나 오래 남길지

RPO, 즉 복구 시점 목표는 장애 때 감당할 수 있는 데이터 손실의 시간 범위다. 사진을 일주일마다 백업한다면 다음 백업 직전에는 거의 일주일치 변경을 잃을 수 있다. 그 손실을 받아들일 수 있는지에 따라 백업 간격을 정한다. 글에서 금융기관과 작은 기업의 서로 다른 간격을 비교하는 이유도 모든 데이터에 동일한 빈도를 적용할 수 없기 때문이다.

보존 기간은 다른 문제를 해결한다. 매일 백업하더라도 최근 14일치만 남기면 훨씬 전에 발생한 손상을 늦게 발견했을 때 정상 상태가 이미 사라졌을 수 있다. 반대로 아주 오래된 모든 날짜를 같은 정밀도로 보존할 필요는 없을 수 있다. 최근의 자세한 이력과 오래된 시점의 대표 이력을 나누는 이유다.

원문의 GFS 보존 예시는 일별 백업을 14일, 주별 백업을 7주, 월별 백업을 12개월 유지하는 방식이다. 새 일별 백업을 만들 때 가장 오래된 일별 이력은 지워도 주별·월별 이력은 더 오래 남는다. 이 수치는 설명을 위한 선택이며 모든 조직에 맞는 표준 보존 기간은 아니다. 데이터가 손상된 사실을 얼마나 늦게 알아차릴 수 있는지와 저장 비용을 함께 고려해야 한다.

중복 제거와 증분 백업으로 줄이는 비용

연속된 스냅샷에는 바뀌지 않은 파일이 많다. 매번 전체 사본을 저장하는 대신 같은 내용을 재사용하면 저장 공간을 줄일 수 있다. 원문은 rsnapshot의 하드 링크 방식을 예로 든다. 여러 시점의 디렉터리가 같은 파일 데이터를 참조하므로 오래된 디렉터리 항목을 제거해도 다른 링크가 남아 있는 데이터는 유지된다.

증분 백업은 인접한 백업 사이의 변경분을 저장하고 차등 백업은 마지막 전체 백업 이후의 변경분을 모은다. 어떤 데이터를 다시 저장하고 전송할지 줄이는 일은 원격 백업의 대역폭과 비용에도 영향을 준다. rsync로 파일을 가져오고 cron으로 실행하면 비교적 단순한 자동화처럼 보인다. 하지만 이 단계에서 다루는 것은 주로 파일의 복사와 이력이며 실행 중인 서비스의 복구 조건까지 해결된 것은 아니다.

Docker 볼륨과 데이터베이스는 복사 조건부터 다르다

홈랩에 적용하면 권한에서 먼저 막힐 수 있다. Docker 컨테이너가 root 소유 파일을 만들었는데 일반 사용자 권한의 cron 작업으로 백업하면 일부 파일을 읽지 못한다. 원문의 예시는 개별 장치 로그를 확인한 뒤에야 실패를 발견하는 상황이다. 백업 작업이 예약돼 있다는 사실과 필요한 모든 파일을 실제로 읽었다는 사실은 구분해야 한다.

데이터베이스에는 일관성 문제도 있다. 일부 변경은 메모리에 머물고 디스크 기록은 진행 중일 수 있으므로 실행 중인 파일을 단순 복사한 결과가 복원 가능한 상태라고 보장하기 어렵다. 글은 데이터베이스 덤프를 백업에 포함하고 필요한 볼륨 접근 권한을 확보하는 방향으로 해결한다. 모든 백업 프로세스에 무조건 광범위한 권한을 주자는 일반 규칙보다, 대상 데이터를 읽을 권한과 애플리케이션에 맞는 일관된 백업 방법을 확인하라는 요구로 이해할 수 있다.

3-2-1과 객체 저장소에서 추가되는 설계

복사본이 여러 개여도 같은 원인으로 함께 잃을 수 있다. 원문의 3-2-1 원칙은 원본을 포함한 복사본 3개, 서로 다른 종류의 매체 2개, 외부 장소에 둔 사본 1개다. 특정 하드웨어의 결함에 대비해 매체를 나누고 화재·침수·전원 사고에 대비해 장소를 나눈다. 클라우드나 가족의 집에 둔 장치가 오프사이트 후보가 될 수 있다.

Amazon S3 같은 객체 저장소를 쓰면 로컬 파일시스템과의 차이가 나타난다. 파일을 그대로 업로드하는 것만으로는 소유자나 접근 권한 같은 파일시스템 메타데이터가 원하는 형태로 보존되지 않으며 작은 파일을 많이 올리면 요청 비용도 중요해진다. 여러 파일을 tar 아카이브로 묶으면 메타데이터 보존과 요청 수 감소에 도움이 된다. 그러나 거대한 아카이브 하나를 매번 다시 만들면 기존의 증분·하드 링크 방식과 맞지 않으므로 데이터를 나누고 검증하는 설계가 더 필요하다. 원문의 50MB 청크는 이런 고민을 설명하는 예시이며 보편적 최적값은 아니다.

도구를 선택한 뒤에도 복원은 직접 확인해야 한다

이 정도 조건이 쌓이면 짧은 스크립트로 시작한 백업은 하나의 저장 시스템이 된다. 글은 직접 구현을 늘리기보다 Borg나 Restic처럼 검증된 도구를 선택하자는 결론에 이른다. 암호화, 청크 단위 중복 제거, 체크섬 같은 기능도 이 도구들이 맡는다. 다만 두 도구가 모든 저장소를 동일한 방식으로 지원한다는 뜻은 아니며 실제 목적지와 운영 조건에 맞춰 골라야 한다.

백업의 최종 검사는 복원이다. 원문은 6개월마다 복원 시험을 하자는 예를 들지만 그 간격이 모든 서비스에 충분하다고 보장하지는 않는다. 백업 파일이 존재하고 작업이 성공했다고 기록돼도 필요한 상태로 데이터를 되돌릴 수 있는지는 별도로 확인해야 한다. 저장 단계의 성공만으로 복구 능력을 대신 판단할 수 없다.

마지막의 새벽 2시·3시 예약 경고에는 시간대 조건이 붙는다. 연결된 Jon Jensen의 글은 서머타임 전환 때 Linux의 vixie-cron 작업이 겹쳐 실행됐던 경험을 설명한다. 모든 환경에서 그 시간이 위험하다는 뜻은 아니며 서버 시간대와 스케줄러 동작을 확인할 필요가 있다. 보충 글은 UTC 사용도 대안으로 제시한다. 파일 내용뿐 아니라 권한·애플리케이션 상태·저장 장소·시간까지 맞아야 복구 가능한 백업이 된다.

참고 자료

Aleksandar Filipovski — Backups aren’t simple

Jon Jensen — Avoid 2:00 and 3:00 am cron jobs!

원문 출처는 본문의 Source에서 확인할 수 있습니다.