MeetBack 2026.08.26 6 min read

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

하드웨어 RAID5 위에 LVM과 NFS를 구성해 업로드와 백업 역할을 나눴다. 디스크 표시, UID/GID, root_squash, automount를 확인한 내용을 정리했다.

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

App 복제본들이 사용자 이미지와 첨부파일을 공유할 공간이 필요했다. MySQL 백업과 서비스 로그도 따로 모아야 했다. 로컬 볼륨만 사용하면 다른 Worker로 이동한 컨테이너가 기존 파일을 볼 수 없어 NFS를 구성했다.

NFS 서버 두 대에 서로 다른 역할을 맡겼다.

NFS #1
  └─ application images and attachments

NFS #2
  ├─ MySQL backup
  └─ service logs

두 서버는 실시간 복제 관계가 아니었다. 저장할 데이터와 접근 권한, 용량의 영향을 나눈 구성이었다.

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

lsblk에는 여러 RAID 디스크가 아닌 /dev/sda 하나만 보였다. /proc/mdstat에도 소프트웨어 RAID가 표시되지 않아 처음에는 구성을 다시 확인해야 했다.

이 장비는 하드웨어 RAID 컨트롤러가 물리 디스크를 묶어 OS에 제공했다. Ubuntu에서 /dev/sda 하나로 보이는 것이 정상 상태였다.

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

lsblk에서는 OS에 제공된 논리 디스크와 파일시스템을 확인할 수 있었다. 물리 디스크 장애와 재구축 진행 상태는 RAID 컨트롤러의 관리 화면이나 제조사 도구로 확인해야 했다.

OS filesystem과 NFS data volume을 분리했다

Ubuntu 설치 후 볼륨 그룹에 남은 공간으로 NFS 전용 논리 볼륨을 만들고 ext4로 포맷했다. UUID를 /etc/fstab에 등록해 /srv/nfs로 연결했다.

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

업로드 파일이 늘어도 OS 루트 공간까지 차지하지 않게 파일시스템을 나눴다. 논리 볼륨별로 사용량과 마운트 상태를 확인할 수 있게 했다.

Export를 목적별 directory로 나눴다

NFS #1에는 App 데이터 디렉터리를, NFS #2에는 DB 백업과 서비스 로그 디렉터리를 만들었다. export 옵션은 아래와 같이 설정했다.

rw,sync,no_subtree_check,root_squash
  • rw: 지정한 클라이언트의 읽기·쓰기 허용
  • sync: 서버가 안정적인 저장장치에 반영한 뒤 응답
  • no_subtree_check: 하위 경로 검사에 따른 이름 변경 문제와 부하 감소
  • root_squash: 클라이언트 root를 NFS 서버의 root 권한으로 처리하지 않음

접근 대상은 실제 Worker와 DB의 내부 주소로 제한했다. App 파일과 로그의 최종 UID/GID는 컨테이너 실행 계정이 정해진 뒤 맞추기로 했다.

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

Export가 rw여도 클라이언트에서 파일을 만들 때 Permission denied가 발생할 수 있었다. 마운트 성공 이후에도 아래 두 권한 조건을 확인해야 했다.

  1. 해당 클라이언트에 NFS export가 rw로 허용됐는지
  2. 디렉터리 소유자·그룹·접근 모드가 프로세스의 UID/GID와 맞는지

root_squash를 적용하면 클라이언트 root는 서버에서 익명 사용자로 취급된다. 디렉터리가 root:root 0755이면 이 사용자에게는 쓰기 권한이 없다.

DB 백업 경로에는 양쪽 서버에서 숫자 UID/GID가 같은 전용 계정을 만들고 소유자와 접근 모드를 맞췄다. chmod 777이나 no_root_squash는 필요한 범위보다 권한을 넓힐 수 있어 사용하지 않았다.

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

양쪽 계정 이름이 같아도 UID/GID가 다르면 권한 결과가 달라질 수 있었다. NFS에서는 숫자 ID까지 맞춰야 했다.

Automount가 사라진 것처럼 보였다

백업 클라이언트에 x-systemd.automount와 유휴 시간 제한을 적용했다. 일정 시간 사용하지 않으면 마운트가 해제되고 경로를 다시 사용할 때 연결되는 방식이었다.

디렉터리가 있다는 것만으로 NFS 연결을 확인할 수는 없었다. 반대로 유휴 상태에서 findmnt에 나오지 않는 것도 곧바로 장애로 판단할 수 없었다. 자동 마운트 상태와 실제 접근 결과를 함께 확인했다.

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

백업 스크립트에는 파일시스템 유형과 쓰기 가능 여부를 검사하도록 넣었다. NFS가 연결되지 않은 로컬 디렉터리에 덤프가 저장되는 것을 막기 위해서였다.

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

RAID5는 물리 디스크 한 개의 장애에 대응한다. 파일 삭제나 파일시스템 손상, 서버 전체 유실에 대비하려면 별도 백업이 필요했다. 각 구성의 역할을 나눠 정리했다.

  • RAID5: 저장장치 장애 대응
  • NFS 역할 분리: 작업과 접근 권한 분리
  • MySQL 덤프: 논리 데이터 복구
  • 외부 위치의 사본: 서버·사이트 유실 시 복구용 후속 과제

MySQL 백업은 NFS #2에 보관하고 실제 복원도 시험했다. 다른 위치의 2차 사본과 RAID 컨트롤러 지표 수집은 남은 작업이었다.

Application 배포 전 남은 작업

당시에는 App 컨테이너가 확정되기 전이라 NFS #1의 최종 실행 UID/GID와 쓰기 시험이 남아 있었다. 이미지의 실행 계정이 정해지면 Worker와 NFS 서버의 숫자 ID를 맞추고 Swarm 볼륨에서 생성·수정·삭제를 확인할 계획이었다.

이번 작업에서는 export와 라우팅, 마운트 상태를 확인한 뒤 UID/GID와 디렉터리 권한까지 점검했다. 파일시스템 연결과 실제 서비스 계정의 사용 여부를 따로 확인해야 했다.

SEARCH JOURNAL

기록 검색

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

검색을 준비하고 있어요.

검색어를 입력해 주세요.

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