Pi 3B+ 하나가 망했기 때문에 복구하기 위한 대장정을 시작한다
일단 자동으로 켜져야 할 에이전트가 안 켜지고, SSH 접근도 안 된다

그리고 직접 키보드와 모니터를 연결해 봤지만 어째 로그인도 안 된다. 패스워드 관리를 나름대로 철저히 하고 있다고 생각하는데... 로그인이 안 되다니... 갑자기 이거 혹시 취약점 공격이라도 당한 게 아닌가 하는 불안감이 든다

microSD 카드를 뽑아서 직접 파일시스템을 수정한다.
/etc/passwd 를 고쳐서 jdoe:x:1001:1001:John Doe:/home/jdoe:/bin/bash 중에서 x 부분을 삭제하면 된다고 하는데... 적용 후 (인터넷 연결 안 하고) 키보드와 모니터만 연결한 상태로 다시 tty 로그인을 시도해 본다. 안 된다!
파이에서 F2FS 써서 이득을 누리기... 라고 써 놓고 보니 내가 힙스터인가 하는 생각이 든다. F2FS - ArchWiki 에도 흉흉한 이야기가 가득함.

근데 저거 다 몇 년 전 얘기고 지금은 저 정도로 혼파망은 아니고요. F2FS 도 그간 꾸준한 개발로 많이 성숙했습니다. 제가 Pi 3B+ 에서 F2FS 를 루트 파일시스템으로 쓰고 있습니다. 물론 그래서 얻은 것이 무엇이냐 하면 잘 모르겠다.

F2FS 란 무엇인가: 플래시메모리는 기존 저장매체와 영 다른 작동특성을 갖는다. SSD 의 경우 펌웨어에 심오하고 숭고한 묘리를 담아 플래시메모리의 온갖 고통과 액난을 유유히 건너가지만, microSD 같으면 그것도 불가능하다(펌웨어 넣을 공간이 어딨어). F2FS 는 플래시메모리의 이런 약점을 파일시스템 층위에서 보완하려는 설계 사상이다. 이론상으로는 플래시메모리가 제공하는 인터페이스를 플래시메모리의 특성에 맞게 적절하게 잘 활용하는 파일시스템이며, 성능 벤치마크도 ext4 등에 비해 우수하다. 파일시스템 구현이 오래 전부터 메인라인 커널에 들어가 있으므로 국밥처럼 든든하다. (물론 유틸리티는 당연히 별도다.)

그래서 무슨 짓을 했는가: 이 Pi 3B+ 처음 설정할 때, Pi OS 이미지 있는 그대로 갖다 쓰지 않고 굳이 루트 파일시스템을 F2FS 로 설정하는 삽질을 했습니다. Pi OS 설정해 보신 분들은 아시겠지만 그냥 ext4 쓰면
dd 한 번으로 microSD 준비가 끝난다. 반면 F2FS 를 루트 파일시스템으로 쓰려면 microSD 를 수동으로 파티셔닝 하는 것은 물론이고 Pi OS 이미지를 루프 디바이스로 마운트하네 어쩌네 하며 별 삽질을 다 해야 함.

그 짓을 해서 행복한가: 뭔가 전반적으로 빠른 것 같기는 한데 잘 모르겠습니다. 사실 제대로 알고 싶으면 벤치마크를 돌려야겠지만 그러면 microSD 를 마모시켜야 되잖아. microSD 의 마모를 줄이려고 F2FS 를 쓰는 건데. 주객전도다. 그래서 차마 못하고 있다. 몇 년째...
F2FS - ArchWiki

아무튼 파이 서버가 안 올라오던 문제: 에이전트 보고도 없고 SSH 접근도 안 되고... 직접 콘솔로 붙어 보니 커넥티비티가 없다. ping 8.8.8.8 이 안 된다. 왜 안 되는가? IP 주소를 못 받는가? DHCP 문제인가? DHCP 는 잘 되었다. 근데 놀랍게도 DHCP 가 잘 된 결과 IP 주소를 예전 것과 새 것 두 개를 잡고 있었다. 애초에 전 ip addr 했을 때 하나의 인터페이스에 두 개의 inet 이 뜰 수 있다는 것을 이번에 처음 알았습니다.

원인은 예전에 이 파이의 NM 설정에 "선호하는" IP 주소를 넣어 두려고 했던 것이었다. 그게 되겠냐. 근데 이러고서도 그 IP 주소를 실제로 할당받는 데에는 몇 년 동안 문제가 없었는데, 첫째로 MAC 주소가 동일하고 (따라서 ISP 가 매번 웬만하면 같은 것을 준다) 둘째로 리부트가 대개 새벽에 unattended-upgrades 에 의해 자동으로 일어났기 때문이었다. 새벽 네 시는 인간이 가장 잔인해지는 시간대로서, 장치 추가든 재설정이든 그냥 아예 뭔가를 잘 하지 않는다. 그래서 이 시간대에 시스템이 꺼졌다 켜져도 주소를 그대로 다시 점유할 수 있었던 것. 운 좋게.

그러나 이번에는 아주 오랜만에 낮 시간대에 하드웨어 전원 내리고 작업을 한 결과, 몇 년 동안이나 유지하던 IPv4 주소를 상실하는 비참한 수모를 겪었다. 근데 그것뿐이면 사실 언젠가는 다시 올라왔을 가능성이 높은데, 시스템은 계속 이 주소를 탈환 (...) 하려고 할 것이고 그러면 점유자가 이탈하는 순간 되찾을 가능성이 있기 때문이다. 근데 어이없게도 DHCP 도 작동해서 하나의 인터페이스에 두 개의 IP 주소가 뜨고 이 상태로 과연 인터넷 프로토콜이 동작하는지 아닌지도 알 수 없는 상태가 되어 버렸다.

예전에 "선호하는" IP 주소 넣어 두려고 했다가 (이때는 아주 높은 업타임을 지향했다) 좀 아닌 것 같아서 다시 없애려고 했던 것 같은데, 제대로 없애지 못하고 뭔가 이도 저도 아닌 상태로 남은 듯... 기억이 안 난다... 반성합니다. 게다가
sudo nmcli 쳐서 설정했던 부분이라 어디 설정 파일에 있는 것도 아니고, 다른 머신에는 전혀 없는 설정이니 더더욱 발견할 수 없었다.

이게 다 결국 DHCP 가 "웬만하면" 같은 IP 주소를 주는 게 문제다. 다이내믹이면 다이내믹답게 매번 다른 주소를 줘야 하는 것 아닙니까? (아님)

의도적으로 긴 다운타임을 만들든지 아니면 MAC 주소를 조금씩 흔들든지 해서 일부러 IP 주소 바뀌게 하면서 에이전트 잘 되고, DynDNS 잘 되는 것을 보장하는 체제를 만들어야 할 것이라는 결론이다. 으윽
그누/리눅스 시스템은 부트 시퀀스에서 루트 파일시스템을 RO (read-only) 로 우선 마운트한 뒤, /etc/fstab 적용 단계에서 RW (read-write) 로 리마운트하는 "RO first, RW later" 를 기본 동작으로 하는 경우가 많습니다.

이 짓을 왜 하는가? 가장 큰 장점은 루트 파일시스템에 대해 "RW 마운트 중에는 불가능한 일" 을 할 수 있다는 것입니다. 예를 들어 많은 파일시스템이 "RW 마운트 중 fsck" 를 지원하지 않습니다. 아무래도 체크섬, 오토 힐 등을 하려는 경우 RW 마운트 중에는 힘들죠 (Btrfs 같은 외계 기술만 예외). 또 하드웨어든 소프트웨어든 문제가 있어서 시스템이 부팅 초기에 거듭 실패하는 경우, 루트가 RW 마운트 중이면 루트의 "깨짐" 이 더 악화될 수 있겠죠. 그래서 적어도 fsck 를 수행할 수 있을 만큼 멀쩡한 시스템 상태가 완비되고, fsck 가 수행되고, 완료될 때까지 루트는 RO 로 둔다는 전략입니다. 그럴듯하죠.

문제는 마운트 옵션을 변경하려는 경우입니다. 예를 들어 F2FS 마운트 옵션 중
flush_mount, atgc 등은 첫 마운트 시점에 들어가야 하고, RO-RW 리마운트 시점에는 넣을 수 없습니다. 따라서 이것들을 /etc/fstab 에 넣고 리부트 해 보면 리마운트가 실패하며 (dmesg 로 볼 수 있음) 루트가 RO 인 채로 부팅이 됩니다. 이러면 시스템은 당연히 마비 상태입니다. 이래도 systemd 서비스들이 꿋꿋이 뜬다는 게 신기할 정도.

최악의 경우 "설정이 잘못되었는데 그 잘못된 설정의 수정도 불가능한" 수렁에 빠지겠죠. 주의하십시오. 어떻게 알았는가? 저도 알고 싶지 않았다.

F2FS 마운트 옵션 문제로 RO 마운트 상태에 빠졌다면 dmesg | grep -i f2fs 로 찍어 볼 수 있다. 대충 이런 게 찍힌다.

F2FS-fs (mmcblk0p2): FLUSH_MERGE not compatible with readonly mode
Pi OS 기준 제일 간단한 해결책은
/boot/firmware/cmdline.txtrw 추가하는 것이다. 그러면 루트 파일시스템이 처음 마운트 될 때부터 RW 로 마운트 되므로, 문제가 없어진다. 급한 불은 껐다.

그러나 이게 "올바른" 해결책인가? 들여다본다. 첩첩산중이다. 전산학이 아니라 역사학이다. 결론부터 말하자면
rw 해도 되는 것으로 보인다.

- 요오즘 대부분의 그누/리눅스 배포판은
최초 램디스크 를 쓴다. 이것은 파일시스템 하나를 통째로 담고 있는 "디스크 이미지 압축 파일" 이다. 부팅 시 이것을 메모리에 압축 풀어 놓으면 그게 그대로 파일시스템이 되며, OS 가 된다. initrd 와 initramfs 가 미묘하게 다르지만, 비닐봉투에 담느냐 종이봉투에 담느냐 정도의 차이일 뿐 하는 일은 비슷하다.
- 근데, 루트 파일시스템을 담고 있는 파티션이 있을 텐데 왜 그걸 그냥 쓰지 않고 굳이 무슨 램디스크 이미지 같은 것을 따로 쓰는가? 그것은 말이여. 요오즘 젊은이들이 바라는 게 많아서 그랴! 예를 들어 루트 파일시스템에 FDE 되어 있으면
cryptsetup open 같은 걸 누군가 해 줘야 한다. 그렇다. initramfs 와 루트 파일시스템의 관계는 대한민국 임시정부와 대한민국 정부의 관계이다.
- 이 initramfs 이미지를 굽기 위해 데비언 계열에서는 커널이나 관련 패키지 버전 올라갈 때마다 update-initramfs 돌아가는 것을 볼 수 있고 아치에서는 mkinitcpio 돌아가는 것을 볼 수 있다.
- initramfs 를 쓴다면 "fsck 를 위해서 RO first, RW later 한다" 같은 것은 무의미한 소리가 된다. initramfs 는 이름 그대로 파일시스템이며 OS 로 기능할 수 있다. 독립국이다. 얘가 fsck 하면 된다. RO 고 RW 고 나발이고, 루트 파일시스템은 마운트할 필요조차 없다.
- Pi OS 는 원래 initramfs 를 쓰지 않았다 (!). 이유는 모르겠음. 짐이 지금 1GB 더 절약해 보겠다고 눈물의 관심법을 하고 있는데 어찌 임시정부 하나를 통째로 구워서 microSD 의 소중한 공간을 차지할 수가 있느냐 이 미련한 것아! 하면서 철퇴 당한 게 아닐까?
- 그러나 이제 microSD 도 기본 수백 GB 단위로 나오는 세상이 와 버렸으며 8GB 같은 것은 잘 팔지도 않는다. 그래서 Pi OS 도 기본 동작이 바뀌었다. 이제 기본 이미지에도 initramfs 들어 있고,
apt upgrade 하면 알아서 새 버전 구워지고, /boot/firmware/config.txt 에는 auto_initramfs=1 이 기본값이다.
- 따라서 initramfs 를 굳이 따로 껐다든지, 옛날에 구성한 오래된 Pi OS 를 쓰고 있다든지, 그런 게 아니라면 initramfs 이미 잘 쓰이고 있을 것이다. 그러므로
cmdline.txt 에서 ro 하느냐 rw 하느냐와 무관하게 fsck.mode 의 값은 본인의 기호에 맞는 매운맛으로 조절하면 된다.

Initial ramdisk - Wikipedia

"이제 곧 F2FS 삽질이 끝난다"
"F2FS 삽질이 끝나면 어떻게 되는데?"
"모르는가? 새 F2FS 삽질이 시작되지"

으휴

F2FS 마운트 옵션으로 atgc, checkpoint_merge 등을 넣고 싶다. 문제는 이걸 /etc/fstab 에 넣으면 systemd-remount-fs 가 실패하며, 옵션은 적용이 안 된다는 것이다. 루트 파일시스템은 initramfs 시점에서 이미 마운트당했고 그걸 다른 마운트 옵션으로 리마운트하려다가 망하는 것이다.

다른 파일시스템 같으면 "RO 후 RW 리마운트" 라는 전략에 아무 문제가 없다. 리마운트 하면서 마운트 옵션 바꾸는 것도 어지간하면 다 된다. 하지만 F2FS 는 그런 거 애초에 지원 안 한다고 한다. 진짜냐? F2FS 의 비위를 맞추겠다고 깨진 멘탈이 질펀했습니다. 이 모든 삽질을 하면서 나는 무엇을 얻고 있는 것일까요?

아무튼 처음부터 RW 로, 그리고 원하는 옵션 넣어서 마운트하는 수밖에 없다. 예를 들어
cmdline.txt

rootflags=noatime,nodiscard,checkpoint_merge,flush_merge,atgc,data_flush,fsync_mode=strict
같은 걸 끼얹는 것이다. 이게 될까? 지금 리부트해 보겠습니다. (플래그)

리부트는 잘 되었다. 그러나 이 시스템이 사용되는 일은 없었다. F2FS 와의 사투에 모든 힘을 쏟아낸 xt 는 이 서버를 전혀 써먹지 않고 의욕 상실, 무기력 상태로 뒹굴었다.