DigitalOcean에서 Hetzner로 — 월 $1,432를 $233으로 줄인 무중단 이전기
6단계 무중단 이전 절차로 248GB 데이터와 65GB 파일을 다운타임 0분으로 이전한 실전 마이그레이션 기록이다.
왜 옮겼나
클라우드 비용이 점점 부담스러워지는 상황에서, 한 터키 소프트웨어 회사가 DigitalOcean을 Hetzner로 교체했다. 이유는 단순했다. "steady-state 워크로드에서 가격 대비 성능이 더 이상 합리적이지 않다."
결과부터 보면:
| 항목 | DigitalOcean | Hetzner |
|---|---|---|
| 월 비용 | $1,432 | $233 |
| 연 절감액 | — | $14,388 |
| CPU | 32코어 | 96코어 |
| RAM | 192GB | 256GB DDR5 |
비용은 83% 절감, 성능은 3배 이상 향상이다.
[💡 잠깐! 이 용어는?] Hetzner: 독일에 본사를 둔 유럽 호스팅 업체. 전용 서버(Dedicated Server)와 클라우드 VM 모두 제공하며, 특히 전용 서버의 가격 대비 성능이 월등하다고 알려져 있다.
이전 대상 스택
이 사례의 서버는 단순하지 않다. 동시에 다음을 운영하고 있었다:
- Nginx — 웹 서버 / 리버스 프록시 (설정 파일 34개)
- PHP — 애플리케이션 런타임
- MySQL 8.0 — 248GB 데이터베이스
- Neo4J — 그래프 데이터베이스
- 웹 파일 — 65GB, 파일 150만 개
이걸 다운타임 없이 이전해야 한다.
6단계 무중단 이전
1단계: 새 서버 스택 구축
Hetzner에 동일 스택을 구성한다. 기존 서버와 동일한 버전의 Nginx, PHP, MySQL 8.0, Neo4J를 설치한다.
# Ubuntu 22.04 기준
sudo apt update && sudo apt upgrade -y
sudo apt install nginx php8.3-fpm mysql-server -y
# MySQL 버전 확인 (기존 서버와 일치해야 함)
mysql --version
# mysql Ver 8.0.xx이 단계에서 실제 데이터는 아직 없다. 새 서버가 정상 작동하는 환경인지만 확인한다.
2단계: 웹 파일 복제 (rsync)
65GB, 150만 개 파일을 rsync로 이전한다. rsync는 변경된 파일만 재전송하므로, 초기 이전 후 계속 동기화 상태를 유지하는 데 적합하다.
# 기존 서버에서 실행
rsync -avz --progress \
/var/www/html/ \
user@hetzner-ip:/var/www/html/
# 이전 후 검증: 파일 수 비교
find /var/www/html -type f | wc -l
# → 1,500,000 확인이 과정은 시간이 오래 걸린다. 초기 전송 후에는 컷오버 직전에 한 번 더 rsync를 실행해 변경분만 동기화하면 된다.
3단계: MySQL 마스터-슬레이브 복제
248GB 데이터베이스는 가장 까다롭다. mydumper를 사용해 병렬 처리로 덤프하고, 슬레이브 복제를 설정해 실시간 동기화 상태를 유지한다.
# mydumper 설치
sudo apt install mydumper -y
# 병렬 덤프 (스레드 8개)
mydumper \
--host=localhost \
--user=root \
--password=your_password \
--outputdir=/backup/mysql-dump \
--threads=8 \
--compress \
--verbose=3# 기존 서버 (마스터) — my.cnf 설정
[mysqld]
server-id = 1
log_bin = /var/log/mysql/mysql-bin.log
binlog_do_db = your_database
# 새 서버 (슬레이브)에서 복제 시작
CHANGE MASTER TO
MASTER_HOST='old-server-ip',
MASTER_USER='replication_user',
MASTER_PASSWORD='password',
MASTER_LOG_FILE='mysql-bin.000001',
MASTER_LOG_POS=154;
START SLAVE;
SHOW SLAVE STATUS\G
# → Slave_IO_Running: Yes
# → Slave_SQL_Running: Yes슬레이브가 마스터를 따라잡으면 두 서버의 데이터가 실시간 동기화된다.
4단계: DNS TTL 축소
컷오버 전에 DNS TTL을 줄여 전환 속도를 높인다.
# 3600초 → 300초
# 변경 후 기존 TTL(3600초)만큼 대기해야 전파 완료
# 변경 확인
dig your-domain.com +short
# → 응답 시간이 빠르면 TTL이 적용된 것[💡 잠깐! 이 용어는?] TTL(Time To Live): DNS 레코드가 캐시에 얼마나 오래 유지되는지 결정하는 값(초 단위). TTL이 3600이면 DNS 변경 후 최대 1시간까지 이전 서버를 가리킬 수 있다. 300으로 줄이면 5분 이내에 새 서버로 전환된다.
5단계: 기존 서버를 리버스 프록시로 전환
DNS 전파 중 기존 서버로 오는 트래픽을 새 서버로 포워딩한다. Nginx 설정 34개를 일괄 변환한다.
# 기존 서버의 모든 Nginx 설정을 리버스 프록시로 변환
for conf in /etc/nginx/sites-enabled/*; do
domain=$(grep -oP 'server_name \K[^;]+' "$conf" | head -1)
cat > "$conf" << EOF
server {
listen 80;
server_name $domain;
location / {
proxy_pass http://hetzner-ip;
proxy_set_header Host \$host;
proxy_set_header X-Real-IP \$remote_addr;
proxy_set_header X-Forwarded-For \$proxy_add_x_forwarded_for;
}
}
EOF
done
sudo nginx -t && sudo systemctl reload nginx이 시점부터 기존 서버는 새 서버로 요청을 중계한다.
6단계: DNS 컷오버
모든 A 레코드를 Hetzner IP로 변경한다.
# 변경 후 전파 확인
dig your-domain.com @8.8.8.8 +short
# → Hetzner IP가 나오면 성공
# 새 서버에서 트래픽 수신 확인
tail -f /var/log/nginx/access.logTTL을 300초로 줄여뒀으므로 전파는 5분 내에 완료된다.
결과
| 지표 | 결과 |
|---|---|
| 다운타임 | 0분 |
| 데이터 손실 | 0건 |
| 월 비용 | $1,432 → $233 |
| CPU | 32코어 → 96코어 |
| RAM | 192GB → 256GB DDR5 |
| 연간 절감 | $14,388 |
성능이 3배 올라갔는데 비용은 83% 줄었다. 트래픽이 꾸준한 steady-state 워크로드라면 전용 서버가 클라우드 VM보다 월등히 유리하다.
적합한 케이스
이 방식이 맞는 케이스:
- 트래픽이 예측 가능하고 일정한 서비스
- 클라우드 탄력성보다 원시 성능이 필요한 경우
- 비용 압박이 있는 스타트업/중소 회사
주의할 케이스:
- 급격한 트래픽 변동이 있는 서비스 (오토스케일링이 필요)
- 미국/아시아 레이턴시가 중요한 경우 (Hetzner는 주로 유럽/미국 데이터센터)
마무리
rsync, mydumper, MySQL 슬레이브 복제, Nginx 리버스 프록시. 네 가지 도구를 조합하면 수백 GB 규모의 서비스도 다운타임 없이 이전할 수 있다. 비결은 컷오버 전에 두 서버가 동기화 상태를 유지하는 것이다. DNS TTL을 줄이고 기존 서버를 리버스 프록시로 두는 것이 그 안전망이다.
참고:
- 원본 마이그레이션 기록: https://isayeter.com/posts/digitalocean-to-hetzner-migration/
- mydumper: https://github.com/mydumper/mydumper
- Hetzner 서버 목록: https://www.hetzner.com/dedicated-rootserver
같은 카테고리 · Tooling
비슷한 주제의 최신 글
태그가 겹치는 글
공통 태그가 많을수록 위에 보인다