**$ vagrant init
$ ii Vagrantfile**
# -*- mode: ruby -*-
# vi: set ft=ruby :
vm_image = "nobreak-labs/rocky-9"
vm_subnet = "192.168.56."
Vagrant.configure("2") do |config|
config.vm.synced_folder ".", "/vagrant", disabled: true
config.vm.define "client" do |node|
node.vm.box = vm_image
node.vm.provider "virtualbox" do |vb|
vb.name = "client"
vb.cpus = 2
vb.memory = 1024
end
node.vm.network "private_network", ip: vm_subnet + "33", nic_type: "virtio"
node.vm.hostname = "client"
end
config.vm.define "server" do |node|
node.vm.box = vm_image
node.vm.provider "virtualbox" do |vb|
vb.name = "server"
vb.cpus = 2
vb.memory = 1024
end
node.vm.network "private_network", ip: vm_subnet + "44", nic_type: "virtio"
node.vm.hostname = "server"
end
end
**$ vagrant up
$ vagrant ssh client
$ vagrant ssh server**
: 분산 파일 시스템 프로토콜
: 중앙집중형 모델
: 내부망(로컬 네트워크 환경)에서 사용
내부망에서 사용하는 이유?
→ 내부망에서는 MTU 를 임의로 설정 가능MTU: 네트워크에서 한 번에 보낼 수 있는 최대 패킷 크기(바이트 단위)
내부망에서는 MTU=9000 같은 Jumbo Frame을 허용.
대량 데이터 전송 시 fragmentation 줄고, 헤더 오버헤드 감소 → 처리 효율 ↑.
내부망 전용 NIC, 스위치, 드라이버 튜닝(RDMA, offloading, interrupt moderation 등).
CPU가 패킷 처리로 낭비되는 걸 줄임.

중앙 서버에 데이터를 저장해서, 각 클라이언트는 그 데이터를 직접 저장해서 리소스를 낭비할 필요가 없음
또한 동일 데이터에 접근하므로 데이터의 일관성 유지 가능
규모가 큰 소프트웨어를 배포할 때 시스템의 부하를 감소시킬 수 있음
클라이언트가 원격 함수를 호출 (result = remote_add(3,4))
호출 요청이 RPC 런타임에 의해 메시지로 변환 (직렬화)
네트워크를 통해 서버로 전송
서버 측 RPC 런타임이 메시지를 받아 실제 함수 실행 (add(3,4))
결과를 응답 메시지로 직렬화해 클라이언트로 전송
클라이언트는 마치 로컬 함수 결과처럼 받음
👉 내부적으로는 네트워크 요청/응답이지만, 프로그래머 입장에서는 함수 호출처럼 보이는 것이 핵심.
NFS의 목적: 원격 서버의 파일을 마치 로컬 파일처럼 접근
구현 방법: 파일 작업(open, read, write, mkdir, unlink 등)을 원격 서버의 함수 호출로 변환해야 함
따라서 “파일 연산 = RPC 호출” 구조로 설계됨
클라이언트에서 read(file, offset, length) 호출한다고 가정해 볼게요.
클라이언트 애플리케이션: read() 시스템콜 호출
NFS 클라이언트 커널 모듈: 이 호출을 NFS 프로토콜로 변환
RPC 호출 생성:
READ네트워크 전송: TCP 또는 UDP를 통해 NFS 서버로 전송
NFS 서버: RPC 요청 수신 → 해당 파일시스템 함수 실행
응답 생성: 읽은 데이터 블록을 직렬화하여 RPC 응답으로 전송
클라이언트 커널: 응답을 받아 로컬 read() 호출에 데이터 반환
👉 이렇게 해서 애플리케이션은 네트워크 통신 사실을 모른 채 로컬 파일 읽듯이 동작할 수 있음.
NFS 프로토콜은 여러 가지 RPC 절차(Procedure)로 정의돼 있어요:
LOOKUP: 파일 이름 → 파일 핸들 얻기
GETATTR: 파일 속성(stat 정보) 가져오기
READ: 파일 데이터 읽기
WRITE: 파일 데이터 쓰기
CREATE / REMOVE / MKDIR / RMDIR: 파일·디렉토리 생성/삭제
READDIR: 디렉토리 엔트리 읽기
즉, 우리가 POSIX 파일 시스템에서 쓰는 거의 모든 동작이 NFS RPC 요청으로 매핑됨.
RPC 프로토콜: SunRPC (ONC RPC) 사용
데이터 포맷: XDR (서로 다른 머신 아키텍처 간 호환성 위해)
네트워크 계층: UDP (NFSv2/v3) 또는 TCP (NFSv3/v4)
버전별 차이:
- NFSv2/3: stateless, RPC 호출마다 모든 정보 포함 → 단순하지만 성능 저하 가능
- NFSv4: stateful, 세션 유지, 보안(ACL, Kerberos) 강화
NFS = “파일시스템을 RPC로 노출한 것”
클라이언트의 파일 연산을 RPC 요청으로 변환 → 서버에서 처리 → 결과 응답
LOOKUP, READ, WRITE 등 모든 파일 연산이 RPC 프로시저로 정의되어 있음
따라서 NFS의 성능, 안정성, 지연시간은 RPC와 네트워크 품질에 크게 의존
# 대부분 root 권한을 필요로 하므로
**[vagrant@client ~]$ sudo su -
[vagrant@server ~]$ sudo su -**
# ip 확인
**[root@client ~]# ip a**
...
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:5c:69:5a brd ff:ff:ff:ff:ff:ff
inet **192.168.56.33**/24 brd 192.168.56.255 scope global noprefixroute enp0s8
...
**[root@client ~]# ip a**
3: enp0s8: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
link/ether 08:00:27:be:3a:8f brd ff:ff:ff:ff:ff:ff
inet **192.168.56.44**/24 brd 192.168.56.255 scope global noprefixroute enp0s8
# 가상 머신 환경 세팅 잘되었는지 네트워크 테스트
**[root@client ~]# ping 192.168.56.44**
PING 192.168.56.44 (192.168.56.44) 56(84) bytes of data.
64 bytes from 192.168.56.44: icmp_seq=1 ttl=64 time=0.897 ms
64 bytes from 192.168.56.44: icmp_seq=2 ttl=64 time=0.967 ms
64 bytes from 192.168.56.44: icmp_seq=3 ttl=64 time=0.851 ms
64 bytes from 192.168.56.44: icmp_seq=4 ttl=64 time=1.19 ms
64 bytes from 192.168.56.44: icmp_seq=5 ttl=64 time=1.43 ms
**[root@server ~]# ping 192.168.56.33**
PING 192.168.56.33 (192.168.56.33) 56(84) bytes of data.
64 bytes from 192.168.56.33: icmp_seq=1 ttl=64 time=8.37 ms
64 bytes from 192.168.56.33: icmp_seq=2 ttl=64 time=0.965 ms
64 bytes from 192.168.56.33: icmp_seq=3 ttl=64 time=0.533 ms
# nfs 패키지 설치
**[root@server ~]# yum install nfs-utils -y**
# 공유 디렉토리 생성
# /srv : service. 시스템에서 제공하는 서비스의 데이터를 담아서 쓰라는 용도로 만들어짐
**[root@server ~]# mkdir /srv/share
[root@server ~]# ls -ld /srv/share/**
drwxr-xr-x. 2 root root 6 Sep 3 03:35 /srv/share/
# 공유 디렉토리에 파일 생성
**[root@server ~]# echo "NFS Share Test File" > /srv/share/test.txt**
# 설정 파일 작성
**[root@server ~]# vi /etc/exports**
// 어떤 클라이언트에게 어떤 디렉토리에 어떤 옵션으로 공유할 것인지
/srv/share *(rw,sync,no_root_squash)
* : 어떤 호스트가 접근 가능하게 할 것인지. : *은 모두를 가리킴. : 원래는 ip 주소를 적는게 정상(rw,sync,no_root_squash) : NFS의 서버 공유 옵션