GX10에 NFS 공유폴더를 붙인 이유와 설정, 117 MB/s 벤치마크
GX10은 서버, Main PC는 작업용 클라이언트로 두고 1GbE 내부망에서만 NFSv4.1을 썼다. 방화벽은 따로 열지 않았고, 대용량 파일은 117~118 MB/s가 나왔다.
GX10을 서버로 계속 쓰다 보니, 결국 가장 먼저 귀찮아지는 건 파일 이동이었다.
로컬 모델용 데이터셋, 체크포인트, 스크립트, 로그 파일은 늘 왔다 갔다 한다. 처음에는 rsync나 scp로 충분하다고 생각했는데, 실제로는 파일 하나 옮길 때마다 터미널을 열고, 경로를 확인하고, 전송이 끝날 때까지 기다리는 과정이 은근히 번거로웠다. 내가 원한 건 파일 전송 도구가 아니라, 네트워크 위의 폴더를 그냥 로컬 폴더처럼 쓰는 방식이었다.
그래서 선택한 게 NFS다. 이 글은 GX10을 NFS 서버로 두고, Ubuntu 메인 PC에서 마운트해서 쓰는 과정을 정리한 기록이다. 설정 자체는 단순하지만, 실제로 써보면 왜 이 조합이 맞았는지 금방 체감된다.
왜 NFS였나
이 환경은 애초에 목적이 단순했다.
- 서버와 클라이언트가 모두 Linux다.
- 내부망에서만 쓴다.
- 파일을 복사하는 것보다 붙여서 쓰는 쪽이 중요하다.
- 계정과 권한도 서로 맞출 수 있다.
이 조건이면 NFS가 제일 덜 복잡하다. 혼합 OS 공유폴더를 겨냥한 다른 선택지도 있지만, 여기서는 굳이 중간 계층을 더 둘 이유가 없었다. Linux 둘만 붙는 내부망이라면 NFSv4.1이 가장 직관적이다.
특히 GX10은 서버 역할이 분명하고, Main PC는 작업용 클라이언트 역할이 분명하다. 이 둘 사이에서 필요한 건 거창한 공유 인프라가 아니라, 같은 디렉터리를 두 기기에서 같은 감각으로 다루는 것이다. NFS는 그 역할에 딱 맞았다.
환경 정리
아래 기준으로 설정했다.
| 항목 | 값 |
|---|---|
| 서버 | GX10 (gx10-e3cd, DGX OS 기반, 192.168.0.72) |
| 클라이언트 | Main PC (Ubuntu 24.04 LTS, WD_BLACK SN850X, 192.168.0.71) |
| 공유기 / 네트워크 | ipTIME BE5100M, 1Gbps 유선 LAN 4포트 (192.168.0.x) |
| 공유 폴더 | /dir/in/server |
| 마운트 경로 | /dir/in/client |
| NFS 버전 | NFSv4.1 |
NFS 서버 (GX10) 설정
-
서비스 상태 확인
GX10에서는 NFS 서버 서비스가 정상 동작 중인지 먼저 확인했다.
systemctl status nfs-server실제 상태는 아래처럼 나왔다.
● nfs-server.service - NFS server and services Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; preset: enabled) Active: active (exited) -
공유 폴더 준비
공유할 디렉터리는 홈 디렉터리 아래에 뒀다.
sudo mkdir -p /dir/in/server이렇게 해 두면 데이터가 어디에 있는지 명확하고, 홈 디렉터리 권한과 함께 관리하기도 편하다.
-
/etc/exports등록NFS에서 핵심은 이 파일이다. 어떤 경로를 누구에게 열지 여기서 정한다.
sudo nano /etc/exports내가 실제로 넣은 한 줄은 아래다.
/dir/in/server 192.168.0.71(rw,sync,no_subtree_check)이 설정은 메인 PC 한 대만 허용하는 형태다. 개인용 내부망에서는 이 정도면 충분하다.
옵션은 단순하게만 썼다.
rw: 읽기/쓰기 허용sync: 쓰기 응답을 보수적으로 처리no_subtree_check: 하위 경로 검사 생략
-
반영하고 재시작
설정 파일을 저장한 뒤에는 export를 다시 읽고, 서비스를 재시작했다.
sudo exportfs -ra sudo systemctl restart nfs-server sudo exportfs -v로컬 내부망(
192.168.0.x)에서만 사용할 계획이라 UFW 등 방화벽 설정은 별도로 하지 않았다. 공유기를 통해 외부에서 직접 접근할 수 없는 환경이라면 방화벽 없이도 충분하다.
NFS 클라이언트 (Main PC) 설정
-
NFS 클라이언트 패키지 설치
Ubuntu 쪽에서는 클라이언트 패키지만 있으면 된다.
sudo apt update sudo apt install nfs-common -
마운트 포인트 준비
GX10 공유폴더를 붙일 위치를 만든다.
sudo mkdir -p /dir/in/client -
수동 마운트
처음에는 수동으로 붙여서 잘 보이는지 확인하는 게 좋다.
sudo mount -t nfs -o nfsvers=4.1 192.168.0.72:/dir/in/server /dir/in/client마운트가 걸리면 커널은 대략 이런 식으로 잡는다.
192.168.0.72:/dir/in/server on /dir/in/client type nfs4 (rw,relatime,vers=4.1,rsize=1048576,wsize=1048576,namlen=255,hard,fatal_neterrors=none,proto=tcp,timeo=600,retrans=2,sec=sys,clientaddr=192.168.0.71,local_lock=none,addr=192.168.0.72,_netdev)여기서 눈여겨볼 부분은
vers=4.1,rsize=1048576,wsize=1048576이다. 별도 튜닝을 많이 하지 않아도 1MB 단위로 협상된다. -
/etc/fstab등록수동 마운트가 정상이라면 자동 마운트를 걸어 둔다.
sudo nano /etc/fstab실제 등록한 내용은 아래 두 줄이다.
192.168.0.72:/dir/in/server /dir/in/client nfs nfsvers=4.1,defaults,_netdev 0 0여기서는 type을
nfs로 두고, 버전은nfsvers=4.1로 고정했다. 옵션은 최소한만 남겼다.적용은 이렇게 한다.
sudo mount -a df -h | grep nfs -
읽기/쓰기 확인
마운트가 끝났으면 바로 파일을 하나 써 본다.
touch /dir/in/client/test-from-client.txt ls -l /dir/in/client서버 쪽에서도 같은 파일이 보이면 끝이다.
ls -l /dir/in/server테스트가 끝나면 지운다.
rm /dir/in/client/test-from-client.txt
속도 벤치마크
설정이 끝난 뒤 실제로 얼마나 잘 버티는지 확인했다. 테스트는 마운트된 경로 아래의 /.nfs-bench 디렉터리에서 진행했다.
벤치마크 스크립트
#!/usr/bin/env bash
set -euo pipefail
MNT='/dir/in/client'
BENCH="$MNT/.nfs-bench"
echo '== NFS mount check =='
mount | grep "$MNT" || {
echo "ERROR: $MNT is not mounted"
exit 1
}
df -h "$MNT"
mkdir -p "$BENCH"
cd "$BENCH"
echo
echo '== Cleanup =='
rm -f large_4g.bin
rm -rf small_64k_4g
sync
echo
echo '== Large file write: 4GiB x 1 =='
/usr/bin/time -p bash -c '
dd if=/dev/zero of=large_4g.bin bs=1M count=4096 conv=fdatasync status=progress
'
echo
echo '== Drop client cache =='
sync
echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null || true
echo
echo '== Large file read: 4GiB x 1 =='
/usr/bin/time -p bash -c '
dd if=large_4g.bin of=/dev/null bs=4M status=progress
'
echo
echo '== Small files write: 64KiB x 65536 = 4GiB =='
rm -rf small_64k_4g
mkdir -p small_64k_4g
sync
/usr/bin/time -p python3 - <<'PY'
from pathlib import Path
import os
base = Path('small_64k_4g')
chunk = b'\0' * (64 * 1024)
count = 65536
for i in range(count):
with open(base / f'file_{i:06d}.bin', 'wb') as f:
f.write(chunk)
os.sync()
PY
echo
echo '== Drop client cache =='
sync
echo 3 | sudo tee /proc/sys/vm/drop_caches >/dev/null || true
echo
echo '== Small files read: 64KiB x 65536 = 4GiB =='
/usr/bin/time -p python3 - <<'PY'
from pathlib import Path
base = Path('small_64k_4g')
total = 0
for p in sorted(base.iterdir()):
with open(p, 'rb') as f:
while True:
data = f.read(1024 * 1024)
if not data:
break
total += len(data)
print(f'read bytes: {total}')
PY
echo
echo '== Small files count =='
/usr/bin/time -p bash -c '
find small_64k_4g -type f | wc -l
'
echo
echo '== Small files stat =='
/usr/bin/time -p bash -c '
find small_64k_4g -type f -exec stat {} \; >/dev/null
'
echo
echo '== Small files delete =='
/usr/bin/time -p rm -rf small_64k_4g
sync
echo
echo '== Cleanup large file =='
rm -f large_4g.bin
sync
echo
echo '== Done =='
실행 로그
== Large file write: 4GiB x 1 ==
4294967296 바이트 (4.3 GB, 4.0 GiB) 복사함, 36.7965 s, 117 MB/s
real 36.80 user 0.00 sys 0.29
== Large file read: 4GiB x 1 ==
4294967296 바이트 (4.3 GB, 4.0 GiB) 복사함, 36.5069 s, 118 MB/s
real 36.51 user 0.00 sys 0.32
== Small files write: 64KiB x 65536 = 4GiB ==
real 156.20 user 0.97 sys 1.25
== Small files read: 64KiB x 65536 = 4GiB ==
read bytes: 4294967296
real 95.75 user 0.82 sys 2.63
== Small files count ==
65536
real 0.01 user 0.00 sys 0.01
== Small files stat ==
real 62.86 user 24.23 sys 24.82
== Small files delete ==
real 62.72 user 0.04 sys 0.82
결과 요약
| 작업 | 크기 | 파일 수 | 시간 | 속도 |
|---|---|---|---|---|
| 대용량 쓰기 | 4 GiB | 1개 | 36.8초 | 117 MB/s |
| 대용량 읽기 | 4 GiB | 1개 | 36.5초 | 118 MB/s |
| 작은 파일 쓰기 | 4 GiB | 65,536개 | 156초 | 26 MB/s(평균) |
| 작은 파일 읽기 | 4 GiB | 65,536개 | 95.8초 | 43 MB/s(평균) |
| 메타데이터 count | 65,536개 | 65,536개 | 0.01초 | 즉시 |
| 메타데이터 stat | 65,536개 | 65,536개 | 62.9초 | 1,042개/초 |
| 메타데이터 delete | 65,536개 | 65,536개 | 62.7초 | 1,045개/초 |
ipTIME BE5100M의 4포트 1Gbps 유선 LAN 기준으로 보면 대용량 단일 파일 속도는 꽤 잘 나온 편이다. 반대로 작은 파일과 메타데이터 작업은 파일 수만큼 비용이 붙는다. NFS가 느리다기보다, 이런 작업이 원래 네트워크 파일시스템에서 비싼 편이라고 보는 게 맞다.
실제 사용 경험
- 큰 파일을 서버-클라이언트간 옮길 때
cp나 파일 관리자 드래그 앤 드롭이 모두 자연스럽게 동작했다. - 데이터셋 폴더를 공유 경로로 직접 붙여 두니, GX10에서 복사 과정 없이 바로 읽을 수 있었다.
- 작은 파일이 많은 워크로드는 분명 느리다. 필자의 경우 GX10은 24시간 상시 운영하면서 용량이 작은 문서(마크다운 for 옵시디언 등)를 동기화 하는데 사용하는데 사용상의 불편함은 느끼기 어려운 수준이었다.
마무리
이번 셋업의 핵심은 거창한 최적화가 아니라, 역할을 분명히 나눈 데 있다. GX10은 서버, Main PC는 작업용 클라이언트. 둘 다 Linux고, 둘 사이를 내부망 NFSv4.1으로만 묶었다. 방화벽은 따로 건드리지 않았다.
이렇게 해 두니 공유폴더가 사실상 로컬 디렉터리처럼 느껴진다. 대용량 파일은 1GbE 한계까지 잘 뽑고, 작업 흐름도 단순하다. GX10을 계속 쓸 생각이라면, 이 정도의 NFS 공유폴더는 꽤 만족스러운 선택이었다.