NFS는 네트워크 상에서 다른 PC 혹은 서버의 파일 시스템을 mount 하여 공유하는것을 의미한다. 사용자는 원격 컴퓨터에 있는 파일 및 디렉토리에 액세스할 수 있도록 하는 일종의 분산 파일 시스템이다.
물론 NFS는 네트워크에 파일시스템을 유출시키므로 위험은 당연히 존재한다.
라즈베리파이4는 결국 NFS 서버, 즉 원격 컴퓨터가 된다. 라즈베리파이에 설치된 운영체제는 Raspbian OS이다.
sudo apt update
sudo apt upgrade
NFS 서버 관련 패키지를 설치한다
sudo apt install nfs-kernel-server -y
공유할 디렉토리를 생성해준다. 여기서는 /mnt
디렉토리의 하위디렉토리 /share
하나를 만들겠다.(일반적으로 여러 기타 파일 시스템을 마운트 하는곳이 /mnt
디렉토리이기 때문이다.
sudo mkdir /mnt/share
라즈베리파이는 기본적으로 vim이 설치되어있지 않다. vim을 설치해주자
sudo apt install vim
/etc/exports
파일을 vim을 통해 연다. /etc/exports
파일은 NFS 서비스를 설정할때 사용하는 파일이다. 서버가 클라이언트에 반출하는 모든 디렉토리를 표시한다.
sudo vim /etc/exports
위에서 공유하기위해 만들었던 디렉토리를 접속허용할 주소, 옵션과 함께 명시해 주어야 한다. 기본적인 포맷은 아래를 따른다
`반출할-디렉토리` `접속허용할ip 혹은 와일드카드`(`옵션`)
옵션에는 아래와 같은것들이 있다.
옵션 | 의미 |
---|---|
ro | 읽기 전용으로 지정(기본값) |
rw | 읽기 및 쓰기 가능으로 지정 |
root_squash | NFS클라이언트에서 접근하는 root 사용자를 무시하고, nfsnobody로 매핑.일반사용자의 권한은 그대로 인정된다. |
no_root_squash | NFS클라이언트에서 접근하는 root 사용자를 무시하지 않고 root로 인정 |
all_squash | root, 일반사용자를 포함하여 권한을 nobody로 매핑 |
no_subtree_check | 하위 디렉토리를 검사하지 못하도록 한다 |
secure | 포트번호가 1024 이하인 요청만 허가할때 사용한다. 기본값 |
insecure | secure의 반대이다 |
sync | 변경사항이 안정적으로 저장된 경우에만 관련 요청에 응하도록 한다. 기본값 |
async | 쓰기가 설정된 디스크 스토리지에 사용하면 유용하다.데이터 변경에 대해 비동기 처리가 가능하다 |
no_wdelay | 쓰기 지연을 적용하지 않는다. NFS는 기본적으로 성능향상을 위해 쓰기 요청을 모아서 일괄처리한다. 이를 끄는 옵션이다. |
fsid | 공유 디렉토리에 대한 고유 식별자를 설정한다.이를 통해 서버는 어떤 디렉토리가 클라이언트와 공유되어야하는지 알 수 있다.fsid=0 으로 설정하면 루트파일 시스템을 공유할 수 있다.(보안 취약점이 있으므로 신중히 고려해야한다) |
여기서는 아래와 같이 작성하였다. 접속허용 IP는 와일드 카드 *
를 사용하였는데, 모든 IP애서 접속할 수 있음을 의미한다. 필요에 따라 IP를 지정할 수 있다.
/mnt/share *(rw,sync,no_subtree_check,no_root_squash,no_wdelay,fsid=0)
변경한 NFS 설정을 적용하고 재시작해준다.
sudo exportfs -a
sudo service nfs-kernel-server restart
rpc-statd를 시작해준다. statd는 시스템 장애시, NFS에서 파일 복구를 위해 제공하는 lockd(원격데이터에 대한 잠금 요청) 프로그램을 지원하는 도구로서, 클라이언트와 서버 상태를 모니터링하는 rpc 프로그램이다.
systemctl start rpc-statd
제대로 적용이 됐는지 확인해본다. 아래 예시는 모두 Mac OS 기준이다. 포맷은 아래와 같다
sudo mount -t nfs (nfs server IP):(nfs server 공유 디렉토리) (로컬 디렉토리)
필자의 라즈베리파이 내부 IP는 172.30.1.91이다. 각자 내부 IP는 다르므로 ifconfig
를 통해 확인한다
sudo mount -t nfs 172.30.1.91:/mnt/share ~/nfs-test
그리고 b.txt라는 파일을 만들어본다.
라즈베리파이의 /mnt/share
를 보면 b.txt가 잘 생성된것을 볼 수 있다.
이제 다시 unmount를 한다. unmount가 안되는 경우, 해당 디렉토리에 접근하고 있는 프로세스가 있는지 확인해 봐야한다.
sudo diskutil unmount ~/nfs-test
위에서 만든 라즈베리파이 NFS를 통해 Kubernetes Persistent Volume으로 사용할 수 있다. 대표적으로 로컬디스크, temporary disk인 emptyDir
, hostPath
가 있다. 하지만 Kubernetes에서 Pod는 다른 호스트 머신에서 재시작되더라도 특정 Pod에 종속적인 데이터가 필요한 경우가 많다. 이 한계점을 극복하기 위해서 AWS EBS
, Azure Disk
, iSCSI
와 같은 퍼블릿 클라우드, 표준 프로토콜 기반의 네트워크 스토리지를 사용할 수 있으며, NFS
또한 네트워크 스토리지 한 종류이다.
여기서는 NFS
PV와 Pod의 연결을 해보는것이 주 목적이므로 이외 쿠버네티스 개념설명은 생략한다. Pod의 yaml은 아래와 같다.
주의할 점은 NFS를 사용하기 위해서는 Pod가 실행되는 각각의 Node에는 nfs 유틸리티가 설치되어있어야 한다
# Ubuntu
sudo apt install nfs-common -y
# CentOS
yum install nfs-utils -y
만약 유틸리티가 설치되지 않으면 아래와 같은 오류가 발생한다
kubernetes nfs ~~ you might need a /sbin/mount helper program
# nfs-test-pod.yaml
apiVersion: v1
kind: Pod
metadata:
name: nfs-test
spec:
volumes:
- name: "nfs-data"
nfs:
server: 172.30.1.91
path: "/mnt/share"
containers:
- name: api-server
image: hoplin/simple-api
resources:
requests:
cpu: "500m"
memory: "300Mi"
limits:
cpu: "800m"
memory: "600Mi"
volumeMounts:
- mountPath: "/api/nfs-mount-example"
name: "nfs-data"
livenessProbe:
httpGet:
path: /health
port: 3000
initialDelaySeconds: 5
timeoutSeconds: 1
periodSeconds: 10
failureThreshold: 3
ports:
- containerPort: 3000
name: http
protocol: TCP
spec.volumes.nfs.server
부분을 자신의 라즈베리파이 내부 IP로 바꿔준다. 이제 Pod를 실행시켜준다. 약간의 설명을 하자면, 해당 컨테이너 이미지는 필자가 예시로 만들어 놓은 이미지이며, (링크) NFS 테스트를 위해 /api/nfs-mount-example
디렉토리가 생성되어있다. /api/nfs-mount-example
디렉토리에 NFS와 연동할 것이다.
kubectl apply -f nfs-test-pod.yaml
꽤 시간이 걸리니 기다리자(라즈베리파이 성능이 그렇게 좋지 않으며, 환경에 따라 네트워크도 영향을 미친다)
Pod가 잘 생성된것을 볼 수 있다. 하지만 정말 연결이 제대로 된것인지 확인해 봐야한다. 해당 Pod의 컨테이너 터미널에 접속해본다.
kubectl exec -it nfs-test -- bash
/api/nfs-mount-example
디렉토리에 접속하면 앞서 생성한 a.txt
, b.txt
가 존재하는것을 볼 수 있다.
그리고 나서 c.txt
를 생성하고 라즈베리파이에서도 생성된것으로 보이는지 확인해본다.