2026. 4. 20. 22:03ㆍ카테고리 없음
가이드 형태로 바로 쓸 수 있게 정리해볼게.
특히 rsize/wsize 의미랑, 리눅스 노드 직접 마운트 성능 / Pod에 PV 붙였을 때 성능을 나눠서 비교하는 형태로 구성하겠어.
좋아. 바로 문서에 넣을 수 있게 가이드 초안 형태로 정리해줄게.
핵심은 리눅스 노드 직접 마운트 성능과 Pod에서 PV로 붙였을 때 성능을 같은 기준으로 비교하는 거야.
NFS 마운트 옵션 적용 및 성능 검증 가이드
1. 목적
NFS 스토리지를 다음 마운트 옵션으로 적용한 뒤, 실제 성능을 확인한다.
성능 검증은 아래 2가지 관점으로 수행한다.
- 리눅스 노드에서 직접 마운트한 경우의 성능
- Kubernetes Pod에 PV로 연결한 경우의 성능
특히 rsize, wsize는 중요한 확인 대상이다. Linux NFS 클라이언트는 rsize/wsize를 지정하지 않으면 클라이언트와 서버가 지원하는 최대값을 협상하며, Linux 클라이언트의 최대 READ/WRITE payload는 1,048,576 bytes(1MB)이다. 실제 적용된 값은 /proc/mounts에서 확인하는 것이 맞다.
2. 마운트 옵션 설명
주요 옵션
- vers=3
NFS v3로 마운트한다. vers는 nfsvers와 동일한 의미다. - tcp
TCP 기반으로 NFS 통신을 수행한다. - hard
요청 타임아웃 시 I/O를 실패 처리하지 않고 계속 재시도한다. 데이터 무결성 측면에서 일반적으로 soft보다 안전하다. soft는 특정 상황에서 silent data corruption 위험이 있다고 man page가 경고한다. - intr
예전 호환성을 위한 옵션이며, kernel 2.6.25 이후에는 무시된다. 즉 최신 Linux에서는 실질 효과를 기대하기 어렵다. 문서에는 넣되, “호환성 목적 옵션”이라고 써두는 게 맞다. - retry=2
mount 명령 자체가 실패했을 때 재시도하는 시간 관련 옵션이다. foreground mount 기본값은 2분이다. - retrans=5
NFS 요청 재전송 횟수다. TCP에서 기본은 2회인데, 여기서는 5회로 늘린다. - timeo=600
TCP NFS에서 응답 대기 시간이며 단위는 decisecond(1/10초)다. 즉 600은 60초다. TCP 기본값도 600이다. - rsize=1048576
한 번의 NFS READ 요청에서 받을 수 있는 최대 데이터 크기다. Linux NFS client 최대값은 1MB다. - wsize=1048576
한 번의 NFS WRITE 요청에서 보낼 수 있는 최대 데이터 크기다. Linux NFS client 최대값은 1MB다. - nconnect=8
TCP 같은 connection-oriented protocol에서 클라이언트와 서버 사이에 여러 연결을 생성해 성능 향상을 노릴 수 있는 옵션이다. 최대 16까지 가능하다. 특히 NIC가 여러 개 있거나 병렬 처리량 확보가 중요할 때 도움이 될 수 있다.
3. 핵심 판단 포인트
이 가이드의 핵심은 아래다.
3-1. rsize/wsize는 꼭 확인해야 함
문서 기준으로도 중요하고, 실제 Linux NFS 클라이언트도 rsize/wsize를 크게 잡을수록 요청당 전송량이 커져 처리량 확보에 유리하다.
다만 명령에 1MB를 써도 실제 적용값은 서버와의 협상 결과로 정해지므로, 반드시 실제 mount 결과값을 확인해야 한다. /etc/mtab가 아니라 /proc/mounts를 보는 이유도 이 때문이다.
3-2. nconnect=8은 처리량 비교 항목으로 포함
여러 TCP 연결을 통해 부하를 분산할 수 있으므로, 단일 연결 대비 처리량 차이가 나는지 같이 확인할 가치가 있다. 다만 환경에 따라 차이가 없을 수도 있다.
3-3. intr은 성능 옵션으로 보지 않음
이건 최신 커널에서 무시되므로 성능 검증 항목으로 잡지 않는 게 맞다.
4. 리눅스 노드 직접 마운트 성능 검증
4.1 마운트
mount -t nfs -o rw,vers=3,tcp,hard,intr,retry=2,retrans=5,timeo=600,rsize=1048576,wsize=1048576,nconnect=8 \
hdfs.sddc.test.com:/dir /mountdir
4.2 실제 적용 옵션 확인
cat /proc/mounts | grep /mountdir
nfsstat -m
확인 포인트
- vers=3
- proto=tcp
- rsize=1048576
- wsize=1048576
- nconnect=8 반영 여부
/proc/mounts에는 실제로 협상된 rsize/wsize 값이 표시된다.
4.3 기본 성능 측정 예시
순차 쓰기
--directory=/mountdir \
--filename=fio_write_test.dat \
--rw=write \
--bs=1M \
--size=10G \
--ioengine=libaio \
--direct=1 \
--iodepth=32 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reporting
순차 읽기
--directory=/mountdir \
--filename=fio_write_test.dat \
--rw=read \
--bs=1M \
--size=10G \
--ioengine=libaio \
--direct=1 \
--iodepth=32 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reporting
랜덤 읽기/쓰기
--directory=/mountdir \
--filename=fio_randrw_test.dat \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--size=5G \
--ioengine=libaio \
--direct=1 \
--iodepth=64 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
4.4 수집할 결과
- Bandwidth (MB/s 또는 GiB/s)
- IOPS
- Latency (avg, p95, p99)
- CPU 사용률
- mount 옵션 실제 적용값
5. Kubernetes Pod에서 PV 연결 후 성능 검증
여기서는 같은 NFS 서버/같은 export 경로/가능하면 같은 mount 옵션을 사용해 Pod 내부 성능을 본다.
5.1 PV/PVC 구성 예시
PV
kind: PersistentVolume
metadata:
name: nfs-perf-pv
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteMany
persistentVolumeReclaimPolicy: Retain
mountOptions:
- vers=3
- tcp
- hard
- intr
- retry=2
- retrans=5
- timeo=600
- rsize=1048576
- wsize=1048576
- nconnect=8
nfs:
server: hdfs.sddc.test.com
path: /dir
PVC
kind: PersistentVolumeClaim
metadata:
name: nfs-perf-pvc
spec:
accessModes:
- ReadWriteMany
resources:
requests:
storage: 100Gi
volumeName: nfs-perf-pv
참고: Pod에서 사용하는 NFS mount option은 CSI/NFS provisioner/PV 방식에 따라 반영 방식이 조금 다를 수 있으므로, 노드의 실제 mount 정보나 Pod 내부 테스트 결과를 함께 확인해야 한다.
특히 nconnect는 커널/클라이언트 지원 여부 영향을 받으니 실제 노드 mount 결과 확인이 필요하다. nconnect 자체는 Linux NFS man page에 정의되어 있다.
5.2 테스트 Pod 예시
kind: Pod
metadata:
name: nfs-perf-test
spec:
containers:
- name: fio
image: alpine:3.20
command: ["/bin/sh", "-c"]
args:
- apk add --no-cache fio && sleep 36000
volumeMounts:
- name: testvol
mountPath: /data
volumes:
- name: testvol
persistentVolumeClaim:
claimName: nfs-perf-pvc
배포 후 접속:
5.3 Pod 내부 성능 측정
순차 쓰기
--directory=/data \
--filename=fio_write_test.dat \
--rw=write \
--bs=1M \
--size=10G \
--ioengine=libaio \
--direct=1 \
--iodepth=32 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reporting
순차 읽기
--directory=/data \
--filename=fio_write_test.dat \
--rw=read \
--bs=1M \
--size=10G \
--ioengine=libaio \
--direct=1 \
--iodepth=32 \
--numjobs=1 \
--runtime=60 \
--time_based \
--group_reporting
랜덤 읽기/쓰기
--directory=/data \
--filename=fio_randrw_test.dat \
--rw=randrw \
--rwmixread=70 \
--bs=4k \
--size=5G \
--ioengine=libaio \
--direct=1 \
--iodepth=64 \
--numjobs=4 \
--runtime=60 \
--time_based \
--group_reporting
6. 비교 방법
같은 조건으로 아래를 비교한다.
| 순차 쓰기 MB/s | 측정값 | 측정값 |
| 순차 읽기 MB/s | 측정값 | 측정값 |
| 랜덤 IOPS | 측정값 | 측정값 |
| 평균 지연시간 | 측정값 | 측정값 |
| p95/p99 지연시간 | 측정값 | 측정값 |
| CPU 사용률 | 측정값 | 측정값 |
해석 기준
- 노드 직접 마운트가 더 높고 Pod가 낮다면
Kubernetes 경유 오버헤드, 네트워크 네임스페이스, 스토리지 플러그인/마운트 방식 차이를 의심 - 둘 다 비슷하게 낮다면
NFS 서버 성능, 네트워크 대역폭, export 설정, 서버측 디스크 병목 가능성 우선 확인 - rsize/wsize가 1MB로 협상되지 않았다면
서버/클라이언트 조합상 실제 1MB가 적용되지 않은 것
7. 권장 검증 절차
1단계
리눅스 노드에서 직접 마운트 후 /proc/mounts, nfsstat -m로 실제 옵션 확인
2단계
노드에서 fio로 baseline 성능 측정
3단계
동일 export를 PV/PVC로 연결
4단계
Pod 내부에서 동일 fio 조건으로 측정
5단계
노드 vs Pod 결과 비교
6단계
필요 시 아래 추가 비교
- nconnect=1 vs nconnect=8
- rsize/wsize=262144 vs 1048576
- vers=3 vs vers=4.1
단, 이번 가이드의 기본안은 vers=3 기준
8. 문서에 넣을 만한 결론 문구
아래처럼 써도 돼.
NFS 마운트 성능 검증 시 rsize와 wsize는 핵심 확인 항목이다. Linux NFS 클라이언트는 서버와의 협상을 통해 최대 1MB까지 READ/WRITE payload를 사용할 수 있으므로, 실제 처리량 확보를 위해 rsize=1048576, wsize=1048576 설정 여부와 협상 결과를 반드시 확인해야 한다. 실제 적용값은 /proc/mounts 또는 nfsstat -m 기준으로 검증한다. 또한 노드 직접 마운트 성능과 Kubernetes Pod에서 PV로 연결한 성능을 각각 측정하여, 플랫폼 경유 오버헤드 유무를 함께 판단해야 한다.
9. 주의사항
- intr은 최신 Linux에서는 무시되므로, 성능 향상 목적 옵션으로 해석하면 안 된다.
- hard는 안정성 관점에서 일반적으로 유리하지만, 장애 시 I/O가 오래 대기할 수 있다.
- nconnect=8은 환경에 따라 효과 차이가 있으므로 반드시 실측으로 판단해야 한다. man page는 다중 연결이 성능 향상에 유리할 수 있다고 설명하지만, 항상 향상된다고 보장하진 않는다.
원하면 내가 이걸 바로 운영 가이드 문체로 더 다듬어서
목적 / 사전조건 / 절차 / 검증 / 결과해석 / 주의사항 형식의 완성본으로 써줄게.