본문 바로가기
문서 목차
ORKESTRIX설치

NFS 스토리지

외부 또는 내장 NFS 서버를 기반으로 영구 볼륨(PV)을 동적으로 생성·관리하는 기능입니다.

QUANTUM C&S

외부 또는 내장 NFS 서버를 기반으로 영구 볼륨(PV)을 동적으로 생성 · 관리하는 기능입니다.

Ceph처럼 여러 노드에 분산 · 복제되는 스토리지가 아니라, 서버 한 대(또는 이미 운영 중인 외부 NAS)의 폴더를 네트워크로 공유해서 여러 파드가 동시에 마운트하는 방식입니다. CephFS처럼 여러 파드 동시 접근(ReadWriteMany)이 가능하지만, 복제 · 이중화가 없어 서버 한 대가 단일 장애점이 됩니다 — 이미 있는 NAS를 그대로 쓰거나, Ceph보다 가벼운 공유 스토리지가 필요할 때 적합합니다.
검증 현황: 아래 CSI 방식만 실제 서버에 설치해 검증했습니다. 서버 프로비저너 방식은 코드상 지원되는 것은 확인했으나(roles/qks-nfs-provisioner 존재), 아직 실제로 설치 · 검증하지 않았습니다.

사전 준비 — NFS 서버 (두 방식 공통)

두 방식 모두 실제 NFS 서버가 먼저 필요합니다. 이미 운영 중인 외부 NFS/NAS가 있다면 이 단계는 생략하고 바로 아래 "CSI 방식" 절의 설정에서 그 서버의 주소만 가리키면 됩니다. 없다면 노드 중 하나를 NFS 서버로 직접 구성합니다.

NFS 서버 자체(이 단계)는 iaas.yaml에 포함되어 있습니다. 다만 아래 CSI 방식(plays/qks-csi-nfs.yaml)은 어떤 번들 플레이북에도 포함되어 있지 않아 직접 실행해야만 설치됩니다.

인벤토리에 서버 노드 배정

inventory/qks/hosts.ubuntu는 Terraform이 재생성하지 않는 수동 관리 그룹입니다(Ceph의 [qks-ceph-admin] 등과 동일한 카테고리):

[qks-nfs-server]
k8s-ubuntu24-w01

Ceph mon처럼 여러 대 · 홀수 개일 필요 없이 노드 하나만 지정하면 됩니다 — NFS는 원래 단일 서버 구조입니다.

플레이북 실행

./install.sh ubuntu plays/qks-nfs-server.yaml

설치 흐름

1. nfs-kernel-server 패키지 설치
2. 공유 폴더 생성       /nfs, /nfs/k8s
3. /etc/exports 설정    "/nfs *(rw,sync,no_root_squash,fsid=0,no_subtree_check)"
4. nfs-server, rpc-statd 서비스 시작
공유 옵션의 fsid=0은 이 디렉터리(/nfs)를 NFSv4 클라이언트가 보는 가상 루트로 지정하는 표준 옵션입니다. 그래서 클라이언트가 서버:/k8s로 마운트를 요청하면 실제로는 서버의 /nfs/k8s를 가리키게 됩니다 — 아래 CSI 방식의 share: /k8s 설정이 이 원리로 동작합니다.

CSI 방식 (검증 완료)

쿠버네티스 SIG-Storage가 관리하는 정식 CSI 드라이버(csi-driver-nfs)를 사용합니다. Ceph RBD/CephFS CSI와 동일한 아키텍처(nodeplugin DaemonSet + controller Deployment)입니다.

설정값

qks_csi_nfs_server: "{{ hostvars[groups['qks-nfs-server'][0]]['private_ip'] }}"  # 서버 IP 자동 참조
qks_csi_nfs_path: /k8s                    # 마운트 경로 (fsid=0 기준 → 실제로는 /nfs/k8s)
qks_csi_nfs_storageclass_name: qks-nfs-csi
qks_csi_nfs_version: 4.13.4   # "v" 접두어 없이! (v4.10.0까지는 v가 붙지만 4.11.0부터 빠짐, 차트 저장소 기준)

플레이북 실행

./install.sh ubuntu plays/qks-csi-nfs.yaml

설치 내용

  • StorageClass qks-nfs-csi (VOLUMEBINDINGMODE: Immediate — 네트워크 공유라 Local Path처럼 파드 스케줄링을 기다릴 필요 없음)
  • kube-system 네임스페이스에 csi-nfs-controller(Deployment), csi-nfs-node(DaemonSet, 전 노드) 파드

설치 확인

kubectl get storageclass qks-nfs-csi
kubectl get pods -n kube-system | grep csi-nfs

실제 PVC 생성 + 파드 2개 동시 마운트(RWX) 테스트

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-nfs-pvc
spec:
  accessModes: ["ReadWriteMany"]
  storageClassName: qks-nfs-csi
  resources:
    requests:
      storage: 1Gi
---
apiVersion: v1
kind: Pod
metadata:
  name: test-nfs-pod-a       # 쓰기 담당
  labels: {test-nfs: "true"}
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector: {matchExpressions: [{key: test-nfs, operator: In, values: ["true"]}]}
        topologyKey: kubernetes.io/hostname   # pod-b와 반드시 다른 노드에 배치
  containers:
  - name: busybox
    image: busybox
    command: ["sh", "-c", "echo hello-nfs > /mnt/test.txt && sleep 3600"]
    volumeMounts:
    - {name: data, mountPath: /mnt}
  volumes:
  - name: data
    persistentVolumeClaim: {claimName: test-nfs-pvc}
---
apiVersion: v1
kind: Pod
metadata:
  name: test-nfs-pod-b       # 읽기 담당 (pod-a와 같은 PVC를 동시에, 다른 노드에서 마운트)
  labels: {test-nfs: "true"}
spec:
  affinity:
    podAntiAffinity:
      requiredDuringSchedulingIgnoredDuringExecution:
      - labelSelector: {matchExpressions: [{key: test-nfs, operator: In, values: ["true"]}]}
        topologyKey: kubernetes.io/hostname
  containers:
  - name: busybox
    image: busybox
    command: ["sh", "-c", "sleep 3600"]
    volumeMounts:
    - {name: data, mountPath: /mnt}
  volumes:
  - name: data
    persistentVolumeClaim: {claimName: test-nfs-pvc}
kubectl get pod test-nfs-pod-a test-nfs-pod-b -o wide   # 둘 다 Running + 서로 다른 NODE 확인
kubectl exec test-nfs-pod-b -- cat /mnt/test.txt        # pod-a가 쓴 hello-nfs가 그대로 읽혀야 함

서로 다른 노드에 있는 두 파드가 동시에 같은 볼륨을 마운트해서 한쪽이 쓴 파일을 다른 쪽이 그대로 읽으면, NFS의 핵심 기능(ReadWriteMany)이 노드 경계를 넘어 실제로 동작하는 것까지 증명된 것입니다(같은 노드에만 뜨면 우연히 로컬 캐시로 통과했을 가능성을 배제 못 하므로, 안티어피니티로 다른 노드 배치를 강제함).

확인 후 정리:

kubectl delete pod test-nfs-pod-a test-nfs-pod-b
kubectl delete pvc test-nfs-pvc

서버 프로비저너 방식 (옵션, 미검증)

nfs-subdir-external-provisioner 기반의 예전 방식입니다. CSI 표준 이전부터 쓰이던, 쿠버네티스 내장 NFS 마운트 기능을 이용하는 구현체로, 이 저장소에서는 roles/qks-nfs-provisioner로 지원됩니다. 생성되는 StorageClass 이름은 qks_nfs_provisioner_storageclass_name(기본값 qks-nfs)입니다.

./install.sh ubuntu plays/qks-nfs-provisioner.yaml
CSI 방식과 마찬가지로 qks_nfs_provisioner_enabled 변수는 iaas.yaml 번들 실행 시에만 의미가 있고, 위 플레이북을 직접 실행할 때는 값과 무관하게 항상 설치됩니다.

CSI 방식과 같은 NFS 서버(/nfs/k8s)를 절대경로로 직접 마운트합니다. 아직 실제로 설치 · 검증하지 않았습니다 — 검증 후 이 섹션에 결과를 반영할 예정입니다.

다음 단계