Network Block Device 사용법

로컬 디스크가 부족하거나, diskless 클라이언트를 원격 스토리지로 부팅해야 하거나, 원격에 있는 이미지 파일을 로컬 블록 디바이스처럼 다루고 싶을 때가 있다. iSCSI가 이런 용도의 표준이지만 타깃 설정이 상대적으로 번거롭다. NBD(Network Block Device)는 커널 모듈 하나(nbd.ko)와 서버·클라이언트 툴만으로 같은 걸 훨씬 단순하게 해낸다. 이 글에서는 qemu-nbd로 이미지 파일을 export하고 nbd-client로 붙여서 실제로 파일시스템을 만들고 데이터를 쓰는 과정을 정리한다.

커널 모듈 준비

NBD 클라이언트 역할을 하려면 nbd 커널 모듈이 필요하다. 기본으로는 /dev/nbd0~/dev/nbd15 정도만 만들어지는데, nbds_max 파라미터로 개수를 조절할 수 있다.

$ sudo modprobe nbd nbds_max=4
$ ls /dev/nbd*
/dev/nbd0  /dev/nbd1  /dev/nbd2  /dev/nbd3

$ sudo apt install nbd-client qemu-utils

서버 쪽 — qemu-nbd로 이미지 export

정식 nbd-server 데몬을 config 파일과 함께 쓸 수도 있지만, 빠르게 테스트할 때는 QEMU에 딸려오는 qemu-nbd가 더 간단하다. 512MB짜리 raw 이미지를 하나 만들어서 export한다.

$ qemu-img create -f raw disk.img 512M
Formatting 'disk.img', fmt=raw size=536870912

$ sudo qemu-nbd --fork --persistent -f raw -p 10809 -b 127.0.0.1 disk.img
$ ss -ltnp | grep 10809
LISTEN 0  4096  127.0.0.1:10809  0.0.0.0:*  users:(("qemu-nbd",pid=50087,fd=3))

-f raw를 빼면 다음과 같은 경고와 함께 형식을 자동 추정한다.

WARNING: Image format was not specified for 'disk.img' and probing guessed raw.
         Automatically detecting the format is dangerous for raw images,
         write operations on block 0 will be restricted.

형식 자동 추정은 이미지 파일이 다른 포맷(qcow2 등)의 매직 바이트를 우연히 포함하고 있을 때 오작동할 수 있어서 QEMU가 경고를 띄우는 것이다. -f raw처럼 형식을 명시하면 이 문제 자체가 사라진다. --persistent는 클라이언트가 붙었다 끊어져도 서버 프로세스가 죽지 않고 계속 떠 있게 해주는 옵션이다.

클라이언트 쪽 — nbd-client로 연결

$ sudo nbd-client 127.0.0.1 10809 /dev/nbd0
Warning: the oldstyle protocol is no longer supported.
This method now uses the newstyle protocol with a default export
Negotiation: ..size = 512MB
Connected /dev/nbd0

$ lsblk /dev/nbd0
NAME MAJ:MIN RM  SIZE RO TYPE MOUNTPOINTS
nbd0  43:0    0  512M  0 disk

“oldstyle protocol” 경고는 실제 오류가 아니라, 최신 nbd-client가 구버전 프로토콜 협상 없이 바로 newstyle로 연결했다는 안내다. 연결되고 나면 /dev/nbd0는 로컬 디스크와 다를 게 없는 평범한 블록 디바이스로 보인다.

파일시스템 생성과 마운트

$ sudo mkfs.ext4 -q /dev/nbd0
$ sudo mkdir -p /mnt/nbd_test
$ sudo mount /dev/nbd0 /mnt/nbd_test
$ echo "hello over nbd" | sudo tee /mnt/nbd_test/hello.txt
$ df -h /mnt/nbd_test
Filesystem   Size  Used Avail Use% Mounted on
/dev/nbd0    488M   28K  452M   1% /mnt/nbd_test

네트워크 스토리지라는 걸 직접 확인하기

진짜 “네트워크” 블록 디바이스인지 확인하는 가장 확실한 방법은 연결을 완전히 끊었다가 다시 붙여서 데이터가 그대로 있는지 보는 것이다. 데이터는 클라이언트가 아니라 qemu-nbd가 들고 있는 disk.img 쪽에 있으므로, 연결을 끊어도 사라지지 않아야 한다.

$ sudo umount /mnt/nbd_test
$ sudo nbd-client -d /dev/nbd0

$ sudo nbd-client 127.0.0.1 10809 /dev/nbd0
Negotiation: ..size = 512MB
Connected /dev/nbd0

$ sudo mount /dev/nbd0 /mnt/nbd_test
$ cat /mnt/nbd_test/hello.txt
hello over nbd

연결을 끊고 다시 붙였는데도 파일이 그대로 있다. dmesg에도 마운트·언마운트·연결 해제 과정이 그대로 남는다.

$ sudo dmesg | grep -i nbd
[85731.118864] nbd0: detected capacity change from 0 to 1048576
[85741.844211] EXT4-fs (nbd0): mounted filesystem ... r/w with ordered data mode.
[85752.425420] EXT4-fs (nbd0): unmounting filesystem ...
[85752.456511] block nbd0: NBD_DISCONNECT
[85752.456866] block nbd0: Disconnected due to user request.
[85754.881740] nbd0: detected capacity change from 0 to 1048576
[85754.934586] EXT4-fs (nbd0): mounted filesystem ... r/w with ordered data mode.

주의사항

  • 연결을 정리할 때는 항상 클라이언트 쪽에서 먼저 umountnbd-client -d 순서로 끊어야 한다. 서버(qemu-nbd) 프로세스를 먼저 죽이면 마운트된 파일시스템의 I/O가 멈추거나 에러로 이어질 수 있다.
  • 기본 NBD 프로토콜에는 암호화·인증이 없다. 신뢰할 수 없는 네트워크 구간에 노출하면 안 되고, 꼭 필요하다면 TLS를 지원하는 nbd-server/qemu-nbd 옵션이나 SSH 터널·VPN으로 감싸야 한다.
  • 같은 export를 여러 클라이언트가 동시에 쓰기 모드로 마운트하면 파일시스템이 손상된다. NBD 자체는 클러스터 파일시스템이 아니므로, 다중 접속이 필요하면 GFS2/OCFS2 같은 클러스터 FS를 그 위에 올리거나 애초에 단일 클라이언트로 제한해야 한다.
  • nbds_max 기본값보다 많은 디바이스가 필요하면 modprobe nbd nbds_max=N으로 미리 늘려야 한다. 모듈이 이미 로드된 상태에서는 값을 바꾸려면 먼저 rmmod해야 한다.

마무리

NBD는 설정 몇 줄로 원격 이미지 파일을 로컬 블록 디바이스처럼 붙일 수 있다는 점에서 진입장벽이 낮다. qemu-nbd를 쓰면 별도 데몬 설정 파일 없이도 바로 테스트해볼 수 있어서, VM 이미지를 로컬에서 마운트해 내용을 확인하거나 diskless 부팅 환경을 실험해볼 때 유용하다. 다만 인증·암호화가 기본으로 빠져 있고 다중 클라이언트 쓰기를 지원하지 않는다는 제약은 분명히 인지하고 써야 한다 — 신뢰할 수 있는 네트워크에서, 단일 클라이언트로 쓰는 게 기본 전제다.

참고

답글 남기기