2019/10/25

btrfs 파일시스템에 우분투 19.10 clean 설치


우분투 19.10이 지난 주말에 출시 됐는데 native root ZFS 설치가 가능한 점이 가장 눈에 띈다. 우분투 설치시에 NVIDIA 드라이버를 설치할 수 있는 점도 좋은 점이다. 우분투 19.10의 새로운 점들은 Release Note를 참고하는 게 좋고, omg! Ubuntu!의 포스트에도 정리가 잘 되어 있다.

btrfs도 잘 활용하지 못하는 판에 캐노니컬은 btrfs 대신 ZFS를 밀어주고 있다. 궁금해서 VirtualBox에서 ZFS로 설치해 보기로 했다. 처음부터 삽질을 하게 만들어 불길한 예감이 들었는데 우분투 19.10을 본격적으로 설치하면서 꽤나 삽질을 해야했다.

VirtualBox(v6.0.14)에서 새로운 VM을 만들어 우분투 설치 iso로 부팅하고 나서 설치를 진행하면 VM이 먹통이 돼버린다. 우분투 19.04 host에서 top을 띄워 보면 VirtualBox cpu 점유율이 100%가 넘는다. 우분투 19.10을 설치하려면 최소 2GB 메모리가 필요하다는데 VM에 2GB를 할당해 놓았었다. 포기하려다 VM에서 gparted로 파티션을 수동분할 해서 설치를 진행하니까 설치가 잘 된다. 우연인가 싶어 먹통 만들기 테스트를 몇가지 했는데 우분투 설치 iso로 부팅이 되자 마자 gparted를 띄우고 View > Disk Info만 확인해도 host의 top에서 VirtualBox cpu 점유율이 떨어진다. VirtualBox나 우분투의 버그이겠지만 아무튼 쓸모 있는 해결책이다. 혹시나 해서 VM의 메모리를 4GB로 늘렸더니 cpu 점유율이 정상으로 돌아온다. 메모리가 넉넉하면 이 방법이 더 좋겠다.

흠, 아무튼 ZFS 설치는 잘 된다. 단, VM 생성시 시스템 설정에서 EFI를 사용하도록 해야 ZFS 설치가 가능하다. 이유는 우분투 ZFS가 gpt 멀티 파티션을 사용하기 때문인데 bios 환경에서는 설정이 복잡해서 아예 설치를 지원하지 않는다. 아직은 Experimental 딱지가 붙어 있으니 실제 시스템에 적용하려면 삽질 정신이 필수일 게다. 더구나, 전체 디스크를 지우고 파티션을 자동 할당하기 때문에 실제 시스템에는 사전 준비없이 ZFS로 설치하지 않는게 좋다. 캐노니컬이 ZFS에 꽤 심혈을 기울이는 모양이다. ZFS 관리를 위한 zsys를 열심히 만들고 있단다. ZFS가 나온지는 꽤 됐는데 서버 파일시스템으로써는 최고라는 수식어가 붙고 있다. 리눅스에서는 License 충돌 문제때문에 ZoL(ZFS on Linux) 프로젝트가 별개로 진행되었고 커널 모듈로만 사용할 수 있는 단점이 있다. ZFS를 배우려는 이들에게 우분투 19.10 VM이 큰 도움이 될 것이다. 기능적으로는 ZFS가 btrfs보다 우월해 보이는데 Desktop 사용자들에게는 btrfs도 꽤나 쓸만하다. SSD가 범용화되면서 애플의 apfs와 더불어 서버건 데스크탑이건 모바일이건 간에 바야흐로 copy-on-write 파일시스템이 대세가 되고 있다. 아무튼 우분투의 ZFS 지원이 사용자들에게 배움의 단맛과 삽질의 쓴맛을 동시에 안겨 줄 것이다.

하지만, 이 글 제목에서와 같이 나는 당분간 btrfs에 좀 더 적응하기로 했다. 몇년 내 리눅스에서 ZFS가 대세가 되면 갈아 타겠지... 지금 당장 ZFS로 우분투 root 파일시스템으로 갈아 타려면 아래의 제약 사항들을 극복해야 한다.
  • grub이 아직 ZFS를 완벽하게 지원하지 못한다.
  • ZFS 커널 모듈로 부팅해야 하므로 root ZFS 설치 절차가 복잡하고 문제 발생시 시스템 복구 등 관리 상의 복잡함이 배가된다.
  • ZFS를 제대로 사용하려면 dataset(btrfs의 subvolume) 설정을 미세하게 할 필요가 있는데 수작업으로 하기엔 좀 복잡하다.
  • ZFS는 btrfs 보다 기능이 많기 때문에 배워야 할 것도 많다.
copy-on-write 파일시스템의 장점은 time-machine 류의 snapshot과 변분(incremental/differential) backup이 가능하고 대형 파일 복제가 매우 빠르며, 파일시스템 문제 발생시 쉽게 복구할 수 있다는 점이다. 파일 압축과 암호화를 지원하는 점도 장점이다. 실제로 btrfs 파일시스템을 사용하고 있는 우분투 19.04에서 우분투 19.10으로 upgrade를 진행했는데 중간에 gdm이 새로 뜨더니 로그인이 안돼서 설치를 제대로 마무리 할 수 없게 됐었다. 다행히 설치 전에 snapshot을 떠 놓아서 다시 19.04로 쉽게 돌아 갈 수 있었다. 할 수 없이 우분투 19.10 clean install을 진행하기로 했고 지금은 snapshot 덕분에 grub에서 19.04로도 부팅할 수 있고 19.10으로도 부팅할 수 있다. 서버라면 RAID 구성도 가능하겠지만 데스크탑에서는 USB 외장하드에 백업이 되는 것 만으로도 매우 유용하다. 필요할 때만 백업해 주면 되는데 시간을 꽤나 절약할 수 있기 때문이다. 뭐, 단점이라면 ext4 파일시스템에 비해 약간의 성능 저하가 있을 수 있는데 피부로 느낄 만큼 크지는 않다. subvolume에 lzo 압축을 적용해서 사용하는데 느리다고 느껴 본 적은 없다. 대신 저장 공간은 크게 절약된다(단, 동영상이나 음악 파일과 같이 자체 압축된 파일들이 많지 않다면...).

btrfs 파일시스템 파티션 조정

디스크 파티션을 조정해야 하므로 중요한 데이터를 별도의 디스크에 백업해 둬야 한다. UEFI 시스템에 btrfs 설치시 필요한 파티션은 EFI System(200MiB)과 btrfs(나머지 용량) 2개이다. 그 동안 우분투 전용 파티션만 4~5개 사용했었는데 이제 1개로 모두 합치게 되었다. EFI System 파티션은 모든 OS가 공용으로 사용하기 때문에 기존에 사용하고 있었다면 새로 추가할 필요는 없다. 리눅스 커널 5.0부터(우분투 19.04부터) btrfs 파일시스템 내의 Swap 파일을 Swap 파티션 대신 사용할 수 있다. 참고로 우분투 19.10의 ZFS는 EFI System, Swap, grub, boot pool, root pool 등 5개의 파티션을 사용하더라. 아마 boot와 root 파티션을 분리한 이유는 encryption이 가능하게 하려는 것인듯 하다. btrfs와 zfs는 비슷한 점이 많기 때문에 boot와 root 파티션을 나누는 게 좋을 수도 있지만 암호화를 사용하지 않으면 굳이 나눌 필요는 없어 보인다. ZFS의 Swap 파티션도 약간의 문제는 있지만 zvol dataset을 사용하면 굳이 필요하지는 않다. 그리 보면 ZFS엔 grub 파티션이 하나 더 있는 셈인데 아직 grub이 ZFS를 완벽하게 지원하지 못해서 분리한 듯하다(굳이 분리할 필요는 없어 보인다).

한마디로 btrfs든 zfs이든 ext4처럼 사용자 파티션 들을 더이상 구분할 필요가 없다. 가능한 파티션을 쪼개지 않는게 더 좋다. 이는 나중에 btrfs의 subvolume 또는 zfs의 dataset을 사용함으로써 구분할 수 있기 때문이다. 궁극적으로 데스크탑 사용자에겐 EFI 시스템 파티션을 제외하면 1개의 파티션으로 충분하다. subvolume 간에는 Quota를 따로 설정하지 않는 한 저장 공간을 공유하기 때문에 파티션을 여러 개 사용하면서 디스크 용량을 얼마씩 할당할지 더이상 고민할 필요가 없다.

참고로, 디스크 파티션을 분리해서 각각 btrfs 파일시스템으로 format 하면 각각의 파티션 수만큼 독립적인 btrfs 파일시스템을 만들게 되고, 각 파티션이 물리적인 Device 역할을 하게 된다. 대개는 여러 개의 디스크를 가지고 RAID를 구성하지만 분리된 btrfs 파티션들을 사용해서 RAID를 구성할 수도 있다. 주의할 점은 단일 btrfs 파일시스템 내에서 subvolume 들을 mount 할 때 다양한 옵션을 사용할 수 없다는 점이다. root subvolume의 mount 옵션을 따를 수 밖에 없다. 즉, root subvolume이 압축을 사용하고 있다면, 이후의 모든 subvolume은 mount 시 nocompress 옵션을 주더라도 압축을 사용하게 된다. 다만, 나중에 다루겠지만 우회적인 해결책은 있다. ZFS에서는 subvolume(dataset)이 파일시스템 단위가 되기 때문에 미세하고도 유연하게 subvolume 설정을 다르게 할 수 있다.

우분투 설치 iso로 부팅하여 설치시 참고 사항

우분투 installer(Ubiquity)를 이용하여 btrfs 파티션에 우분투 설치를 할 때 subvolume 압축을 사용할 수 있다. 압축을 사용하는 이유는 저장 공간을 줄이는 의미도 있지만 btrfs 파일시스템의 성능을 높이는 효과도 있다. 그냥 설치 후 나중에 /etc/fstab에서 subvolume 압축 옵션을 주고 mount 할 수도 있는데, btrfs에서는 기존의 파일들은 압축하지 않고 새로 생성된 파일들만 압축하기 때문에, 설치 전에 빈 subvolume을 압축 옵션을 주고 mount 해서 설치를 진행하는 것이다. 물론, 설치를 마치고 나서 defrag 명령에 압축 옵션을 사용할 수도 있기는 하지만, 사용 중인 파일들은 압축할 수 없기 때문에 바람직 하지는 않다.

Install Ubuntu 아이콘을 double click 하여 설치 진행시, [Installation type] 설정에서 [something else]를 선택하여 파티션 용도에 맞게 EFI 시스템 파티션을 [change]하고 btrfs 파티션은 /에 마운트 지정한다. 설정을 마친 후, [Where are you?] 설정(Time zone) 화면에서 멈추고, <Ctrl>+<Alt>+<t> 키 조합으로 터미널을 띄운다.

$ df -h
$ sudo btrfs subvolume list /target

명령으로 확인해 보면 btrfs 파티션(/dev/sda2로 가정)의 두 개의 subvolume 중에 @는 /target, @home은 /target/home, EFI 파티션은 /target/boot/efi에 마운트 되어 있음을 알 수 있다. 이 단계에서는 /target/swapfile과 /target/etc/fstab만 생성되어 있다.

먼저, btrfs용 swapfile은 root subvolume(@)에 snapshot을 사용할 수 있도록 하기위해 @swap subvolume에 다시 만들어야 한다. 그리고, @ subvolume을 포함한 모든 subvolume은 /etc/fstab에서 압축 옵션을 주고 부팅시 자동 mount 될 것이므로, swapfile이 압축되지 않도록 해야 하고 /target/etc/fstab 파일도 이에 맞게 아래와 같이 수정해야 한다.

$ sudo nano /target/etc/fstab

UUID=12345678-1234567890ab / btrfs defaults,noatime,compress=lzo,subvol=@ 0 1
UUID=1234-1234  /boot/efi vfat  umask=0077 0 1
UUID=12345678-1234567890ab /home btrfs defaults,noatime,compress=lzo,subvol=@home 0 1
UUID=12345678-1234567890ab /swap btrfs defaults,noatime,nodatacow,subvol=@swap 0 0
/swap/swapfile none  swap  sw 0 0

기존의 fstab 파일 내용과 다른 점은 @, @home 부분에 noatime,compress=lzo 부분이 추가됐고, @swap subvolume을 /swap에 mount하도록 한 줄이 추가됐다. 또, /swapfile 대신 /swap/swapfile을 사용한다. /swap mount 옵션에 compress 대신 nodatacow를 주긴했지만 /etc/fstab의 첫줄에 의해 mount 옵션이 동일하게 적용되기 때문에 옵션이 적용되지는 않는다. 다만, 실제로 압축을 사용하지 않을 것이므로 구분해 둘 필요는 있다. 이 단계에서 사용자 subvolume을 fstab에 더 추가할 수도 있겠지만 설치 후에 작업하는게 더 편해 보인다.

@swap/swapfile은 아래와 같이 만든다.

$ sudo -i
$ swapoff -a
$ rm /target/swapfile
$ mount /dev/sda2 /mnt
$ cd /mnt && ls
$ btrfs subvolume create @swap
$ chattr +C @swap
$ lsattr /mnt
$ cd @swap
$ touch swapfile
$ fallocate --length 1000MiB swapfile
$ chmod 600 swapfile
$ mkswap swapfile

$ swapon swapfile
$ cat /proc/swaps
$ swapoff -a
$ cd /
$ umount /mnt

@swap을 mount 할 swap 폴더를 아래와 같이 생성한다.

$ mkdir /target/swap
$ chattr +C /target/swap

참고로, btrfs 파일시스템에서 chattr +C 옵션은 파일이나 폴더/subvolume에 no-cow(no copy-on-write) 속성을 설정하는데,  subvolume 마운트시 nodatacow 옵션을 준 것과 같은 효과가 있고 압축을 사용하지 않는다. no-cow 속성이 설정되어 있더라도 subvolume의 snapshot 생성에는 아무 문제가 없다. no-cow 폴더 내의 파일이나 하위 폴더 들은 size가 0이거나 새로 생성될 때만 no-cow 속성이 계승된다. cp로 cow 파일을 no-cow 폴더에 복사하면 파일을 새로 만들기 때문에 no-cow 속성이 부여된다. no-cow 파일을 cow 폴더에 복사할 때도 cow 속성으로 바뀐다. mv로 기존의 파일을 옮길 때는 파일 속성을 그대로 유지한다.

이제 fstab과 같은 옵션으로 아래와 같이 remount 한다. lzo 압축 방식은 압축율은 좀 안좋지만 성능은 빠르다(ZFS의 lz4와는 다른 방식임). noatime 옵션은 파일시스템에서 access time을 사용하지 않도록 하는 것인데 성능을 높이기 위한 것이다.

$ sudo mount -o remount,defaults,noatime,compress=lzo /target
$ sudo mount -o remount,defaults,noatime,compress=lzo /target/home
$ grep btrfs /proc/mounts

이미 생성된 파일들은 몇개 안되지만 자동 압축되지 않았으므로 아래와 같이 수동으로 압축한다(/target/home은 비어 있음).

$ sudo btrfs fi defrag -r -clzo /target

다시 Ubiquity로 돌아와 [Where are you?] 설정을 마치고 우분투 설치를 진행하여 완료 후 디스크의 btrfs 파티션으로 재 부팅하면 우분투 clean 설치가 마무리된다.

참고로, ZFS는 이런 식으로 설치 할 수 없다. 파티셔닝부터 모든 게 자동화 되어 있으니까... 그리고, 우분투 19.10부터 설치시 3rd Party 비디오 드라이버와 WIFI 드라이버를 선택하면 자동으로 설치해 준다(설치 iso에 드라이버 탑재). Intel H/W PC에서 NVIDIA의 경우 부팅시 화면이 지글거리던 문제도 좀 나아졌다.

btrfs 사용자 subvolume 생성

btrfs 명령의 기본 사용법에 대해서는 이전 글을 참조하는 게 좋다. 이제 우분투 19.10으로 부팅해서 터미널에서 사용자 subvolume을 생성한다. @opt를 예로 든다.

$ sudo -i
$ mount /dev/sda2 /mnt
$ cd /mnt

$ btrfs sub create @opt
$ mkdir /opt
$ mount /dev/sda2 -o subvol=@opt /opt

위의 명령들을 사용해서 @opt subvolume 생성 후 /opt 폴더에 마운트해서 subvolume을 사용할 수 있게 된다. /etc/fstab에 등록해 주면 부팅시 자동으로 마운트된다.

VM 파일, DBMS storage 등에는 copy-on-write를 사용하면 성능 문제가 발생할 수 있으므로, Swap 파티션과 마찬가지로 no-cow 속성을 사용하는게 좋다. 아래와 같이 @nocow subvolume을 만들어 사용하면 된다. 어차피 압축을 사용하지 않기 때문에 동영상이나 음악 파일과 같이 자체 압축을 사용하는 파일들도 @nocow subvolume에 담아 두는게 좋아 보인다.

$ btrfs sub create @nocow
$ chattr +C @nocow
$ lsattr ./
$ mkdir /nocow
$ chattr +C /nocow
$ mount /dev/sda2 -o nodatacow,defaults,subvol=@nocow /nocow
$ grep btrfs /proc/mounts

앞서 설명했듯이 마운트 옵션을 다르게 주어도 root subvolume의 옵션을 따르기 때문에 의미는 없다. chattr +C가 이미 그 일을 해 주고 있다. 결국은 간단하게 모든 subvolume에 대해 아래와 같은 방식으로 마운트하면 된다.

$ mount /dev/sda2 -o subvol=@nocow /nocow

우분투 19.10 설치 후 발생한 문제들

우선, grub-efi 패키지가 제대로 설치되어 있지 않았다.

$ sudo apt install grub-efi --reinstall

그리고, grub에서 HDD의 iso 파일로 부팅이 안된다. 우분투 19.04에서는 잘 됐었기 때문에 EFI System 파티션의 /EFI/ubuntu 폴더를 19.04 버전으로 되돌려서 사용하고 있다. 이것이 가능했던 것은 우분투 19.04의 snapshot 덕분이다. 우분투 19.04 부팅 메뉴를 grub에 추가하되 linux와 initrd 부분에 @root-19.04 subvolume을 참조하도록 해야 한다.

linux   /@root-19.04/boot/vmlinuz-5.0.0-32-generic root=UUID=...... ro rootflags=subvol=@root-19.04
initrd  /@root-19.04/boot/initrd.img-5.0.0-32-generic

그리고, 부팅시 @root-19.04와 @home-19.04 subvolume이 mount 되어야 하므로 @root-19.04/etc/fstab 파일에서 @는 @root-19.04로, @home은 @home-19.04로 각각 수정해 주어야 한다. writable snapshot은 보통의 subvolume과 같이 파일을 수정할 수 있다. 이 경우에도 원본 subvolume은 안전하다.

이런 식으로 특정일의 @와 @home snapshot을 grub 메뉴에 등록해서 과거로 부팅할 수 있게 된다. 참고로, ZSF에서는 과거 특정 시점의 snapshot으로 rollback하면 그 과거 특정 시점 이후 생성한 snapshot 들은 삭제된다. 이에 반해 btrfs에서는 rollback이라는 것이 특정 시점의 snapshot을 사용하는 것이므로 중간 시점의 snapshot 들을 삭제할 필요가 없다. 즉, 과거에서 현재까지의 모든 snapshot 들의 상태로 들락날락 할수 있는 장점이 있다.

그 다음 문제는 VirtualBox 사이트에서 제공하는 6.0.14 버전이 설치가 안된다. 다행히 우분투 19.10 패키지에 6.0.14 버전이 탑재돼 있었다.

$ sudo apt install virtualbox virtualbox-ext-pack

설치시 modprobe 오류가 발생해서 모듈들이 로딩되지 않는 문제가 생기는데 수동으로 다시 올리면 되고, 재부팅해도 잘 된다. 또한, 이렇게 설치한 virtualbox는 guest additions iso 파일을 제대로 다운로드하지 못해서 별개로 다운로드 받아서 설치해야 했다.

btrfs 파일시스템에서 우분투 Clean Install시 사용자 설정 복원

Clean Install의 장점은 최신 버전의 앱들을 다시 설치함과 동시에 앱들이 구동되는 환경을 최신으로 바꿔 줄 수 있다는 점이다. 그러면 사용자가 과거에 설정했던 부분들을 어떻게 조화시킬 수 있을까? 이것이 가장 큰 문제이다.

현재 사용하고 있는 방법은 원하는 앱들을 모두 설치하고 나서 아래와 같이 하는 것이다.

$ sudo mount /dev/sda2 /mnt
$ cd /mnt
$ sudo btrfs sub snap @home-19.04 @home-new
$ cd /mnt/@home-new/aaa
$ rm -rf ./.*
$ cp -R /mnt/@home/aaa/.* .
$ cp /mnt/@home-19.04/aaa/.bashrc .
$ cp -R /mnt/@home-19.04/aaa/.config/VirtualBox .

$ sudo mv @home @home-19.10
$ sudo mv @home-new @home
$ sudo reboot

댓글 없음:

댓글 쓰기