Troubleshooting 2026.10.30 7 min read

NFS CSI로 두 Worker의 PVC를 연결하고 root_squash 권한 경계를 확인했다

먼저 기존 export와 사용 중인 경로를 확인했다. ESXi용 export는 유지하고 Kubernetes용 디렉터리와 export 설정을 별도로 준비했다. 이 글에서는 두 경로를 역할에 따라 ESXi 영역과 Kubernetes 영역으로 구분한다.

외부 HTTP 경로를 만든 뒤에는 Pod의 데이터를 어디에 둘지 정해야 했다. 이미 ESXi가 공유 NFS datastore를 사용하고 있었으므로, 같은 NFS 서버에서 Kubernetes용 저장 경로를 따로 마련하기로 했다. 목표는 PVC를 요청하면 전용 하위 디렉터리가 생기고, 서로 다른 Worker의 Pod가 같은 데이터를 읽을 수 있게 만드는 것이었다.

ESXi export와 Kubernetes export를 나눴다

먼저 기존 export와 사용 중인 경로를 확인했다. ESXi용 export는 유지하고 Kubernetes용 디렉터리와 export 설정을 별도로 준비했다. 이 글에서는 두 경로를 역할에 따라 ESXi 영역과 Kubernetes 영역으로 구분한다.

ESXi·Kubernetes NFS export와 NFS 서비스 상태
ESXi·Kubernetes NFS export와 NFS 서비스 상태.

Kubernetes 쪽 접근 대상은 Control Plane과 Worker 노드로 제한하고 rw, sync, no_subtree_check, root_squash 조건을 두는 방향이었다. 새 디렉터리는 당시 확인한 익명 소유자 UID/GID 65534를 기준으로 권한을 준비했다. 기존 ESXi export를 제거하거나 NFS 서비스를 재시작하는 방식으로 범위를 넓히지 않았다.

디렉터리와 export를 나눈 목적은 사용 경로와 권한을 분명히 하는 데 있었다. 같은 서버와 하부 저장소를 사용하므로 물리 장애나 I/O 경합까지 분리되는 구조는 아니었다.

CSI를 넣기 전에 노드에서 NFS를 확인했다

클러스터에 드라이버를 넣기 전 노드가 NFS를 실제로 사용할 수 있는지부터 확인했다. Ansible로 필요한 클라이언트 패키지를 준비하고 Worker에서 NFSv4.1 마운트, 파일 쓰기와 삭제, 마운트 해제까지 시험하는 흐름이었다.

CSI 구성부터 시작하면 서버의 export 문제와 노드의 기본 NFS 접근 문제, 드라이버 문제를 한꺼번에 보게 될 수 있었다. 노드에서 작은 파일 하나를 다루는 검사를 먼저 두고 다음 계층으로 넘어가려 했다.

df -hT /mnt/nfs-check

위 명령은 마운트 시험 중 파일시스템의 유형과 연결 상태를 읽는 확인 지점이었다. 실제 연결 주소와 서버 이름은 공개 글에서 생략했다. 마운트가 됐다는 사실뿐 아니라 같은 경로에 파일을 쓸 수 있는지까지 확인 대상으로 잡았다.

shared-nfs 데이터스토어의 현재 NFS 3 연결 정보
shared-nfs: NFS 3 데이터스토어, 용량 393.15GB.

PVC별 하위 디렉터리를 만들도록 구성했다

NFS CSI는 당시 안내에서 chart 4.13.4를 사용했다. 드라이버 리소스와 관련 Pod 상태를 확인하고 StorageClass를 준비하는 순서였다. 이 버전은 당시 선택값이며 현재 설치 권장 버전으로 제시한 것은 아니다.

StorageClass에는 NFS 서버와 Kubernetes 전용 share를 지정했다. PVC namespace와 이름, PV 이름을 조합한 하위 디렉터리를 사용하고, 삭제 시 데이터를 유지하는 방향으로 설정했다. 주요 의도는 아래와 같았다.

provisioner: nfs.csi.k8s.io
reclaimPolicy: Retain
volumeBindingMode: Immediate
allowVolumeExpansion: true
mountOptions:
  - nfsvers=4.1

여기서 두 가지를 구분했다. PVC에 1Gi를 요청했다고 해당 NFS 디렉터리에 같은 크기의 hard quota를 설정한 것은 아니었다. 또 Retain은 삭제 시 보존 정책이지 원본 저장소가 없어졌을 때 복구할 수 있는 백업이 아니었다. Kubernetes 리소스의 속성과 실제 저장소의 보장 범위를 같은 것으로 설명하지 않으려 했다.

NFS CSI StorageClass와 드라이버 상태
NFS CSI StorageClass와 드라이버 상태.

Writer와 Reader를 다른 Worker에 배치했다

공유 저장소 시험에는 ReadWriteMany PVC 하나와 Pod 두 개를 사용했다. Writer는 첫 번째 Worker, Reader는 두 번째 Worker에 고정했다. 같은 노드에서만 동작하는 시험이 되지 않도록 배치를 명시했다.

Writer는 공유 경로에 짧은 문자열을 쓰고 대기했다. Reader는 같은 PVC를 연결해 그 파일을 읽었다. PVC 상태와 PV, Pod의 배치 노드를 확인한 뒤 두 Pod의 Ready를 기다리고 파일 내용을 확인하는 순서였다.

완료 기준은 Reader에서 WRITTEN FROM WORKER-01이라는 문자열을 읽는 것이었다. 전체 확인을 마치면서 서로 다른 Worker가 같은 PVC의 데이터를 읽고 쓰는 경로를 확인했다. 이 시험을 동시 쓰기 정합성이나 파일 잠금, 성능 부하 시험까지 수행한 결과로 확장하지는 않았다.

애플리케이션 UID가 바뀌자 권한 문제가 다시 나타났다

처음 공유 파일 시험이 성공했다고 모든 애플리케이션이 같은 볼륨에 쓸 수 있는 것은 아니었다. 이후 실제 RCA 애플리케이션을 배포할 때 PostgreSQL의 UID 70이 root_squash 볼륨에 쓰지 못하는 문제가 나왔다.

이때 NFS 전체의 권한 조건을 바꾸는 대신 전용 DB의 실행 UID/GID를 확인된 익명 소유자 65534에 맞추는 범위로 해결했다. 기존 export, StorageClass와 PV, ESXi 경로는 유지했다. 실습에서 확인한 소유권 조건을 애플리케이션의 실행 신원과 연결해서 본 것이다.

root_squash를 끄거나 디렉터리를 모두에게 쓰기 가능하게 만드는 방향으로 일반화하지 않았다. 당시 환경에서는 누가 쓰는지와 서버에서 누구의 소유권으로 보이는지가 핵심이었다. 간단한 파일 쓰기 시험과 실제 DB의 실행 계정이 다르면 결과도 달라질 수 있었다.

이 작업으로 PVC 생성부터 노드 간 공유 읽기까지의 기본 경로를 확인했다. 다음 과제는 저장소 장애 시 영향 범위, 데이터 보존과 별도 백업을 검증하는 일이었다. 공유 디렉터리를 만들었다는 사실과 애플리케이션 데이터를 안정적으로 운영한다는 목표 사이에는 확인할 항목이 더 남아 있었다.

shared-nfs는 ESXi용 데이터스토어로 사용했다. Kubernetes NFS CSI에는 별도 export와 마운트 설정을 사용했다. 현재 Platform DB는 PostgreSQL 16.15 StatefulSet과 nfs-csi 8Gi PVC를 사용하며, PVC Bound와 PV Retain을 2026년 10월 19일 조회에서 확인했다.

nfs-csi PVC의 Bound 상태와 PV Retain 정책
nfs-csi PVC의 Bound 상태와 PV Retain 정책.

SEARCH JOURNAL

기록 검색

글 제목, 요약, 태그에서 찾습니다.

검색을 준비하고 있어요.

검색어를 입력해 주세요.

    Ctrl/⌘ K 검색 Esc 닫기 ↑ ↓ 결과 이동