무튼.. 바로 시작하도록 하겠다.
이번 기사는 서브볼륨과 스냅샷 기능에 대한 내용을 다루고 있따~
Btrfs 의 subvolumes 는 디바이스가 싱글이든, Raid 등으로 구성되어 있든 상관없이,
여러개의 파일시스템을 생성 할 수 있도록 하는 기능인데,
이것은 다른 여느 파일시스템들에서는 볼 수 없을 흥미로운 가능성을 제공할 수 있다. +.,+
조나단은 이 기사에서 Subvolumes 의 기능들과
이것을 스냅샷과 연동해서 사용하는 것에 대해 이야기 할 것이다.
Subvolume Basics
전통적인 유닉스스타일 파일시스템은 디렉토리 Tree 구조와 / 디렉토리로 구성된다.
Btrfs 파일시스템은, 기본적으로, 같은 방법으로 구성되어진다.
하지만 서브볼륨이라는 기능은 특정 디렉토리를 마치 루트디렉토리인냥,
루트 디렉토리를 대응하여 독립적인 파일시스템 구조를 만들어 주는 기능을 제공한다..
아래 예제는 일반적으로 btfs 파일시스템을 만들고, 일반적으로 사용할때와,
subvolume 을 사용했을때의 구성을 나타내 준다.
일반 :
# mkfs.btrfs /dev/sdb5
# mount /dev/sdb5 /mnt/1
# cd /mnt/1
# touch a
이것은 한개의 dummy 파일 (a) 를 갖고 있는 특색없이 Btrfs 파일시스템을 사용하는 그림이고,
아래와 같은 방법으로 서브볼륨을 이용한다면 다음과 같은 Tree 구조를 볼 수 있다.
# btrfs subvolume create subv
# touch subv/b
# tree
.
├── a
└── subv
└── b
1 directory, 2 files
suby 라고 만들어진 서브볼륨은 대강보기에는 일반적인 디렉토리와 별반 차이 없어보인다.
그러나 여기엔 매우 독특한 차이가 있다 :
# ln a subv/
ln: failed to create hard link ‘subv/a’ => ‘a’: Invalid cross-device link
비록 "suby" 는 전통적인 subdirectory 처럼 보임에도 불구하고! 파일시스템은
이것을 마치 분리된 물리적 device 처럼 다루고 있다...
(내 블로그에서 이렇게 보는 이유가 왜인지 모르는 엔지니어는 없겠지..제발..)
"suby" 는 이게 비록 디렉토리처럼 보이지만,
마치 물리적으로 연결된 일반 mount point 처럼 동작하는데다가,
독립적으로 서브볼륨을 따로 마운트 할 수도 있다 :
# btrfs subvolume list /mnt/1
ID 257 gen 8 top level 5 path subv
# mount -o subvolid=257 /dev/sdb5 /mnt/2
# tree /mnt/2
/mnt/2
└── b
0 directories, 1 file
어떤가? 심장이 쫄깃쫄깃 해지지 않는가? 아직임? 내 쫄깃해질때까지 해주겠음ㅋ
결과적으로 각 서브볼륨은 마치 개별적 파일시스템처럼 다뤄질 수 있다는 것인데다,
만들어진 모든 서브볼륨을 완전하게 개별적 마운트 또한가능하며,
스토리지 아래에서 공유되는 모든 독립적 파일시스템에서까지 가능하다는 점..
즉, 생성된 서브볼륨들은 구지 "root" 위치에 마운트 되어져야 할 필요가 없다는 것이다.
Btrfs 는 보통 / 볼륨에 마운트 될 것이지만,
위에서 처럼 subvolid 값을 mount 옵션을 통해, 원하는 곳에 마운트 할 수 도 있다.
새로 만든 서브볼륨을 다른 곳에 마운트하고자 한다면, 다음과 같이 하면 된다 :
btrfs subvolume set-default 257 /mnt/1
이제, /dev/sdb5 는 subvolid 옵션 없이도, suby 를 포함하여 마운트 할 것 이다.
/ 볼륨은 subvolume ID 가 0 이며, subvolid=0 으로 두면 root 로 마운트 된다.
서브볼륨의 삭제는 다음과 같이 한다 :
btrfs subvolume delete path
일반적인 subvolume 을 삭제하려면, 반드시 지정된 path 가 비어있어야 한다.
스냅샷은 비어있지 않아도 삭제가 된다.
사고를 방지하기 위한 멋진 방책이라고 생각된다.....지만
파일이 안드로메다로 가는이슈들은 없어진거 맞지???? ㅋㅋ
Snapshots
Btrfs 에서의 스냅샷이란 특정 서브볼륨의 현재 상태의 사본을 포함하고 있는.
특별한 형태의 서브볼륨으로 제공된다.
아래 그림을 보면, /mnt/1 에 대한 스냅샷을 /mnt/1/snapshot 에 생성한 모습이다 :
# btrfs subvolume snapshot /mnt/1 /mnt/1/snapshot
# tree /mnt/1
/mnt/1
├── a
├── snapshot
│ ├── a
│ └── subv
└── subv
└── b
3 directories, 3 files
서브커맨드로 "snapshot" 을 주면 스냅샷을 생성할 subvolume 대한 스냅샷을 생성,
그 서브볼륨 밑에 현재 상태 바로 이전 (스냅샷을 생성한 시점) 의 데이타를
모두 갖고 있는 snapshot 이라는 이름의 subvolume 을 추가 생성한다.
물론, 그러나, Btrfs 는 COW 파일시스템이기 때문에 실제 전체 데이타를 복제가 아니다.
이 스냅샷은 대상 파일시스템에 대해서 간단한 reference 만 갖고 있을 것이며,.
만약 메인볼륨이나 스냅샷 자체에 어떤 변화가 발생될 때에, 변경된 데이타부분만 복제되어 보관 될 것이다.
또한 이미 존재하는 서브볼륨의 contents 는 보이지 않으며, 필요할 경우,
해당 서브볼륨에 대한 스냅샷은 따로 생성해야 한다. ( subvolume 이니까 )
스냅샷은 백업기능에 매우 유용성을 보여준다.
예를들어, Btrfs 를 사용하는 시스템이 있다면,
distibution update 를 수행하기 전에 snapshot 을 생성하고,
해당 업데이트가 맘에 들거나 정상적으로 수행되었다면 스냅샷을 지우고,
만족스럽지 않거나, 문제가 발생했을 경우,
다음 부팅때 스냅샷 부분을 이용하도록 한다면 간단하게 롤백 될 것이다.
스냅샷은 간단한 "time machine" 기능을 구현 할 수 있다.
뭐 거창하게 조나단옹은 타임머쉰 운운 하지만 사실상 기능적으로 별반 다를게 없다.
아래 스크립트를 보자 :
rsync -aix --delete /home /home-backup
btrfs subvolume snapshot /home-backup /home-backup/ss/`date +%y-%m-%d_%H-%M`
완전 너무 간단해지만... rsync 는 /home-backup 디렉토리로 /home 의 내용을 복사하되,
/home 에 없는 자료들은 /home-backup 에서도 자동으로 삭제하여, 완벽하게 동기화 시키라는 명령이다.
보통 Mirroring 을 유지시키는 방법으로 많이들 사용하곤 하는 명령이다.
그 다음 스크립트는 눈에 빛을 내줘야 한다. +,.+
동기화를 완벽하게 한후, 동기화 된 상태를 수행된 시각을 기준으로
Timestamped snapshot 을 만들어 놓는 커맨드이니까...
만약 /home 디렉토리를 특정 시점으로 되돌려야 하는 일이 생긴다면,
간단하게 해당 시점의 snapshot 으로 돌아가면 되는 것이다...
이 기능은 아주 재밌게도, yum-update-snapshot 인가?
yum plugin 을 설치하면, yum 이 실행 될 때마다 변화가 있을 시,
timestampped package subvolume 을 기록해 준다.
이게, 은근 편하거든.. 뭔가 의존성이 열라 많은 것들을 설치했을때, 혹은
자동업데이트가 이루어 졌는데, 그후로 뭔가 잘 안돼... 이런것들 추적할때 참 좋다는 말이지..
조나단의 본 기사에서는 이 기능을 이용해, 개발쪽에서 보다 High level 도구로
사용 가능함을 소개시켜 주고 있다.
Subvolume quotas
이 기능은, 언제나 그렇듯, 각 서브볼륨이 사용되는 공간을 어떻게 계산할 수 있는지,
또 이것들이 언젠간 너무 많아져 레알 Disk space fulled 현상을 불러오지 않을까
하는 걱정에 가득찬 사람들을 위해 제공된 기능으로,
스냅샷의 일부 공유되는 데이타들의 사용량을 "du" command 만으로 확인하기에는
다소 문제가 있고 백그라운드 sync 중에
모든 스토리지 공간을 소진시켜버리는 것을 방지하기 위하여.
각 서브볼륨별로 quota 를 제공한다.
사실 보통 quota 는 user base 로 제공되던 기능이였기 때문에,
여러사람의 제안들에도 불구하고, Btrfs 에서는 그 방법을 적용하기
어려웠던 부분이 있었고, 그래서 subvolume 별,
quota group 단위로 제한을 두는 것을 도입하게 되었다.
하지만, qouta 를 group 으로 적용한다는 것은,
ownership 등을 구분하고 지원하기 위한 Performance 의 저하라는 단점이 있다.
기본적으로 Btrfs 는 quotas 를 disable 한 채로 제공되며,
다음과 같이 enable 시킬 수 있다 :
# btrfs quota enable path
구버젼의 Btrfs 에서의 quotas 를 새로 장착하고자 하는 요구로 인한 작업이 이루어졌고,
바로 quotas 는 구현돼었으며, 아래와 같은 형태로 quota 그룹상태를 볼 수 있다.
( 사실 완전 비추하는 기능이다. ㅋ )
# btrfs qgroup show /home-backup
qgroupid rfer excl
-------- ---- ----
0/5 21184458752 49152
0/277 21146079232 2872635392
0/281 20667858944 598929408
0/282 20731035648 499802112
0/284 20733419520 416395264
0/286 20765806592 661327872
0/288 20492754944 807755776
0/290 20672286720 427991040
0/292 20718280704 466567168
0/294 21184458752 49152
qgroupid 는 서브볼륨ID,
rfer 는 서브볼륨에서 보여지는 총 size,
excl 은 다른 서브볼륨들과 공유되지 않는 실제 사용량을 나타낸다.
즉, "rfer" 는 "du" 와 비슷한 값을 나타낼 것이며, "excl" 은 삭제할 경우
확보가 가능한 실제 공간을 나타낸다고 볼 수 있다.
서브볼륨에 대한 제한은 아래와 같이 적용 가능하다 :
# btrfs qgroup limit 30M /mnt/1/subv
테스트:
# dd if=/dev/zero of=/mnt/1/subv/junk bs=10k
dd: error writing ‘junk’: Disk quota exceeded
2271+0 records in
2270+0 records out
23244800 bytes (23 MB) copied, 0.0334957 s, 694 MB/s
보이는 바와 같이, 일반적인 quota 와 비슷하게 제약을 받게된다.
# btrfs qgroup show -r /mnt/1
qgroupid rfer excl max_rfer
-------- ---- ---- --------
0/5 16384 16384 0
0/257 23261184 23261184 31457280
요기보면 재밌는게, 257 서브볼륨을 보면, 훨씬 적은 상태에서
더이상 사용불가능한 상태로 제한을 받게된다.
이것은 COW 의 특성으로, 일반 ext3 파일시스템등에서 저널링으로 사용하는 예약공간처럼,
COW 를 위한 약간의 공간이 더 필요한 것으로 보여진다.
Btrfs 에서는 quota 를 서브볼륨 그룹별로 설정 가능하기 때문에,
아래와 같이 운용이 가능하다.
# cd /mnt/1
# btrfs subvolume create home
# btrfs subvolume create home/user1
# btrfs subvolume create home/user2
# btrfs subvolume create home/user3
# btrfs qgroup create 1/1 home
# btrfs qgroup assign 0/258 1/1 .
# btrfs qgroup assign 0/259 1/1 .
# btrfs qgroup assign 0/260 1/1 .
258,259,,260 서브볼륨은 1/1 에 assign 되었고, 아래처럼 제한을 두고,
# btrfs qgroup limit 5M 0/258 .
# btrfs qgroup limit 5M 0/259 .
# btrfs qgroup limit 5M 0/260 .
# btrfs qgroup limit 10M 1/1 .
실제 몇개 그룹의 사용량을 소진후 다음 명령을 실행 해 보면,
# btrfs qgroup show -r .
qgroupid rfer excl max_rfer
-------- ---- ---- --------
0/5 16384 16384 0
0/257 16384 16384 0
0/258 5189632 5189632 5242880
0/259 5189632 5189632 5242880
0/260 16384 16384 5242880
1/1 10346496 10346496 10485760
두개의 서브볼륨 그룹이 모두 소진되자, 1/1 인 상위 그룹 역시,
모두 소진됨을 확인 할 수 있다.
사실 이런 것들은 계층적으로 약간 문제를 일으킬 소지가 있음을 알 수 있으며,
아직 뚜렷하게 이 상태를 조회하고 조절 할 수 있는 방법은 제공되지 않는다.
개인적으로는 quotas 의 기능 자체가 아주 중요하다고 생각되지는 않기때문에,
이부분에 대한 것은 본문 기사를 직접 읽는 사람들에게 넘기고 싶다.
(귀찮아..맥주 벌써 네캔 ㅠㅠ)