꽃삽질 : Snapper, Btrfs snapshot 의 문제점 돌아가기

Snapper 기본 설정의 문제점 파악

Btrfs Snapshot 을 사용하면, 손쉽게 복사본(?)을 만들 수 있다. 완전한 복사본이라 말하기엔 애매한 부분도 있지만, 아무튼 충분히 원하는 효과를 얻을 수는 있다.

문제는, 단순히 ‘보관’을 위한 작업을 위해서는 Snapshot 이 최선의 방법이지만, 만약, 이전 상태로 되돌아가려고 한다면(Rollback), 조금 더 복잡한 방법을 생각해내야 한다는 데에 있다.

이런 필요에서 나온게 Snapper 라는 프로그램이다. 이건 Suse 에서 만들었고, OpenSuse 를 설치하면 기본으로 사용하게끔 되어 있다.

그런데.. 여기엔 조금 애매한 점이 있다.
그 애매한 점에 대해서, Archlinux 를 사용하는 어떤 이가 자세하게 정리를 해놨다.

그에 앞서, 용어 정리가 필요하다. Btrfs 에는 막연히 ‘root’ 라고 말하면 어느 위치를 가리키는지 애매할 때가 많다. 여기서는 이렇게 정리하도록 한다.

  • FS Root : File System Root. 즉, Btrfs 파일 시스템의 최상위. 즉, subvolid=5 (또는 0. 과거에는 0 으로 지칭했던 듯?)
  • root 혹은 / : mount 로 지정한, 디렉토리 시스템의 루트. 즉 cd / 로 접근할 수 있는 위치.

다소 길고, 복잡한 내용이지만 정리하자면 다음과 같다.

  • root 디렉토리를, snapper 를 사용해서 snapshot 을 만든다.
  • snapper 는, 해당 디렉토리(root 디렉토리) 아래에 .snapshot 이란 디렉토리를 만들고, 그 아래에 스냅샷을 만든다. (스냅샷도 서브볼륨이다.)
  • 이렇게 만들어진 스냅샷은, /.snapshot 이하에 보관된다.
  • 이런 상황에서, 특정 스냅샷으로 복귀하려고 한다면, Snapper 는 그 스냅샷을 그대로 root 로 마운트 해버린다.
  • 결과, FS_ROOT/subvol_root 는 그냥 공간만 차지해버리는 형태가 돼 버린다.

아래에서 위 상황을 대충 설명해봤다.

시스템 설치 시에는 FS_ROOT/@ 가 root 디렉토리였다. 이걸 fstab 에 이런 식으로 마운트를 했다. set-default 는 하지 않았다는 가정 하에.

# /etc/fstab
UUID=.... /               btrfs   defaults,subvol=@ 0       1

그런데, 이전 Snapshot 으로 복귀하려고 했으므로, Snapper 는 복잡한 과정 대신, 이전 snapshot 을 root 로 삼아 버린다. 7번째 스냅샷을 선택했다는 가정 하에.
물론, 이 스냅샷은 Read Only 다. Snapper 가 생성한 스냅샷은 모두 Read Only 이므로, 사실 이렇게는 사용하지 않는다. Snapper 의 Rollback 은, 선택한 스냅샷을, 다시 RW 로 스냅샷하여 그걸 사용한다.
여기선 그냥 단순히 설명을 위해 중간 과정은 생략했다.

# /etc/fstab
UUID=.... /               btrfs   defaults,subvol=snapshots/7/snapshot 0       1

그냥 이렇게 사용해도, 사용자는 변한 점을 눈치챌 수가 없다. 디렉토리 구조가 똑같고, 단지 파일 내용만 이전으로 회귀했을 뿐이다.

그런데, Arch Forum 의 사용자가 문제삼은 점은, 원래 있던 FS_ROOT/@ 의 상황이다. FS_ROOT/@ 에 뭔가 문제가 생겨서 과거로 돌아갔고, 따라서 그 문제는 해결되었으나, FS_ROOT/@ 산하 파일들은 그대로 남아있고, 시스템은 그걸 그냥 남겨놓고 무시하고 있다. 즉, 쓸데없는 공간 낭비라고도 볼 수 있고, 원래 집을 놔두고 다른 집에서 세를 들어 살고 있는 듯한 느낌도 든다.
내가 아는 한, Snapper 로는 저 공간(FS_ROOT/@)을 어떻게 해줄 방법이 없다. 이 분이 한 것처럼 수동으로 처리하는 게 유일한 방법이 될 듯 한데..

그 사람은 그 상황을 이렇게 표현했다.

This is very unclean, and convoluted.

by tal (An Archlinux User)

Convoluted 라는 단어, 오랜만이다. “서로 얽혀있다”는 뜻인데, 나도 처음 OpenSuse 에서 이 상황을 봤을 땐 비슷한 느낌이었다. (그렇다고 저 단어가 떠오르지는 않았다.)

그리하여.. 저 양반은 일련의 ‘수작업’을 통해, 복귀를 원하는 스냅샷을 FS_ROOT/@ 로 이동시키는 작업을 제안하고 있다.

별 거 아닌 시스템이지만, 지금 서버를 계획하고 있는 와중에.. (물론 지금까지도 서버를 운영해오곤 있었지만, 사실 저런 식의 고차원 백업 수단까지는 사용하지 못하고 있었다. 단순히 cron 을 써서 수시로 자료복사만 했을 뿐.)
어떤 방법이 더 손이 안가고 편리할 지는, 좀 더 공부가 필요하다.


Snapper 설정 (문제점 돌아가기)

그리하여, ArchLinux 의 한 사용자가 제안하고, 지금은 ArchLinux Snapper 문서에 까지 오른 방법이, 바로 아래에 있는 내용이다.
이 방법은, Snapper Rollback 을 사용할 때는 써서는 안된다. 따로 (뭔가 쓰려고 했던 모양인데.. 뭔질 알 수가 없다.)

이 작업을 요약하면 다음과 같다. (root 디렉토리 기준.)

  • Snapper 용 서브볼륨(@snapshot)을 따로 만든다. (기본값은 /.snapshot 이지만, @ 와 동일한 수준에 서브볼륨을 생성한다.)
  • 따로 만드는 이유는, 나중에 이전 스냅샷으로 복귀를 했을 때, /.snapshot 서브디렉토리는 비어있는 상태가 되기 때문이다.
  • fstab 에 /.snapshot 을 @snapshot 으로 마운트하는 명령을 추가한다.
  • 라이브 디스크로 부팅 후,
  • 현재 루트 서브볼륨(/@)을 지우거나, 이름을 바꾼다.
  • 복귀를 원하는 스냅샷을, btrfs sub snapshot 명령을 써서, /@ 로 생성한다.

Btrfs 서브볼륨의 구성은 이런 식이다.
이걸 Flat 형식이라고 한다.
OpenSuse 는 FS_ROOT 가 아닌, 시스템 루트(@) 하에 서브볼륨을 생성한다. 이것은 Nested 방식이라 한다.

subvolid=5
   |
   ├── @
   |   |
   |   ├── /usr
   |   |
   |   ├── /bin
   |   |
   |   ├── /.snapshots
   |   |
   |   └── ...
   |
   ├── @snapshots
   |
   ├── @home
   |
   └── @var 등등...

이제 하나씩 만들어본다. (모든 작업은 관리자 권한으로 실행)
먼저 서브볼륨, @snapshots

mount /dev/sdaX /mnt -o subvolid=5
btrfs subvolume create /mnt/@snapshots

@snapshots 을 따로 만드는 이유는 이렇다.
btrfs snapshot 은 서브볼륨을 대상으로 하고, 서브볼륨 아래에 있는 서브볼륨은 무시해버린다.
우분투의 경우, @ 을 스냅샷하면, /home 디렉토리는 비어있는 채로 작업이 완료된다. /home 은 실제로 @home 서브볼륨이기에, 작업이 제외되기 때문이다.
따라서 스냅샷에 포함될 필요가 없는 디렉토리들은 서브볼륨으로 만들어 루트에 마운트 한다. 이런 방식을 OpenSuse 에서 사용한다.

Snapper 는 /.snapshots, 즉, FS_ROOT/@/.snapshot 을 생성하는데, 이 글에서 사용할 방식에 따르면 원래 루트 디렉토리를 모두 삭제(또는 이름변경)할 예정이고, 이러면 결국 /.snapshots 도 삭제가 된다.
또는, 삭제하지 않더라도, 아래 방법으로는 FS_ROOT/@/.snapshots 를 다시 사용하기가 애매해지고, 따라서 snapper 사용도 역시 애매해진다.

이런 위험과 불편함을 방지하기 위하여 @snapshots 서브볼륨을 따로 생성한 뒤, /.snapshots 에 마운트하는 방법을 사용한다.

자세한 사항은 ArchLinux 포럼Snapper 문서를 참고하고, 여기서는 간단히 정리한다. 포럼 쪽이 좀 더 자세하다.

@snapshots 를 만들었다면 이젠 Snapper 를 설정할 차례가 됐다.
snapper config 를 실행한다. @snapshots 은 아직 마운트 하지 않는다.

snapper -c root create-config /

자세한 사용법은 man snapper 로 알아볼 수 있고, 다른 글에서도 간단히 정리하기도 했다. 여기선 위 구문만 설명한다.

  • -c root : –config name. 즉, 현재 설정에 ‘이름’을 부여함. 기본값은 root 고, 다른 값을 줘도 되지만, / 를 Snapshot 하기 위해선 ‘root’ 로 준다.
  • create-config file system | subvolume : file system 또는 subvolume 에 대해 설정을 만듦.

여기서 주의점이 있다.

  • /.snapshots 디렉토리가 명령을 내리기 전부터 존재하고 있다면 오류(Creating config failed (subvolume already covered).)가 발생한다.
  • 이전에 동일한 명령을 내린 적이 있어도 오류가 발생한다.

이미 오류가 발생한 상황이고, /.snapshots 를 지워도 되는 상황이라면, 다음 명령으로 이전 상태로 되돌릴 수 있다.

snapper -c root delete-config

이 명령은 다음 세가지를 실행한다.

  • /.snapshots 삭제
  • /etc/default/snapper 에서, SNAPPER_CONFIGS=”root” 항목 중 ‘root’ 를 삭제
  • /etc/snapper/configs/root 파일 삭제

저 세가지를 수동으로 해도 되지만, delete-config 명령을 쓰는게 훨씬 편하다.

다시 돌아와서, 명령이 잘 수행이 됐다면, 생성된 /.snapshots(서브볼륨) 을 지우고, 마운트 포인트를 생성한다.

btrfs subvolume delete /.snapshots
mkdir /.snapshots
chmod 750 /.snapshots

이제, /etc/fstab 에 @snapshot 을 추가한다.

UUID=...	/.snapshots  btrfs	OPTIONS,subvol=@snapshots	0	0

원문에는 @snapshots 이 아니고 subvol_snapshot 인데, 이름은 주기 나름이므로 아무런 관계가 없다. 데비안/우분투, Suse 계열에선 Btrfs 서브볼륨 앞에 @ 를 붙인다.

재부팅을 해도 되고, mount 명령 (또는 mount -a) 를 해도 된다.

mount /.snapshots

이제 Snapper 를 사용(snapper create)하다가, 특정 스냅샷으로 복구하길 원한다면, 다음 과정을 따른다.

  • Linux 라이브 미디어로 부팅한다.
  • 사용 중인 btrfs 볼륨을 /mnt 등으로 마운트한다. (set-default 사용 중이라면, mount /dev/xxxx /mnt -o subvolid=5)
  • 복귀를 원하는 스냅샷을 정확히 찾아낸다. (이 상황이라면, /mnt/@snapshots/번호/info.xml 을 참고할 수 있다.)
  • 사용 중이던 루트 서브볼륨을 삭제 또는 이동한다. (mv /mnt/@ /mnt/@.broken)
  • 복귀할 스냅샷(Read Only)을, R/W 로 다시 스냅샷을 만든다. (여기는 아래에 다시 설명한다.)

이러면, 망가진 원래 루트는 가볍게 버려버리고, 그 자리에 아무 문제없던 파일들을 다시 위치시킬 수 있다.

복귀할 스냅샷을 RW 로 다시 만드는 명령.

btrfs subvol snapshot /mnt/@snapshots/X/snapshot /mnt/@

이렇게 하고 부팅하면… 잘 될까? 안될 가능성이 높다.

Archlinux 에 있는 글엔, 살짝 모순이 있다. 모순이라기 보다는 생략이랄까.
거기에 있는 fstab 은 이렇다.

	UUID=...	/            btrfs	OPTIONS				0	0
	UUID=...	/.snapshots  btrfs	OPTIONS,subvol=subvol_snapshots	0	0
	UUID=...	/home        btrfs	OPTIONS,subvol=subvol_home	0	0
	UUID=...	/opt         btrfs	OPTIONS,subvol=subvol_opt	0	0

보다시피, / 에 subvol 항목이 없다. 이렇단 건, set-default 를 했다는 뜻이다. 또한, grub 문제도 있다. 이것들은 생각보다 귀찮은 문제가 될 수도 있다. 자세한 사항은 연결 글 참고. (간단하게, set-default 를 사용하려면 Grub 보다는 rEFInd 가 편하다.)

set-default 를 하지 않으려면, fstab 에는 subvol 항목이 반드시 들어가야 한다.
물론, 우분투라면 기본으로 들어가 있으니 별 관계는 없다.

** set-default 를 했을 경우.

@ 에 set-default 를 했고, @ 을 @.broken 으로 이름변경한 경우,

btrfs subvolume get-defalut /mnt
ID 259 gen 681 top level 5 path @.broken

이런 결과가 나온다. 즉, defalut volume 은 @.broken 이 된다.

여기서, 새로 root 로 삼을 snapshot 을 @(/mnt/@)로 만들었다면, @ 을 다시 set-default 해야 한다.

btrfs subvolume set-default /mnt/@

이 방식의 장점은? fstab 을 편집할 필요가 없다는 점.

그러나, 복잡..하군.

Author: 아무도안

안녕하세요. 글 남겨주셔서 고맙습니다.