2024년 8월 21일 수요일

ZFS만으로 우분투를 구동하는 모험

 1. 저지르기

우분투가 설치 때부터 ZFS를 쓸 수 있게 지원하지만, 나는 그 한참 전부터 시스템을 굴려왔었고, ZFS를 도입할 때도 단순히 데이터 저장용으로만 ZFS를 구성했다. 중간에 OS 디스크를 교체하는 경우는 종종 있었지만 Clonezilla 같은 걸로 OS 디스크끼리만 복사하면 충분했기 때문에 ZFS 디스크들은 계속 데이터 저장용으로만 남아 있었다.

 

여차저차한 이유로, 퇴역시켰던 HP 마이크로서버를 다시 활용하겠다는 생각이 들었다. 하지만 그 사이 OS는 NVMe로 넘어온 상태였고 마이크로서버에는 NVMe는 없기 때문에 SATA로 디스크를 복사하는 게 가장 흔한 선택이었겠지만 NVMe로 넘어가면서 1테라 용량을 선택했는데 애석하게도 가지고 있는 SATA 디스크 중에는 그런 용량이 없었기 때문에 다른 방법을 찾아야 했다.

 

가장 먼저 떠올린 건 그냥 돈을 써서 SATA 디스크를 하나 사는 거였지만 채택하지 않았다. 추가 지출은 피하고 싶은 상황이기도 했고 그렇게 바꾸고 나면 저용량 디스크는 용도가 애매해져서 결국 디지털 쓰레기에 일조하게 되는 것도 싫었다.

다음으로는 어떻게든 사용 용량을 줄여서 쓰던 SATA로 되돌아가는 거였지만 이리저리 줄여봐도 이미 방만해진 사용량을 아주 홀-쭉하게 줄이는 건 어려웠다. 어지간한 건 다 ZFS 쪽으로 빼내서 SATA에는 최소한만 남기는 식이 되어야 했는데 이럴 바에는 ZFS로 다 옮기는 게 맞다.

그렇다면 본격적으로 ZFS를 OS로도 쓰는 모험을 감행할 차례였다. 실은 우분투가 정식으로 ZFS 설치를 지원하기 시작한 때부터 옮겨갈까 생각하긴 했었다.

 

하지만 막상 결심은 쉽지 않았다. ZFS를 도입한 뒤 충분한 용량 때문에 관리의 필요를 거의 못 느꼈고 지금에 와서는 자잘한 파일들이 잔뜩 쌓여서 혹시라도 사고가 생기는 날에는 뭐가 날아갔는지 파악조차 어려울 지경이었다. 사고를 피하려면 ZFS 전체 내용을 백업해둬야 했지만 지금에 와서 그만한 용량의 디스크를 따로 마련하자니 추가 지출이 발생하고, S3로 백업하는 것도 거기에 들어가는 시간은 둘째 치고 S3 용량과 전송량을 생각해봤을 때 AWS 비용면에서 같은 용량의 디스크를 사는 것과 별반 차이가 없어 보였다.

그래서 그냥 저질렀다. (https://github.com/openzfs/zfs/discussions/16120 코멘트에 따라 snapshot은 만들어두었지만 정말 큰 사고가 생긴다면 이것도 도움이 안 될 거라고 생각했다)

 

2. 어떻게 저질러야 하나

처음에는 우분투의 설치 과정을 따라가다가 보면 "이미 있는 ZFS 풀"에 설치하는 방법도 제시하지 않을까 하는 기대를 하고 라이브 USB를 만들어서 켜봤지만 그런 옵션은 없었다. 디스크를 다 지우고 진행하는 선택지만 있었다. OpenZFS에서 제공하는 문서를 봤지만 https://openzfs.github.io/openzfs-docs/Getting%20Started/Ubuntu/Ubuntu%2022.04%20Root%20on%20ZFS.html 이것도 "이미 있는" 뭔가를 다루는 게 아니라 새로 설치하는 방법을 안내하는 거였다. 아마 우분투가 이 흐름을 따를 터였다. 이걸 따라갈 수는 없었다.

https://www.complete.org/converting-an-existing-linux-installation-to-zfs/ 이것저것 찾다가 본 이 문서는 꽤 그럴듯해 보였다. 하지만 여전히 어떻게 흘러가야 하는지 잘 눈에 들어오지 않았다. https://stackoverflow.com/a/61506953 에서 간명하게 세 단계로 진행된다고 하는 편이 차라리 안심하는 데 도움이 되었다.

 

무엇보다 필요한 건 어쨌든 ZFS로 OS 내용을 옮기는 거였다. OS가 ZFS로 넘어가 있어야 ZFS로 부팅한다는 행위가 성립할 테니까.

그래서 우선 떠있던 데몬들은 다 멈추고 라이브 USB로 부팅한 다음 rsync로 ZFS에 만든 풀로 루트 파티션 전체를 옮겨줬다. 하지만 왜인지 df, du로 확인한 용량은 ext4와 zfs가 서로 꽤 달랐고, FS에 따라서 다를 수 있다는 건 알고 있지만 그래도 너무 달라서 find로 출력한 전체 파일의 상대경로 비교를 해봤지만 find에는 있거나 없다고 나오는 파일이 실제로는 양쪽 다 있어서 find를 믿을 수 없었고, rsync 옵션을 av, avH, avc 같이 이것저것 줘봤는데 checksum이 너무 오래 걸려서 중도에 멈추고 결국 에러 없이 종료하는 rsync를 믿기로 했다.

그 상태로 fstab 파일에서 / 경로만 zfs로 바꿔서 열면 어떻게 될까 싶어 파일을 바꾸고 재부팅했지만 zfs로는 부팅되지 않았다. ext4로 루트가 잡힌 채로 부팅이 되었는데 뭔가 이상해서 살펴보니 ro 상태였다. 뭔가 에러 때문에 ro로 넘어온 걸까 의심했지만 dmesg에는 의심할만한 구석은 안 보였다. 망한 건가 싶었지만 이미 진창에 발은 디뎠고 진흙도 잔뜩 묻었으니 돌파하는 것 밖에는 다른 수가 없었다.


3. OS를 부팅한다는 것

루트 파티션이 준비되었으니, 설치 과정에 견주어 생각해보면 다음은 부트로더가 새 루트 파티션 기반으로 돌아가게 할 차례였다.

그리고 여기서 생각이 막혔다. 부트로더라 하면 BIOS가 부팅 장치로 인식하는 어떤 디스크를 구조적으로 바꿔야 하는 건데, ZFS는 그냥 디스크 전체가 ZFS로 잡혀있고 여러 디스크가 똑같은 구조이기 때문에 어느 하나만 부팅용으로 만든다는 개념이 와닿지 않았다. 깊게 들어간다면 MBR이니 GPT니 EFI니 하는 단어가 나와야 하지만 어쨌든 ZFS 디스크를 건드리고 싶지 않았다.

그래서 ZFSBootMenu를 검토했다. 사실 검색 초기부터 이 이름이 나오긴 했는데 가뜩이나 전체 그림이 안 잡히는 상황에서 뭔가 새로운 걸 다 파악하고 싶지 않아서 지나쳤다.

https://docs.zfsbootmenu.org/en/v2.3.x/guides/ubuntu/noble-uefi.html#install-zfsbootmenu 문서를 읽어보니 앞부분의 신규 설치 과정들은 다 했다고 치고 넘어갈 수 있어 보였다. 중요한 단계는 짚어보자면 이렇게 되는 거였다.

  1. ZBM은 빈 vfat에 EFI/ZBM/VMLINUZ.EFI 경로로 파일을 넣어준다.
  2. ZFS는 미리 zfs set 명령으로 ZBM이 인식하는 정보를 넣어준다.
  3. efivars 정보에 접근해서 efibootmgr 명령으로 ZBM을 EFI 부팅 항목으로 인식시킨다.

ESXi를 USB로 만들어서 부팅용으로만 쓰는 건 알고 있었기 때문에, ZBM도 빈 vfat이 꼭 기존 디스크의 파티션 중 하나일 필요는 없이 USB를 하나 만들어서 넣어주면 되겠다 싶었고, 실제로도 USB로 부팅에 성공했다.


4. 시작이 반이다. 아니 반이 시작이다.

부팅 후 확인했을 때 NVMe 디스크는 더 이상 시스템에 사용되지 않았다. 원하던 결과였다.

하지만 이건 이제 시작이고, 원래 하려던 HP 마이크로서버로의 귀환까지 마무리가 되어야 한다. 아마 ZBM을 EFI에 인식시키느라 재부팅을 몇 번 해야 할 것 같다. 그리고 기왕에 GRUB의 역할을 ZBM에 넘겼으니 그동안 GRUB으로 처리했던 부분도 ZBM에선 어떻게 하는지도 차차 알아봐야 할 것이다. (HP 마이크로서버에서 부팅해보니 EFI 쉘에서 직접 실행하는 걸론 안 되었지만 라이브 USB를 통해 efibootmgr로 등록해준 다음에는 라이브 USB를 제거해도 ZBM으로 정상 부팅됐다)

그 와중에 예전에 쓰던 OS를 부팅하면서 생긴 tailscale 겹침 증상 때문에 여차저차 tailscale 전체 노드를 새로 로그인해야 하는 번거로움이 있었다. rsync가 잘 되었는지도 약간 불안하기 때문에 debsums 명령으로 전체를 확인해서 일단 패키지 범위에서는 문제가 없음을 확인했다. docker는 의외로 이미지가 멀쩡하게 살아있는지 검사해주는 명령이 없어보여서 그냥 컨테이너가 떴으면 정상이려니 하고 넘어가기로 했다.

Dropbox가 zfs 같은 거 쓰지 말고 평범하게 ext4로 쓰라고 안내하는 건 이미 예전에 zvol로 반영해둔 상태라서 괜찮다. qemu를 NVMe 대신 zfs에서 굴리면 얼마나 속도 저하를 역체감할지는 걱정이다.

부디 아무 사고 없이 이 모험이 끝나기를.