SSD Nodes Learn 🎉 VPS $5.50/월부터
가이드 Matt Connor작성자 Matt Connor · 업데이트됨 2026-08-13

VPS 스냅샷 백업 클론 차이점과 올바른 데이터 보호 전략

VPS 스냅샷은 백업이 아닙니다. 스냅샷, 백업, 클론의 기술적 차이와 장애 도메인 개념을 설명합니다. 제공업체 계정 정지나 리전 장애 시 데이터를 안전하게 보존하는 방법과 클론 생성 후 반드시 수행해야 할 설정 작업을 확인하십시오.

스냅샷, 백업, 클론의 실제 의미

VPS 스냅샷은 서버의 디스크 이미지를 의미하며, 서비스 제공업체의 인프라 내 귀하의 계정 안에 저장됩니다. 백업은 데이터의 독립적인 사본으로, 원본을 보관하던 제공업체의 도움 없이도 다른 곳에서 복구할 수 있습니다. 클론은 스냅샷에서 배포된 새로운 인스턴스이며, 원본의 식별 정보를 포함하여 완전히 동일한 상태로 시작합니다.

이들은 서로 다른 문제를 해결합니다. 스냅샷은 잘못된 업그레이드를 몇 분 만에 되돌릴 수 있지만, 계정이 폐쇄된 경우에는 아무런 도움이 되지 않습니다. 백업은 제공업체가 서비스를 중단하더라도 데이터를 보존할 수 있게 해주지만, 먼저 머신을 재구축해야 하므로 복구에 더 많은 시간이 소요됩니다. 클론은 한 번의 단계로 두 번째 실행 중인 서버를 제공하지만, 결과적으로 동일한 머신이라고 인식하는 두 대의 서버가 생성됩니다.

VPS 스냅샷이 백업이 아닌 이유

문제는 이미지의 품질이 아니라 장애 도메인입니다. 스냅샷은 서버와 동일한 제공업체의 스토리지 플랫폼에 저장되며, 대개 서버와 같은 리전(region)에 위치하고 항상 동일한 계정 내에 존재합니다. 단 하나의 사건으로 서버와 스냅샷이 동시에 사라질 수 있습니다.

  • 계정이 정지되거나, 결제가 실패하거나, 로그인 정보가 탈취되는 경우입니다.
  • API 접근 권한이 있는 사람이나 스크립트가 인스턴스를 삭제하는 경우입니다. 많은 제공업체에서 인스턴스를 삭제하면 스냅샷도 함께 삭제됩니다. 다르게 동작할 것이라고 가정하기 전에 제공업체의 문서화된 동작 방식을 반드시 확인하십시오.
  • 리전에 장애가 발생하여 해당 리전 내의 모든 자원에 동시에 접근할 수 없게 되는 경우입니다.
  • 서버에서 root 권한으로 실행 중인 무언가가 /root에 남겨둔 제공업체 API 토큰을 찾아내어, 디스크를 건드리기 전에 스냅샷을 먼저 삭제하는 경우입니다.

백업이란 이 네 가지 상황 모두에서 살아남는 복사본을 의미합니다. 판단 기준은 단 하나입니다. 오늘 오후에 제공업체 계정이 사라진다면 무엇을 복구할 수 있으며, 어디에 복구할 것인가 하는 점입니다. 이 질문을 통과하지 못하는 것은 모두 롤백 도구일 뿐입니다. 스냅샷은 복구 속도가 가장 빠르므로 계속 사용하십시오. 그 후 제공업체가 제어할 수 없는 스토리지에 두 번째 복사본을 보관하십시오.

오래된 규칙은 여전히 유효합니다. 데이터 사본 3개를 두 가지 종류의 스토리지에 보관하고, 그중 하나는 플랫폼 외부에 두어야 합니다. 제공업체 스냅샷과 별도 인프라의 restic 백업 저장소를 조합하면 두 가지 요소만으로 이 규칙을 충족할 수 있습니다.

실행 중인 데이터베이스의 스냅샷을 복구할 때 문제가 발생하는 이유

공급자가 제공하는 스냅샷은 특정 시점의 블록 장치를 그대로 복사합니다. 이 과정에서 애플리케이션을 먼저 중지하도록 요청하지 않으며, 페이지 캐시에 남아 있는 데이터는 확인할 수 없습니다. 따라서 이 이미지는 기껏해야 '크래시 일관성(crash-consistent)' 수준에 머무릅니다. 이는 마치 누군가 전원 케이블을 갑자기 뽑았을 때의 디스크 상태와 정확히 일치합니다.

대부분의 스택은 이를 처리할 수 있습니다. ext4와 XFS는 마운트 시 저널을 재생(replay)하여 파일 시스템을 복구합니다. PostgreSQL은 시작 시 쓰기 전용 로그(write-ahead log)를 재생하며, 로그에는 다음과 같은 메시지가 기록됩니다.

LOG:  database system was not properly shut down; automatic recovery in progress

InnoDB도 동일한 작업을 수행하며 시작 중에 자체적인 크래시 복구 메시지를 출력합니다. 이러한 복구 과정은 데이터베이스가 설계된 대로 작동하는 것이므로, 조용한 상태의 PostgreSQL이나 MySQL을 단일 볼륨 스냅샷으로 복구하면 대개 정상적으로 작동합니다.

크래시 일관성만으로는 충분하지 않은 실제 사례들이 존재하며, 이러한 경우 문제가 발생합니다. 데이터가 두 개의 볼륨에 걸쳐 있는 경우, 루트 디스크와 별도의 데이터 디스크가 서로 다른 시점에 스냅샷으로 저장됩니다. 이로 인해 데이터 파일과 로그 디렉터리 간의 불일치가 발생하며, 복구 시점에 재생할 올바른 데이터가 없게 됩니다. 애플리케이션이 fsync를 호출하지 않고 작성한 파일(예: 절반만 수신된 업로드 파일이나 큐 파일)은 잘린 상태로 복구될 수 있습니다. 애플리케이션이 메모리에 보관하다가 타이머에 맞춰 기록하는 데이터는 이미지에 포함되지 않습니다.

따라서 스냅샷을 생성하기 전에 디스크에 덤프를 작성하십시오. 그러면 라이브 데이터 파일의 상태가 어떻든, 내부적으로 일관성이 보장되는 파일을 이미지에 포함할 수 있습니다.

sudo -u postgres pg_dumpall --clean --file=/var/backups/pg-$(date +%F).sql
sudo mysqldump --single-transaction --routines --all-databases > /var/backups/mysql-$(date +%F).sql

--single-transaction는 반복 읽기(repeatable-read) 트랜잭션 내에서 덤프를 실행하므로, 쓰기 작업을 차단하지 않고도 InnoDB 테이블의 일관된 덤프를 생성합니다. 이는 MyISAM 테이블에는 적용되지 않으며, MyISAM 테이블은 잠금을 수행하거나 서버를 중지해야 합니다. 덤프를 신뢰하기 전에 내용이 비어 있거나 잘리지 않았는지 확인하십시오. 전체 tail -n 1 /var/backups/mysql-$(date +%F).sql 작업은 Dump completed 주석으로 끝납니다.

별도의 데이터 볼륨이 있는 경우, 스냅샷에 필요한 몇 초 동안 해당 볼륨을 고정(freeze)할 수 있습니다.

sudo fsfreeze -f /srv
# take the snapshot from your provider's panel or API
sudo fsfreeze -u /srv

데이터 볼륨만 고정하십시오. /은 절대 고정하지 마십시오. 루트 파일 시스템을 고정하면 고정 해제 명령을 입력할 셸을 포함하여 시스템의 모든 쓰기 작업이 차단됩니다. 이 경우 시스템에서 잠겨 버리며 강제 재부팅을 해야 할 수도 있습니다.

오프사이트 백업: restic 또는 Borg

스냅샷은 빠른 절반입니다. 오프사이트 복사본은 서비스 제공업체에 문제가 생겨도 데이터를 보존할 수 있는 나머지 절반입니다. restic은 중복 제거, 클라이언트 측 암호화를 지원하며 S3 호환 객체 스토리지, SFTP, 일반 디렉터리에 데이터를 기록할 수 있어 기본 선택지로 적합합니다. 백업 저장소는 높은 IOPS보다는 용량이 중요하므로 오프사이트 대상으로서의 스토리지 VPS를 활용하는 것이 좋습니다.

sudo apt update && sudo apt install -y restic
sudo sh -c 'umask 077; head -c 24 /dev/urandom | base64 > /root/.restic-pass'
sudo chmod 600 /root/.restic-pass
sudo cat /root/.restic-pass

해당 암호(passphrase)를 지금 바로 이 서버가 아닌 다른 장치의 비밀번호 관리자에 저장하십시오. restic 저장소는 암호 없이는 열 수 없으며 복구 경로도 존재하지 않습니다. 만약 암호의 유일한 사본이 방금 손실된 서버에 있었다면, 백업 데이터는 암호화된 무의미한 데이터 조각에 불과합니다.

export RESTIC_REPOSITORY="s3:https://s3.example.com/vps-backups"
export RESTIC_PASSWORD_FILE=/root/.restic-pass
export AWS_ACCESS_KEY_ID="..."
export AWS_SECRET_ACCESS_KEY="..."
sudo -E restic init
sudo -E restic backup /etc /srv /var/backups
sudo -E restic snapshots

sudo -E는 해당 변수들을 유지합니다. 이 설정이 없으면 root 계정은 초기화된 환경을 사용하게 되어 restic이 저장소 위치를 찾을 수 없다고 보고합니다. restic snapshots을 실행하면 방금 수행한 백업 작업이 호스트 및 경로와 함께 나열되어야 합니다. 저장소 자체를 주기적으로 검증하고, 단순히 구조만 확인하는 데 그치지 말고 실제 데이터를 일부 읽어 들여 복구 테스트를 수행하십시오.

sudo -E restic check --read-data-subset=5%
sudo -E restic restore latest --target /tmp/restore-check
sudo -E restic forget --keep-daily 7 --keep-weekly 4 --keep-monthly 6 --prune

테스트하지 않은 백업은 추측일 뿐입니다. 최소 한 번은 다른 VPS로 데이터를 복구해 보고, 소요 시간을 기록하십시오. 그 시간이 바로 귀하의 실제 복구 목표(RTO)가 됩니다. Borg는 또 다른 확실한 선택지이며 객체 스토리지 대신 SSH를 통해 저장소를 관리합니다. 두 도구의 장단점은 restic과 BorgBackup 비교에서 다룹니다.

복제된 VPS를 운영 환경에 투입하기 전 수정해야 할 사항

복제본은 원본의 정확한 복사본입니다. 이것이 복제의 장점이자 문제입니다. 원본을 고유하게 만들었던 모든 요소가 중복되며, 이 중복된 요소들은 충돌을 일으킵니다.

SSH 호스트 키를 재생성하십시오. 복제본은 원본의 /etc/ssh/ssh_host_* 파일을 그대로 가지고 있으므로, 두 서버가 동일한 호스트 ID를 제시하게 됩니다. 한 서버를 제어하는 공격자는 해당 키를 신뢰하는 모든 클라이언트에 대해 다른 서버를 사칭할 수 있습니다. 클라이언트는 이미 해당 키를 알고 있으므로 SSH는 경고를 발생시키지 않습니다.

sudo rm -f /etc/ssh/ssh_host_*
sudo ssh-keygen -A
sudo systemctl restart ssh
ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub

ssh-keygen -A는 데몬이 요구하는 모든 유형의 새로운 키를 생성합니다. 마지막 명령으로 확인한 지문(fingerprint)이 원본과 달라야 합니다. sshd를 재시작해도 기존 연결은 끊기지 않으므로 현재 세션은 유지됩니다. 복제본에 누군가 접속하기 전에 이 작업을 수행하십시오. 나중에 수행하면 이미 기존 키를 신뢰하던 모든 클라이언트에서 WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! 오류가 발생하며, 사용자는 먼저 ssh-keygen -R <host>를 실행해야 합니다.

머신 ID를 초기화하십시오. /etc/machine-id는 systemd가 최초 부팅 시 한 번 생성하는 고유 식별자이며, 복제본은 이를 그대로 상속받습니다.

sudo truncate -s 0 /etc/machine-id
sudo rm -f /var/lib/dbus/machine-id
sudo ln -s /etc/machine-id /var/lib/dbus/machine-id
sudo reboot

/etc/machine-id 파일을 비우면 다음 부팅 시 systemd가 새로운 값을 생성합니다. 파일을 삭제하지 않고 내용을 비우는(truncate) 이유가 바로 이것입니다. 머신 ID가 중복되면 두 가지 문제가 발생합니다. DHCP로 주소를 할당받는 이미지의 경우, systemd-networkd는 기본적으로 머신 ID에서 DHCP 클라이언트 식별자를 도출합니다. 따라서 두 복제본이 동일한 클라이언트로 간주되어 서버로부터 같은 IP 주소를 할당받게 됩니다. 또한 journald는 모든 로그 항목에 머신 ID를 기록하므로, 중앙 로그 수집기는 두 서버의 로그를 하나의 머신에서 발생한 것으로 처리합니다. 재부팅 후 cat /etc/machine-id을 실행하여 값이 변경되었는지 확인하십시오.

호스트네임을 변경하십시오.

sudo hostnamectl set-hostname web-02
grep 127.0.1.1 /etc/hosts

hostnamectl/etc/hostname를 기록하고 즉시 이름을 적용합니다. 하지만 /etc/hosts 파일은 수정하지 않으므로, 127.0.1.1 라인을 편집하여 일치시켜야 합니다. 이를 건너뛰면 새로운 이름으로 주소를 해석할 수 없게 되어, 모든 sudo 호출이 조회 실패를 기다리다가 sudo: unable to resolve host web-02: Name or service not known 메시지를 출력하게 됩니다.

이미지에 포함된 모든 자격 증명을 교체하십시오. 복제본은 원본의 비밀 정보를 그대로 가지고 있으며, 이제 두 대의 기계가 원본처럼 동작할 수 있습니다. SSH authorized_keys 파일, 공급자 및 DNS API 토큰, 애플리케이션 .env 파일, 데이터베이스 비밀번호, TLS 개인 키, 모니터링 등록 토큰, restic 저장소 비밀번호 등을 모두 확인하십시오. 다음 명령으로 대부분의 항목을 찾을 수 있습니다.

sudo grep -rIlE 'PASSWORD|SECRET|TOKEN|API_KEY' /etc /srv /opt /home 2>/dev/null
sudo find / -name '.env' -not -path '/proc/*' -not -path '/sys/*' 2>/dev/null

복제본이 트래픽을 처리하지 않는 테스트용 사본이라면, 교체(rotate) 대신 폐기(revoke)하십시오. 운영 환경의 API 토큰이 포함된 스테이징 서버는 보안 패치가 미흡한 운영 서버와 다를 바 없습니다.

중복 실행되는 작업을 중지하십시오. 동일한 crontab을 실행하는 두 서버는 같은 분에 동일한 외부 시스템으로 요청을 보냅니다.

systemctl list-timers --all
sudo crontab -l
sudo ls -l /etc/cron.d /etc/cron.daily

restic의 경우 단순히 오류가 발생하는 것을 넘어 보관 정책을 손상시키기 때문에 특별히 주의해야 합니다. restic은 각 스냅샷에 호스트네임을 태그로 지정하며, restic forget --keep-daily 7은 호스트별로 정책을 적용합니다. 동일한 호스트네임을 가진 두 기계는 하나의 호스트로 간주되므로, 원본의 스냅샷이 삭제되는 동안 복제본에서 생성된 스냅샷이 7개의 "일일" 스냅샷을 모두 차지할 수 있습니다. 첫 백업을 실행하기 전에 호스트네임을 수정하거나 복제본의 타이머를 중지하십시오. certbot의 경우는 더 간단합니다. 동일한 도메인에 대해 인증서를 갱신하려는 두 서버는 인증 기관의 중복 인증서 발급 제한에 걸리게 되며, 나중에 실행된 서버는 이미 너무 많은 인증서가 발급되었다는 오류와 함께 실패합니다. 도메인이 여전히 원본을 가리키고 있는 복제본은 HTTP 챌린지를 통과할 수 없으므로, 복제본에서는 갱신 기능을 비활성화하십시오.

모니터링 에이전트를 처리하십시오. 대부분의 에이전트는 호스트네임이나 설치 시 생성된 ID 파일로 기기를 식별합니다. 따라서 하나의 호스트로 보고하는 두 에이전트는 메트릭을 하나의 시계열 데이터로 섞어버립니다. 이로 인해 CPU 그래프에는 실제 어떤 단일 기계도 생성하지 않은 값이 표시되고, 경고가 불안정하게 발생합니다. 복제본의 에이전트를 중지 및 삭제하거나, 공급업체의 문서화된 절차에 따라 새로운 호스트네임으로 다시 등록하십시오.

네트워크 설정에서 원본의 주소를 확인하십시오. 이미지가 netplan에 고정 IP 주소를 포함하고 있다면, 복제본은 다른 기계의 IP를 점유하게 됩니다.

ip -br addr
sudo grep -r addresses /etc/netplan/

복제본을 템플릿으로 사용할 경우 cloud-init 상태를 초기화하십시오.

sudo cloud-init clean --logs

이 명령은 /var/lib/cloud 아래의 cloud-init 상태를 제거합니다. 따라서 다음 부팅 시 첫 부팅 모듈이 다시 실행되며, 여기에는 SSH 호스트 키가 없을 경우 새로 생성하는 과정이 포함됩니다. 일부 버전은 머신 ID를 초기화하는 플래그도 제공합니다. 다른 곳의 플래그 목록을 무조건 신뢰하기보다, 자신의 이미지에서 cloud-init clean --help을 실행하여 지원 여부를 확인하십시오.

상황별 활용 가이드

위험한 업그레이드를 되돌릴 때: 스냅샷을 사용합니다. 변경 작업 몇 분 전에 스냅샷을 생성하고 업그레이드를 진행합니다. 문제가 발생하면 이미지를 복원하십시오. 복원 시 스냅샷 이후의 모든 쓰기 작업이 삭제되므로, 실시간 트래픽이 발생하는 서버라면 먼저 데이터베이스를 덤프하고 손실될 데이터 범위를 정확히 파악해야 합니다. 10분 정도 오프라인 상태로 전환할 수 있는 do-release-upgrade라면 스냅샷만으로 충분한 계획이 됩니다.

더 큰 플랜으로 마이그레이션할 때: 클론을 배포합니다. 스냅샷을 기반으로 더 큰 플랜의 클론을 생성합니다. 위에서 언급한 식별 정보 목록을 정리한 뒤, 트래픽을 전환하기 전에 해당 서버의 IP로 테스트를 수행하십시오. 전환을 신속하게 처리하려면 하루 전에 DNS TTL을 낮추고, 새 서버가 실제 트래픽을 안정적으로 처리할 때까지 기존 서버를 유지하십시오. 더 큰 플랜이 실제 워크로드에서 더 빠른지 두 서버에서 동일한 벤치마크 방식을 사용하여 먼저 확인해야 합니다. 하드웨어가 붐비는 환경에서의 vCPU 증가는 항상 성능 향상으로 이어지지는 않기 때문입니다.

템플릿을 만들 때: 정리된 머신을 스냅샷으로 저장합니다. 서버 하나를 설치하고 보안 설정을 마친 뒤, 이미지를 생성하기 전에 고유한 정보를 모두 제거하십시오. 호스트 키, 머신 ID, 개인용 authorized_keys, 자격 증명, cloud-init 설정 등을 모두 삭제합니다. 그 상태를 스냅샷으로 저장하십시오. 이 템플릿으로 배포된 모든 인스턴스는 첫 부팅 시 고유한 식별 정보를 생성하므로, 위에서 언급한 체크리스트를 매번 수행할 필요가 없습니다. 이 템플릿을 새 VPS에서 수행하는 표준 초기 10분 작업과 결합하면, 반복해야 할 작업을 미리 템플릿에 포함할 수 있습니다.

FAQ

VPS 스냅샷은 백업입니까?

아닙니다. 스냅샷은 원본 서버와 장애 도메인을 공유하기 때문입니다. 스냅샷은 일반적으로 같은 리전 내의 제공자 스토리지, 즉 귀하의 계정 안에 저장됩니다. 계정이 정지되거나, API key가 탈취되거나, 실수로 인스턴스를 삭제하면 서버와 스냅샷이 한 번에 사라질 수 있습니다. 많은 제공자가 인스턴스 삭제 시 스냅샷도 함께 삭제하도록 설계했습니다. 스냅샷은 가장 빠른 롤백 수단이므로 계속 생성하되, 제공자가 제어할 수 없는 별도의 인프라에 암호화된 사본을 하나 더 보관하십시오.

스냅샷을 찍기 전에 데이터베이스를 중지해야 합니까?

항상 그럴 필요는 없지만, 스냅샷의 상태를 감수해야 합니다. 제공자의 스냅샷은 크래시 일관성(crash-consistent)을 보장합니다. 즉, 전원이 갑자기 차단되었을 때의 디스크 상태와 동일합니다. PostgreSQL과 InnoDB는 시작 시 이 상태에서 복구하며, PostgreSQL은 복구 과정에서 database system was not properly shut down; automatic recovery in progress 로그를 남깁니다. 서로 다른 시점에 스냅샷을 찍은 두 볼륨에 데이터가 걸쳐 있거나, 애플리케이션이 fsync 없이 데이터를 기록하는 경우에는 복구를 보장할 수 없습니다. 먼저 pg_dumpall이나 mysqldump --single-transaction를 디스크에 기록하여, 일관성이 보장된 파일이 이미지에 포함되도록 하십시오.

복제된 두 서버가 왜 같은 IP 주소를 두고 충돌합니까?

/etc/machine-id를 공유하기 때문입니다. DHCP를 사용하는 이미지에서 systemd-networkd는 기본적으로 machine ID를 기반으로 DHCP 클라이언트 식별자를 생성합니다. 따라서 두 복제본이 동일한 클라이언트로 간주되어 DHCP 서버가 같은 주소를 할당합니다. /etc/machine-id의 내용을 비우고, /var/lib/dbus/machine-id을 삭제한 뒤, /etc/machine-id로 심볼릭 링크를 다시 생성하고 재부팅하면 systemd가 새로운 값을 생성합니다. 또 다른 흔한 원인은 /etc/netplan/에 기록된 고정 IP 주소가 그대로 복제된 경우입니다. ip -br addr 명령으로 확인하십시오.

복제본을 운영 환경에 투입하기 전 가장 빠르게 안전성을 확인하는 방법은 무엇입니까?

원본과 다음 네 가지를 비교하십시오. 양쪽에서 ssh-keygen -lf /etc/ssh/ssh_host_ed25519_key.pub을 실행하여 지문(fingerprint)이 다른지 확인합니다. 양쪽에서 cat /etc/machine-id를 실행하여 값이 다른지 확인합니다. hostnamectl status을 실행하여 호스트 이름이 새로 지정되었고 정상적으로 해석되는지 확인하여 sudo 경고가 발생하지 않도록 합니다. 마지막으로 systemctl list-timers --all를 실행하여 백업, 인증서 갱신, 모니터링 에이전트 등 공유 시스템과 통신하는 모든 타이머를 중지하고, 어떤 서버가 해당 작업을 수행할지 결정하십시오.