프로젝트 소개
NFS Quota Agent는 Kubernetes의 NFS PersistentVolume에 정의된 저장공간 용량을 실제 NFS 서버 파일시스템에서도 강제하기 위한 경량 Kubernetes 에이전트입니다.
일반적인 NFS 프로비저너는 PVC/PV 객체에 용량을 기록할 수 있지만, 그 숫자가 NFS 서버의 디렉터리 사용량을 자동으로 제한하는 것은 아닙니다. NFS Quota Agent는 이 Kubernetes Storage API와 실제 Filesystem 사이의 제어 공백을 해결합니다.
에이전트는 NFS PersistentVolume을 감시하고, PV의 실제 export/subdirectory와 파일시스템 quota 메커니즘을 연결합니다. 중요한 점은 quota 명령이 NFS client가 아닌 실제 NFS server의 local filesystem에서 실행되어야 한다는 것입니다.
핵심 동작
PV 감시
에이전트는 Bound 상태의 NFS PV를 감시하며 설정된 provisioner를 기준으로 대상 PV를 필터링할 수 있습니다. Native NFS PV뿐 아니라 nfs.csi.k8s.io 기반 CSI PV도 처리합니다.
경로 매핑
CSI NFS의 share와 subdir, Native NFS의 path를 로컬 NFS export 경로로 변환해 실제 quota 대상 디렉터리를 결정합니다.
Project ID
PV 이름을 기반으로 안정적인 project ID를 생성하여 여러 PVC가 같은 NFS 서버에서 운영될 때 quota 대상을 구분합니다.
상태 추적
PV annotation을 통해 quota가 pending, applied, failed 중 어떤 상태인지 확인할 수 있어 Kubernetes 리소스 조회만으로도 적용 결과를 파악할 수 있습니다.
파일시스템 지원
| Filesystem | Mechanism | 특징 |
|---|---|---|
| XFS | xfs_quota / project quota | Kubernetes NFS 환경에서 주력 지원 |
| ext4 | setquota + project attribute | Linux project quota 기반 지원 |
| Btrfs | qgroup quota | 대상이 subvolume이어야 함 |
따라서 이 프로젝트는 단순한 Kubernetes controller라기보다 Kubernetes + Linux filesystem 경계에서 동작하는 storage enforcement agent에 가깝습니다.
Kubernetes 배포 모델
에이전트는 일반 Deployment가 아니라 NFS 서버가 위치한 노드에 실행되는 DaemonSet 모델을 사용합니다.
이 배포 방식은 호스트 파일시스템 접근이 필요하기 때문에 일반적인 cluster-wide controller보다 보안 경계가 큽니다. 따라서 nodeSelector, hostPath, hostPID 등 privileged access를 실제 NFS 서버 노드로 좁히는 것이 핵심입니다.
운영 기능
프로젝트에는 단순 quota 적용 외에도 실제 운영을 위한 선택 기능이 포함됩니다.
- Prometheus metrics / ServiceMonitor
- PrometheusRule 기반 알림
- Audit logging
- Usage history
- Orphan cleanup과 dry-run
- Namespace quota policy
- Optional Web UI
- RollingUpdate 기반 DaemonSet 배포
- Helm chart를 통한 환경별 설정
Namespace 정책을 사용할 때는 LimitRange, Namespace annotation, global default와 같은 Kubernetes 정책 모델을 활용해 quota의 기본값과 최대값을 관리할 수 있습니다.
보안과 운영상의 핵심 경계
NFS Quota Agent는 실제 파일시스템을 변경하므로 잘못된 경로 매핑이나 quota 명령은 데이터 접근성에 직접 영향을 줄 수 있습니다. 따라서 운영 시 다음을 중요하게 봅니다.
- NFS 서버 노드만 대상으로 배치
- hostPath 범위를 실제 export로 제한
- 자동 cleanup은 기본적으로 disabled / dry-run 우선
- quota 상태를 PV annotation과 metric으로 관찰
- Helm upgrade 시 DaemonSet 전환 여부와 host access 변경을 검토
시작하기
git clone https://github.com/dasomel/nfs-quota-agent.git
cd nfs-quota-agent
make buildKubernetes 환경에서는 Helm chart를 사용합니다.
kubectl label node <nfs-server-node> nfs-server=true
helm install nfs-quota-agent ./charts/nfs-quota-agent \
--namespace nfs-quota-agent \
--create-namespace상세 기술 문서
| 주제 | 문서 | 내용 |
|---|---|---|
| Overview | 에이전트 개요 | 문제 정의와 filesystem enforcement 모델 |
| Architecture | 스토리지 아키텍처 | PV → 경로 매핑 → quota 실행 구조 |
| Feature Guide | 기능 가이드 | filesystem, policy, metrics 기능 |
| Getting Started | 설치 및 설정 | Helm 및 환경 준비 |
| Features | 기능 상세 | UI, history, policy 등 확장 기능 |
| Operations | 운영 가이드 | 모니터링, cleanup, 장애 대응 |
| Web UI | 웹 UI | 저장공간 상태와 운영 화면 |
프로젝트 관계
Narwhal에서는 NFS CSI 기반 스토리지와 함께 사용할 수 있으며, Kube-Ready-Box의 XFS Project Quota 튜닝과도 직접 연결되는 스토리지 enforcement 계층입니다.
현재 상태와 검증 범위
현재 최신 릴리스는 v0.4.3이며 프로젝트 상태는 Beta입니다. XFS, ext4, Btrfs의 핵심 quota 적용 경로는 실제 Linux 커널을 사용하는 CI 시나리오에서 검증되고, 일반적인 기능 회귀는 Go 단위 테스트와 air-gapped E2E 테스트로 확인합니다. 다만 단위 테스트는 외부 quota 명령을 stub 처리하므로 실제 호스트 커널의 quota 강제를 대신 증명하지 않습니다.
파일시스템별 운영 전제도 다릅니다.
| 파일시스템 | 적용 방식 | 운영 전제 및 주의점 |
|---|---|---|
| XFS | project quota와 xfs_quota | pquota/prjquota로 마운트된 export 필요 |
| ext4 | project quota와 setquota | project,quota 기능 및 prjquota 필요; 일부 최소 커널에서는 quota_tree와 quota_v2 모듈이 추가로 필요 |
| Btrfs | qgroup quota와 btrfs | btrfs quota enable이 선행되어야 하며 quota 대상은 subvolume이어야 함 |
XFS와 ext4는 setquota/xfs_quota의 KB 단위 한계 때문에 요청 바이트를 1KiB 단위로 내림하여 실제 hard limit을 설정합니다. 따라서 PV 용량과 디스크 보고값을 비교할 때는 이 filesystem semantics를 반영해야 합니다. 또한 ext4는 CAP_SYS_RESOURCE를 가진 root writer가 hard limit을 우회할 수 있으므로, NFS export에서는 기본값인 root_squash와 비root workload 사용을 권장합니다.
운영 전 체크리스트
- NFS export가 실제로 quota를 지원하는 XFS, ext4, Btrfs 파일시스템 위에 있는지 확인합니다.
nfs-server=true라벨이 붙은 NFS 서버 노드에만 DaemonSet이 배치되는지 확인합니다.- 컨테이너의 hostPath가 export,
/dev,/etc/projects,/etc/projid등 필요한 범위로 제한되어 있는지 검토합니다. - Btrfs는 각 PV 경로가 subvolume인지, ext4는 커널 quota 모듈과
root_squash설정이 준비됐는지 확인합니다. - 처음에는 cleanup을 비활성화하거나
dryRun=true로 운영하고, metrics와 audit log를 먼저 관찰합니다.




