LabHub

백업과 복구 · tar 와 rsync · 실습

rsync 로 세대 백업 구성

LabHub 에서 이어서 보기

목표

rsync 로 미러 동기화와 세대 백업을 구성하고, --delete 가드와 부하 제어까지 실무 형태로 만듭니다.

왜 중요한가

--link-dest 세대 백업은 rsync 의 가장 아름다운 기능입니다. 각 세대 디렉터리가 완전한 스냅샷처럼 보이면서 디스크는 변경분만 차지합니다. 원리는 하드 링크이고, 그래서 du 로 재면 예상보다 훨씬 작게 나옵니다 — 같은 inode 를 중복해서 세지 않기 때문입니다.

그리고 --delete 는 반드시 가드와 함께 써야 합니다. 원본이 비었거나 마운트가 풀린 상태에서 실행되면 대상 데이터를 전부 지웁니다. 실무에서 실제로 반복되는 사고입니다.

단계

1. /root/rs/src 아래에 app/main.py, conf/app.yaml, logs/app.log, tmp/cache.bin 을 만들고, /root/rs/dst/ 로 동기화하세요. 결과적으로 /root/rs/dst/app/main.py 가 존재해야 합니다.
2. dry-run + itemize 로 실행해 /root/rs/itemize.txt 로 저장하세요. 대상은 아직 동기화하지 않은 새 디렉터리여야 합니다 — 1번의 dst/ 를 다시 겨냥하면 이미 같은 상태라 rsync 가 아무 줄도 내놓지 않아 파일이 빕니다. itemize 는 "무엇이 왜 바뀌는가" 를 보는 도구이므로 바뀔 것이 있어야 볼 것도 있습니다.
3. /root/rs/backup.sh 를 작성하세요. set -euo pipefail 로 시작하고, 원본이 비어 있으면 종료 코드 1로 중단하고, --delete/root/rs/src//root/rs/mirror/ 에 동기화해야 합니다. 원본 경로는 첫 번째 인자로 받고, 인자가 없으면 /root/rs/src/ 를 씁니다 — 채점기가 빈 디렉터리를 첫 인자로 넘겨 가드가 실제로 도는지 확인합니다. 실행해 /root/rs/mirror 를 만드세요.
4. /root/rs/exclude.txt 에 제외 패턴을 적고(logs/tmp/), 그것을 써서 /root/rs/clean/ 으로 동기화하세요. /root/rs/clean/logs/root/rs/clean/tmp 가 없어야 합니다.
5. 세대 백업을 만드세요. /root/rs/gen/daily.1/ 로 전체 동기화한 뒤, --link-dest/root/rs/gen/daily.0/ 를 만드세요. 바뀌지 않은 파일은 두 세대가 같은 inode 를 공유해야 합니다.
6. --numeric-ids 를 써서 /root/rs/numeric/ 으로 동기화하고, app/main.py 의 소유자 UID 를 숫자 한 줄로 /root/rs/uid.txt 에 적으세요.
7. /root/rs/throttled.sh 를 작성하세요. ionice, nice, --bwlimit 세 요소가 모두 들어간 rsync 명령이어야 합니다. 실행해 /root/rs/slow/ 를 만드세요.
8. /root/rs/report.txt 를 다음 4줄로 만드세요.
MIRROR_FILES=<mirror 안 파일 수> / CLEAN_HAS_LOGS=no / SHARED_INODE=yes / GEN_COUNT=2

참고

단계 8개

  1. 기본 미러 동기화
  2. 변경 내역 표시
  3. 가드가 있는 백업 스크립트
  4. 제외 목록 파일
  5. 세대 백업
  6. 숫자 소유자 유지
  7. 부하 제어
  8. 세대별 용량 보고서