Ubuntu Server: Btrfs Subvolume 사용 설치(NVMe). v2

원 글과 비교하여, 몇가지 내용이 추가되었다. 원 글은 비교를 위해 그냥 남겨두기로 한다.

  • var(@var) – NoCoW 설정
  • 서브볼륨 세분화
  • /var/lib/dpkg root 로 link(ln -s)

우분투 서버 이미지에는 두가지가 있다. live 가 붙은 것과, 그렇지 않은 것.
서버 설치 프로그램면에선 live/비 live 가 확연히 다른데, 정작 설치된 서버 자체는 미묘한 차이만 있는 듯 하다.

아무튼, 이 글은 ‘Live’ 판을 기준으로 작성했다.


아직 개발 중인 우분투 20.04 Live 이미지로도 시험해봤는데, 아주 약간 다른 점(/run 관련)이 있지만 무사히(?) 잘 설치할 수 있었다. 정식판이 나오면 이 글도 살짝 수정할 예정. (잊지 않겠지?)


우분투 서버를 설치할 때, 파일시스템을 Btrfs 로 선택할 순 있지만, 서브볼륨을 설정하고 사용할 순 없다. OpenSuse 는 설치프로그램이 정말 완벽하다할 수 있을 정도인데, 우분투는 이 부분이 많이 아쉽다.

이를 극복하려면, 마치 ArchLinux 를 설치할 때처럼 약간의 지식이 필요하다.
이 글에서 간단하게 그 방법을 정리해보기로 한다.
다음 글에서 도움을 얻었다.

Ubuntu Server 18.04 btrfs raid1 (optionnal)


Ubuntu Live Server 디스크 이미지로 설치 진행

우분투 서버 설치 디스크(18.04, HWE 커널)로 부팅한 후 진행하다가, 파티션 작업에서 두가지를 해줘야 한다.

  • / 를 btrfs 로 설정
  • /boot 를 ext4 로 설정. (약 1GB)

디스크 파티션에서, /boot 영역(1GB 정도)을 따로 만드는게 Btrfs 를 사용할 때 여러모로 편리한 면이 있으므로, /boot 파티션을 따로 만들고, 파일시스템은 ext4 로 해준다. (예전에 어떤 책에서는 ext2 를 추천했었는데, 여기선 아예 ext2 를 선택할 수 조차 없다.)

** /boot 파티션(ext4)은 꼭 해야하는 필수사항은 아니다.

/boot 파티션을 만들면, /boot/efi 는 자동으로 생성된다.

파티션 예.

그리고 끝까지 진행한다.

** 파티션 작업이 은근히 불편하다. 꼭 저 화면에서만 파티션 작업을 해야 한다. (미리 나눠놓은 파티션은 인식은 하지만, 마운트 할당등은 불가능하다.)

계속 진행하다가, 마지막 단계(12/12, 또는 13/13) 가 되었을 때, Reboot Now 를 택하지 말고, Ctrl-Alt-F2(VBox 의 경우, 메뉴 – 입력 – 키보드 – Soft Keyboard) 를 입력한 뒤 두번째 가상 콘솔로 이동한다.

이곳으로 가면, 이제 자유롭게(?) 명령어들을 입력할 수 있다.
좀 더 원활하게 하기 위해 Dvorak 으로 전환한다. (20.04 부터는 아래 작업을 안해도, 설치 시에 Dvorak 을 선택했다면 그냥 Dvorak 이 적용된다.)

sudo dpkg-reconfigure keyboard-configuration
... 일련의 설정을 끝내고..
sudo setupcon

setupcon 을 해줘야 변경이 즉각 반영된다.

** 모든 명령은 sudo -i 후 관리자 권한으로 진행한다.

이제 여기서 해야할 일은 다음과 같다.

  • Btrfs 압축을 원한다면, defrag 실행.
  • Btrfs Subvolume 생성
  • 생성된 Subvolume 으로, 설치 프로그램이 만든 파일들 복사
  • 서브볼륨을 사용해 새 루트 시스템 mount 후, chroot 작업
  • fstab 수정
  • 부트로더 수정

복잡해보이지만, ArchLinux 는 저런 식으로 설치해야만 한다. 그것에 비하면 훨씬 간단한(?) 작업이다.

작업을 편하게 하기 위해 sudo -i 로 관리자로 전환한다.
원 글에서는 /target 을 나중에 umount 하라고 되어 있는데, run 디렉토리 때문에 그럴 수가 없었다(오류 발생). 따라서 그냥 umount 는 없이 진행한다.

/target 확인

우분투 서버 설치 프로그램은 /target 디렉토리에, 위에서 작업한 일련의 파티션들을 마운트 한 후 시스템을 구성한다. 따라서 먼저 저 디렉토리를 확인해본다.

ll /target # 잘 설치되어 있는지 확인한다.

그 뒤 lsblk 로 현재 디스크 상황도 파악한다.

설정한 대로, ESP, boot, / 모두 잘 만들어져있다.

Btrfs Compression

만약, Btrfs 의 Compression 기능을 원한다면, 이 시점에서 /target 을 압축해줘야 한다. 후에 fstab 에서 btrfs compression 을 줄 경우, 추후에 생성되는 파일들에 대해서만 압축이 이뤄진다. 따라서, 이왕 할거라면 지금 압축 작업을 해주는게 좋다. (물론, 나중에 시스템이 완성된 후에 해도 된다. 아마도.)

btrfs filesystem defragment -r -v -clzo /target

-clzo 가 핵심인데, 현재 Btrfs 는 zlib, lzo, zstd 세가지 압축 방식을 지원하고 있다. 여기서, 압축효율과 속도를 감안하여 가장 추천(?)하는게 lzo 라고 한다. 기본값은 zlib 이다.
압축 시간은 몇분 걸리지 않는다.
압축이 됐는지 여부는, 나중에 compsize(apt install btrfs-compsize)를 통해 알아볼 수 있다.

Sub Volume 생성

이제 /target 으로 이동하여 Btrfs Subvolume 을 생성한다.
우분투는, @ 을 시스템 루트(/)로, @home 을 /home 으로 사용한다.
헌데, OpenSuse 를 보니 보다 다양한 서브볼륨을 사용하고 있었다. 서브볼륨을 사용한다는 의미는 결국 Snapshot 을 활용한다는 뜻이 되므로, 적절히 추가하는게 효과와 효율면에서 더 나은 선택이 될 수 있다고 본다.
물론, ‘관리’가 가능하다는 전제 하에.

하여, OpenSuse 를 최대한 참고하고, Snapper 를 사용한다는 전제하여 다음과 같이 서브볼륨을 사용하기로 했다.
왼쪽은 서브볼륨, 오른쪽은 마운트 포인트.

  • @ : /
  • @home : /home
  • @var : /var
  • @tmp : /tmp
  • @srv : /srv
  • @root : /root
  • @opt : /opt

OpenSuse 와 다른 점은, usr/local 서브볼륨이 없고, 서브볼륨 구조가 Nested(OpenSuse)가 아닌 Flat 형이라는 점이다.

또, 저 서브볼륨들을 독립된 파티션에 만들 것인지, 아니면 한 파티션에 서브볼륨으로만 만들 것인지도 고민이 됐는데, 그냥 한 파티션만 사용하기로 했다.
만약 파티션이 다르다면, 아래에 서술할 mount 작업에서 적절히 바꿔주기만 하면 되겠다.

cd /target # /target 은, 우분투 설치 프로그램이 작성한 새 시스템 디스크 영역의 / 다.
btrfs subvolume create @
btrfs subvolume create @home
btrfs subvolume create @var
btrfs subvolume create @tmp
btrfs subvolume create @srv
btrfs subvolume create @root
btrfs subvolume create @opt

# set default 는 해주는게 좋다.
btrfs subvolume set-default @

set-default 에 관한 설명은 나중에.

@var NoCoW 설정 및 파일 복사.

@var 에는 NoCoW 를 설정하는게 권장된다고 하므로, 다음과 같이 설정한다.

chattr +C /target/@var

다음 단계에선 파일을 이동(mv)해야 하지만, 여기선 복사를 해줘야 한다. 이유는 NoCoW.
NoCoW 를 시행하려면, 파일을 새로 복사해야하고, 기존의 파일을 그냥 옮기면 아무 효과가 없다.
복사를 한 뒤에는 /var 밑의 파일들은 필요없으므로 지운다.

cp -rp /target/var/. /target/@var
rm -rf /target/var

/var/lib/dpkg 위치 새롭게 설정

Snapper 사용 시 사소한 dpkg 문제가 생길 수 있다. 이를 위해선 이 디렉토리를 루트 Snapshot 에 포함시켜야 하는데, 뭔가 다른 방법이 있을 수도 있겠지만, 간단하게 이런 식으로 처리하기로 했다.

방법 : /var-dpkg 를 만들고, /var/lib/dpkg 를 심볼릭링크로 걸어준다.

실제 작업은 chroot 이후에 해준다.

/target 디렉토리 서브볼륨으로 복사/삭제

위 작업(@var)과 같지만, NoCoW 는 하지 않는다.

현 시점에서 home, opt, srv 는 비어있으므로 복사를 해줄 필요는 없다.
(mv 를 해도 되는데, 그리 하면 /target/root 아래 있는 .bashrc 등을 어떻게 옮겨야 하는지 방법을 알아내지 못했다. 게다가, 어차피 디렉토리(tmp, root 등)를 지워야 하므로, 그냥 복사후 삭제를 택했다.)

# 복사
cp -rp /target/tmp/. /target/@tmp
cp -rp /target/root/. /target/@root

# 삭제
rm -rf /target/tmp/*
find /target/root -mindepth 1 -delete

/target/root 에는 . 으로 시작하는 파일들이 있는데, 이걸 rm 으로 지우기가 쉽지 않아서 find 를 사용했다.

/target 내부 파일 서브볼륨 @ 으로 이동

이제, /target 안에 생성되어 있는 파일들을, 서브볼륨 @ 안으로 적절히 이동시킨다.
그에 앞서, /target/boot 와 /target/boot/efi 는 마운트 해제해줘야 한다. 이건 독립 파티션이므로, 이동(mv)시킬 필요가 없다.
순서는 efi 를 먼저, boot 를 나중에.

** cdrom 디렉토리는 /target/run/cdrom 이 아닐 수도 있다. 확인 후 적절히 umount 해줘야 한다.

Unmount 작업

umount /target/boot/efi
umount /target/boot
umount /target/cdrom 또는 umount /target/run/cdrom

파일 이동

mv -t @ b* d* e* h* i* l* m* o* p* root s* t* u* v*

run 디렉토리는 mv 가 안된다. 굳이 이 디렉토리를 이동해줘야 할 필요는 없기에 아예 이동시키질 않았다. (예전엔 r* 로 root, run 을 모두 이동시켰지만, root 만 해줬다.)

만약 이동해주면, 아래에서 할 chroot 이후에도 네트웍 관련 작업(apt 등)을 그대로 할 수 있게 된다.
따라서, 이 작업이 필요하다면, 그리고 mv 시 run 디렉토리 관련 오류가 난다면, mv 말고 run 디렉토리를 ‘복사’ 해준다.

cp -rp /target/run /target/@

만약, run 디렉토리가 mv 로 오류없이 이동한다면 그대로 하면 된다.
내 상식으로는, run 디렉토리는 시스템 첫 부팅 시에 새로 만들어지기 때문에, 굳이 남겨놓을 필요는 없다.

서브볼륨을 사용한 /target 재구성

/new-target 을 생성하여 새롭게 시스템을 재구성한다.
워낙엔 /target 을 마운트 해제하고 작업했는데, run 디렉토리로 인해 이게 불가능하게 됐다. (Busy 오류가 나오면서 마운트 해제가 되지 않을 경우가 있다.)

따라서 굳이 umount 를 하지 말고, /new-target 등을 새로 만든 후 그 이하로 아래 작업을 시행하면 된다.

home, opt 는 지금은 mount 해주지 않아도 된다. (현 시점에선 쓸모가 없다.)

또, 원 글에서는 여기에 mount compress 옵션을 줬는데, /target 이 umount 가 되지 않는 상황에선 이 옵션을 줘도 의미가 없다. 게다가 굳이 지금 compress 를 줄 필요도 없다.
나중에 fstab 에서만 옵션을 주면 된다.

cd /
umount /target #(오류가 나면 하지 말고, mkdir /target2 를 만든 뒤 아래를 모두 target 2 로 바꾼다.)
mkdir /target2 #(또는 new-target 등, 원하는대로)

# /, 즉 @ 가 있는 디스크/파티션
mount /dev/nvme0n1p3 /target2 -o subvol=@ # set-default 를 해줬기 때문에 subvol 은 굳이 없어도 되지만.
# /boot 가 있는 디스크/파티션
mount /dev/nvme0n1p2 /target2/boot
# ESP 가 있는 디스크/파티션
mount /dev/nvme0n1p1 /target2/boot/efi

# @var 가 있는 디스크/파티션
mount /dev/nvme0n1p3 /target2/var -o subvol=@var

# 기타 @srv 등은 지금은 필요없다.

mount --bind /proc /target2/proc  
mount --bind /dev /target2/dev  
mount --bind /sys /target2/sys

만약, 위에서 set-default 를 해주지 않았다면, 다음과 같이 @ 를 명시해주는게 여러모로 편하다.

mount /dev/nvme0n1p3 /target -o subvol=@

fstab 수정

이젠, fstab 을 수정해줘야 한다.
chroot 한 뒤 해도 되지만, 지금도 할 수 있다.
lsblk 를 참고하여, fstab 을 아래와 같이 고친다.
맨 먼저 / 를 마운트 해야 하고, 그 후에 home 등을 해주면 된다. (당연하지만, 여기선 반드시 home, opt, var 등 Subvolume 으로 만든 모든 것들을 포함시켜줘야 한다.)

Btrfs 의 현재 제약으로 인해, 마운트 옵션을 서브볼륨별로 달리 줄 수가 없다. 따라서, compress 등 옵션은, 맨 첫 서브볼륨(루트)에만 주고, 나머지엔 써주지 않아도 모두 동일한 옵션이 적용된다.

/boot 를 먼저, /boot/efi 를 나중에 해야 함도 잊지 말 것.

lsblk -f
NAME         FSTYPE   LABEL UUID                                 MOUNTPOINT
nvme0n1                                                          
├─nvme0n1p1  vfat           zzzz                            /target/boot/efi
├─nvme0n1p2  ext4           yyyy                            /target/boot
└─nvme0n1p3  btrfs          xxxx                            /target


vim /target2/etc/fstab
UUID=xxxx 	/ 		btrfs 	defaults,compress=lzo,subvol=@ 0 0
UUID=xxxx 	/home 		btrfs 	subvol=@home 0 0
UUID=xxxx 	/var 		btrfs 	subvol=@var 0 0
UUID=xxxx 	/opt 		btrfs 	subvol=@opt 0 0
UUID=xxxx 	/srv 		btrfs 	subvol=@srv 0 0
UUID=xxxx 	/root 		btrfs 	subvol=@root 0 0
UUID=xxxx 	/tmp		btrfs 	subvol=@tmp 0 0
UUID=yyyy 	/boot 		ext4 	defaults 0 0
UUID=zzzz	/boot/efi 	vfat 	defaults 0 0

밑밥은 끝났다. chroot 로 가상 시스템으로 접근한 뒤, /var/lib/dpkg 를 / 로 이동시켜주고, 링크를 만든 뒤, 부트로더 관련 작업들을 해주면 긴 장정이 끝나게 된다.

chroot 작업

chroot /target2

# dpkg 디렉토리 이동
mkdir /var-dpkg
cp -rp /var/lib/dpkg/* /var-dpkg
rm -rf /var/lib/dpkg
ln -s /var-dpkg /var/lib/dpkg

# 혹시 몰라서.. (/run 이 없으면 부팅 시에 오류 발생 가능성이 있다.)
mkdir /run

# 커널 등록
update-initramfs -u -k all  
grub-install --recheck
update-grub  

** cryptsetup 관련 오류

update-initramfs 을 하고 나면, cryptsetup 관련 오류가 발생한다.
이것은 ext4 로 설치했을 땐 생기지 않는데, 아마도 Btrfs 관련한 오작동으로 보인다.

cryptsetup 2.0.2 까지 이 버그가 있다고 하는데, 우분투 18.04 까지는 2.0.2 가 제공되고 있기에, 피해갈 방법은 없다.

그냥, cryptsetup 꾸러미를 지워버리는게 가장 단순하지만 효과 만점인 해결책이었는데.. 2020년 2월 현재, 이 꾸러미를 지우면, ubuntu-server 꾸러미도 지워진다.
따라서, 그냥 이 문제는 그냥 무시하고 넘길 수 밖에 없다.
데비안 보고에 따르면, 2.0.3 부터는 해결이 된 모양인데, 우분투 20.04(현재 한창 개발중..)에는 2.2.x 가 들어있었고, 그래서인지 이 문제는 없었다.

이렇게 끝!
exit 후, 원래 콘솔로 돌아가서 reboot 를 택해주면 된다.

설치가 끝나고 할 일!

위 설치에서 약간 찌꺼기(?)가 남는다. FS_Root(파일시스템 root)에 run, cdrom 디렉토리가 지워지지 않고 그대로 남아있게 된다.

이건 그냥 부팅해서는 볼 수가 없고, 이 디스크를 다시 마운트 해줘야 볼 수 있는데, subvolume set-default 를 했다면, 마운트 시에 subvolid=5 를 추가해줘야만 이 디렉토리들을 볼 수 있게 된다.

이 작업은, 새로 만든 시스템으로 부팅한 후 해야 한다.

sudo mount /dev/xxxx /mnt -o subvolid=5

ll /mnt
drwxr-xr-x 1 root root 238 2020-01-29 00:30 @
drwxr-xr-x 1 root root  30 2020-01-16 17:22 @home
drwxr-xr-x 1 root root   0 2020-01-13 22:37 @opt
drwxr-xr-x 1 root root 128 2020-01-22 15:57 @var
drwxr-xr-x 1 root root 128 2020-01-22 15:57 @root
drwxr-xr-x 1 root root 128 2020-01-22 15:57 @srv
drwxr-xr-x 1 root root 128 2020-01-22 15:57 @tmp
drwxr-xr-x 1 root root   0 2020-01-13 22:37 cdrom
drwxr-xr-x 1 root root 128 2020-01-22 15:57 run

이런 식으로 cdrom 과 run 이 남아있을 가능성이 있다. 불필요하므로 지워준다.

또, cloud-init 꾸러미도 (적어도 내겐) 불필요하다. 저게 뭔지 설명을 읽어봤음에도 이해를 못하겠다.

sudo apt purge cluod-init --autoremove

이후, 여러가지 작업이 필요하겠지만, 로캘(locale) 설정, 시간대 설정이 가장 최우선이다.

로캘설정은 몇가지 방법이 있겠지만, dpkg-reconfigure 를 이용하는게 편하다.

sudo dpkg-reconfigure locales

시간대 설정도 같은 명령으로 가능하다.

sudo dpkg-reconfigure tzdata

이제 서버를 원활하게 사용하기 위한 세부 설정이 남아있다!!

Add a Comment

Your email address will not be published. Required fields are marked *