MeetBack 2026.08.26 5 min read

RAID5 위에 역할별 NFS Storage를 나눈 이유

Hardware RAID5 위에 LVM과 ext4를 구성하고 애플리케이션 파일과 백업·로그용 NFS를 분리한 이유, UID/GID와 Automount 문제를 정리했다.

프로젝트 기간: 2026-08-18 ~ 2026-09-02
글 범위: Hardware RAID5·LVM·ext4 기반 역할별 NFS

MeetBack에는 사용자 이미지와 첨부파일처럼 application replica가 공유해야 하는 파일이 있다. MySQL backup과 service log를 모아 둘 공간도 필요하다. local volume만 사용하면 container task가 다른 worker로 이동했을 때 같은 파일을 볼 수 없기 때문에 외부 shared storage가 필요했다.

나는 NFS server 두 대를 역할별로 나눴다.

NFS #1
  └─ application images and attachments

NFS #2
  ├─ MySQL backup
  └─ service logs

두 server가 같은 data를 실시간 mirror하는 구조는 아니다. workload와 권한, 용량 영향을 분리한 것이다.

RAID5인데 Linux에는 disk 한 개만 보였다

처음 lsblk를 확인했을 때 여러 RAID member가 아니라 /dev/sda 하나만 표시됐다. /proc/mdstat에도 software RAID array가 없었다. RAID5 구성이 잘못된 것처럼 보일 수 있었다.

원인은 hardware RAID controller였다. 여러 physical disk를 controller가 RAID5 logical disk 하나로 묶어 OS에 제공하므로 Ubuntu에서는 /dev/sda 하나만 보이는 것이 정상이다.

Physical disks
  → Hardware RAID5 controller
  → One logical disk
  → LVM PV/VG/LV
  → ext4
  → /srv/nfs

이 구조에서 lsblk는 logical disk와 filesystem만 보여 준다. physical disk failure와 rebuild progress는 RAID controller의 관리 interface나 vendor tool에서 따로 확인해야 한다. RAID5를 쓴다고 monitoring이 자동으로 생기는 것은 아니다.

OS filesystem과 NFS data volume을 분리했다

Ubuntu 설치 뒤 volume group에는 사용하지 않은 공간이 남아 있었다. 나는 남은 extent로 NFS 전용 logical volume을 만들고 ext4로 format했다. UUID를 /etc/fstab에 등록해 /srv/nfs에 mount했다.

Volume Group
  ├─ OS Logical Volume → /
  └─ NFS Logical Volume → /srv/nfs

OS root와 NFS data를 같은 filesystem에 두면 application file이 가득 찼을 때 OS까지 쓸 수 없게 될 수 있다. logical volume을 나누면 용량과 mount 상태를 별도로 관찰할 수 있다.

Export를 목적별 directory로 나눴다

NFS #1에는 application data directory, NFS #2에는 DB backup과 service log directory를 만들었다. export option은 다음 원칙을 사용했다.

rw,sync,no_subtree_check,root_squash
  • rw: 지정된 client가 읽고 쓸 수 있다.
  • sync: server가 안정적인 storage에 반영한 뒤 응답하도록 한다.
  • no_subtree_check: subtree 검사에 따른 rename 문제와 overhead를 줄인다.
  • root_squash: client root를 NFS server root로 신뢰하지 않는다.

client 범위는 넓은 subnet 전체가 아니라 실제 worker와 DB private address를 기준으로 제한했다. application file과 log의 최종 service UID/GID는 container user가 확정된 뒤 맞추기로 했다.

rw인데도 쓰기 실패가 발생했다

NFS export에 rw가 있고 mount도 성공했지만 client에서 파일을 만들 때 Permission denied가 발생할 수 있다. 처음에는 export option 문제로 보이지만 NFS 쓰기 권한은 두 계층에서 결정된다.

  1. NFS export가 해당 client에 rw인가
  2. directory의 POSIX owner, group, mode와 process UID/GID가 맞는가

root_squash가 적용되면 client root는 server root가 아니다. directory가 root:root 0755이면 squash된 사용자는 쓸 수 없다.

DB backup 경로에는 server와 client에서 동일한 numeric UID/GID를 가진 전용 account를 만들고 directory owner와 mode를 맞췄다. chmod 777이나 no_root_squash로 우회하지 않았다. 당장 write error는 사라질 수 있지만 storage 권한 경계를 없애기 때문이다.

NFS server directory owner UID/GID
  = DB server backup process UID/GID

NFS는 username 문자열보다 숫자 UID/GID 일치가 중요하다. 양쪽에 같은 이름이 있어도 number가 다르면 예상과 다른 권한이 적용된다.

Automount가 사라진 것처럼 보였다

DB backup client에는 x-systemd.automount와 idle timeout을 사용했다. 일정 시간 접근하지 않으면 실제 NFS mount가 해제되고, path에 접근할 때 다시 mount될 수 있다.

이때 mountpoint directory가 존재한다고 remote filesystem이 mount된 것은 아니다. 반대로 idle 상태에서 findmnt에 보이지 않는다고 항상 장애인 것도 아니다.

systemctl status <mount>.automount
ls -la <mountpoint>
findmnt <mountpoint>
nfsstat -m

backup script는 directory 존재만 검사하지 않고 실제 filesystem type과 write 가능 여부를 확인한 뒤 dump를 시작하도록 했다. NFS가 mount되지 않은 상태에서 local 빈 directory에 backup을 써 버리는 상황을 막기 위해서다.

RAID5와 Backup을 같은 것으로 보지 않았다

RAID5는 한 physical disk 장애를 견디는 데 도움을 주지만 사용자가 파일을 삭제하거나 filesystem이 손상되거나 server 전체가 유실되는 상황을 복구하지 못한다. 그래서 RAID와 backup을 별개로 취급했다.

  • RAID5: storage device level availability
  • NFS role separation: workload와 permission 분리
  • MySQL dump: logical data recovery
  • 향후 off-site copy: server·site level recovery

현재 MySQL backup은 NFS #2에 보관하고 실제 restore를 시험했다. 하지만 off-site 2차 사본과 RAID controller metric은 남은 과제다.

Application 배포 전 남은 작업

application container가 아직 확정되지 않아 NFS #1의 최종 service UID/GID와 directory write test는 남겨 뒀다. image가 사용하는 user를 확인한 뒤 worker와 NFS server에 같은 numeric identity를 적용하고, Swarm volume에서 생성·수정·삭제를 검증할 예정이다.

NFS를 구축하며 가장 중요했던 것은 mount 성공과 사용 가능을 구분하는 일이었다. export, route, mount, filesystem type, UID/GID, directory mode를 모두 확인해야 실제 service가 안전하게 쓸 수 있다.