운영 서버 한 대가 꺼졌다고 가정해 보겠습니다. 두 번째 서버에서 앱이 떠 있어도 사용자가 쓰던 주소가 그 서버로 향하고, 앱이 기존 데이터를 읽고 새 데이터를 저장할 수 있어야 서비스가 돌아옵니다. 얼쑤에서는 서버 두 대를 유지하고 추가 유료 인프라를 전제하지 않는 조건으로 Docker Compose를 확장하는 안과 가벼운 Kubernetes 배포판인 K3s를 쓰는 안을 비교했습니다. 비교 기준은 각 도구가 앱 실행, 접속, 쓰기 복구 중 어디까지 맡을 수 있는가였습니다.

정상 배포와 서버 전체 장애

10월 검토 당시 웹 입구와 백엔드, MySQL 컨테이너는 한 서버에 모여 있었습니다. 정상 배포에서는 그 서버가 살아 있습니다. 기존 백엔드 옆에 새 버전을 먼저 띄우고, 준비 상태를 확인한 뒤 웹 입구가 새 요청을 넘길 대상을 바꿀 수 있습니다. 기존 요청을 끝낼 때까지 이전 버전을 남겨 두는 블루그린 배포입니다. 익숙한 Compose를 확장하는 안을 먼저 검토하자는 권고는 여기서 나왔습니다. 새 배포 도구로 옮기지 않아도 이 문제를 줄일 방법이 있었기 때문입니다. 얼쑤의 Compose 블루그린 배포

서버 전체가 사라지면 조건이 달라집니다. 그 위의 두 백엔드와 사용자 요청을 받아 주던 입구, 쓰기를 받던 DB가 함께 영향을 받습니다. 두 번째 서버에서 앱을 켤 수 있어도, 사용자의 주소가 살아 있는 쪽으로 향해야 하고 앱은 쓰기를 안전하게 이어 갈 DB에 연결해야 합니다. 이미 저장된 녹음을 읽을 수 있는지도 확인해야 합니다. 검토에서는 실패한 지점에 따라 앱 실행, 사용자 접속, 데이터 복구를 따로 비교했습니다.

상황필요한 것성공을 판단할 수 있는 관측
정상 배포로 앱 버전을 바꾼다새 버전 준비 검사, 연결 전환, 이전 요청의 완료전환 전후 대표 요청과 진행 중이던 작업이 끝난다.
운영 서버 한 대를 잃는다살아 있는 앱, 접속 전환, 안전한 DB 쓰기 경로와 파일 접근같은 사용자 주소에서 읽기와 쓰기가 다시 성공한다.
삭제나 데이터 손상 이전으로 돌아간다되돌아갈 유효한 백업 사본과 복원 절차격리 환경에서 데이터를 복원하고 필요한 내용과 앱 동작을 확인한다.

두 번째 서버에서 확인한 세 가지

11월 운영 점검에서는 운영 서버의 블루·그린이 같은 쓰기 DB를 사용하고, 다른 서버에 대기 앱, 읽기 전용 DB 복제본, 백업 사본이 있는 것을 확인했습니다. 대기 앱은 자체 DB로 검증할 수 있게 구성돼 있었습니다. 운영 변경을 받아 오는 복제본과는 분리돼 있어, 대기 앱이 응답한다는 사실만으로 운영 데이터를 읽고 쓸 수 있다고 판단할 수는 없었습니다.

점검 시점에는 복제본이 운영 DB의 변경을 받아 적용하고 있었고, MySQL이 표시한 지연은 0초였습니다. 비동기 복제에서는 운영 DB가 저장을 확인한 변경이 복제본에 아직 도착하지 않았을 수 있습니다. 한 번의 지연 수치로 장애 시 데이터 손실량을 정할 수 없는 이유입니다. 쓰기를 넘기려면 이전 DB가 다시 쓰지 못하도록 막고, 복제본이 어디까지 적용했는지 확인한 뒤 새 쓰기 대상으로 지정해야 합니다. MySQL 복제 문서

백업 사본을 다시 여는 정기 시험은 격리 환경에서 약 99초에 통과했습니다. 다른 리허설에서는 장애를 선언한 뒤 기존 쓰기 차단, 백업 복원, 앱 기동, 내부 접속 전환을 거쳐 새 쓰기가 성공하기까지 32.82초를 기록했습니다. 두 수치는 서로 다른 시험에서 나왔습니다. 첫 시험은 사본을 복원할 수 있는지, 두 번째는 같은 호스트의 한 MySQL 안에서 리허설용 DB 공간을 나눠 전환 절차가 끝까지 이어지는지 확인했습니다. 실제 운영 서버를 잃은 상황에서 공개 주소와 쓰기를 복구하는 시간은 측정하지 않았습니다. 얼쑤의 DB 쓰기 전환 검증

Kubernetes로 옮겼을 때 달라지는 범위

Kubernetes의 Deployment는 선언한 수의 앱 인스턴스를 유지하고 버전을 점진적으로 바꿉니다. 다른 호스트에 여유 용량이 있고 그곳에서 이미지와 설정을 가져올 수 있다면, 호스트가 사라진 뒤 앱을 다시 배치하는 데에도 도움이 됩니다. 팀이 여러 서비스를 여러 호스트에 반복해서 배치하거나 인스턴스 수를 자주 조절해야 한다면 직접 작성한 배포 도구의 부담을 줄일 수 있는 부분입니다. Kubernetes Deployment 문서

앱을 옮길 새 호스트와 클러스터를 관리하는 기능이 살아 있어야 한다는 조건도 있습니다. 두 대로 시험할 때는 한 대에 관리 기능을 두고 다른 한 대를 실행 노드로 쓰는 안을 검토했습니다. 관리 서버가 멈추면 이미 실행 중인 앱은 남아 있을 수 있지만 새 배치와 클러스터 차원의 자동 복구는 진행할 수 없습니다. K3s의 내장 etcd는 클러스터 상태를 기록할 때 과반수 동의를 요구합니다. 두 멤버 중 한 대를 잃으면 남은 한 대로는 과반수를 만들 수 없습니다. 그래서 이 방식의 고가용성 구성은 관리 서버를 최소 3대 둡니다. 외부 저장소를 쓰면 관리 서버 2대도 가능하지만, 이번 조건에서 그 저장소까지 장애를 견디게 할 구성은 확인하지 못했습니다. 운영 앱이 쓰는 DB와 클러스터 설정을 저장하는 DB도 역할이 다릅니다. K3s 내장 etcd 구성 · K3s 외부 DB 구성

당시 검토에서는 평소 배포 중단부터 줄이는 데 Compose를 확장하는 방식을 우선 권고했습니다. 기존 배포 경로에 새 인스턴스 준비와 요청 전환을 추가하는 것으로 당장의 문제를 다룰 수 있었기 때문입니다. K3s로 옮기면 여러 서버의 앱 배치는 선언으로 관리할 수 있지만, 이미지 전달과 클러스터 상태 저장소를 함께 운영해야 합니다. 접속 주소와 DB 쓰기 경로의 전환은 두 안에서 공통으로 남습니다. 이후 운영에서 확인한 것은 Compose로 실행한 블루그린 배포와 복구 준비였습니다.

다음 도구를 고르기 전에 시험할 것

다음 리허설을 설계한다면 접속과 쓰기가 실제로 함께 돌아오는지를 시험 기준으로 삼을 수 있습니다.

  1. 격리 환경에서 시각과 식별자를 붙인 쓰기를 남기고, 정상 응답을 받은 항목을 기록합니다.
  2. 운영 역할의 서버를 끊은 시점부터 시간을 잽니다. 시험용 사용자 주소로 다시 접속해 이전 데이터 읽기, 새 쓰기, 기존 파일 접근이 성공하는 시각을 각각 기록합니다.
  3. 마지막으로 복구된 쓰기를 처음의 기록과 대조합니다. 원래 서버가 돌아왔을 때도 한 DB만 쓰기를 받는지 확인합니다.

팀이 서비스가 멈춰도 되는 시간(RTO, 복구 시간 목표)과 잃어도 되는 데이터의 시간 범위(RPO, 복구 지점 목표)를 정하면, 시험에서 잰 값을 그 기준과 비교할 수 있습니다. 앱을 다른 곳에 띄우는 데 시간이 걸리면 자동 배치를 비교할 이유가 생깁니다. 앱이 떠도 같은 주소에서 접근하거나 쓰기를 재개하는 데 시간이 걸린다면, 접속 전환이나 DB 복구가 먼저 다룰 대상입니다.