archived-old-homelab
(Project) HomeLab Cluster - Base Storage Setting (4)
Index
- Introduction
- HDD & DAS
- RAID & LVM
- NFS
- Test & Benchmark
- Conclusion
Introduction
안녕하세요 Yureutae입니다. 저번 포스팅을 작성하고 오랜만에 작성하는 포스팅입니다.
Petraschu 백엔드 작업 마무리할 것도 있고, 저번 포스팅에 공을 너무 많이 들인 바람에 현타가 와서 잠깐 쉬었습니다…ㅎㅎ 물론 실제 구축 작업은 꾸준히 진행해뒀고 사진도 다 찍어뒀는데 포스팅 작성이 여간 귀찮은 일이 아니네요. 그래도 너무 밀려서 놓치는 부분 없도록 최대한 노력해보겠습니다.
오늘 작성할 부분은 스토리지입니다.
이제껏 스토리지 관련 작업을 했던 경험은
- EC2에 추가 EBS를 붙여 스토리지 증설
- 윈도우 조립식 컴퓨터에 HDD 추가해서 D 드라이브 만들기
- Ubuntu 설치 시에 LVM, 파티션 설정
- 윈도우, 우분투 듀얼 부팅 및 파티션
정도인 것 같습니다. 아마 대부분의 개발자분들의 경험이 비슷할 것이라 생각합니다. 컴퓨터 공학 커리큘럼에서 OS나 Linux 관련 과목에서는 다 해본다는 얘기도 들었던 것 같습니다. 이전의 포스팅들과 마찬가지로 단순 스토리지 증설 + 파일 마운트 방법 등은 다른 분들의 포스팅을 참고해서 빠르게 지식을 얻어가는 것이 좋습니다.
저는 사용 목적과 현재 환경, 비용, 성능(을 결국 잡진 못했지만), NFS 구축 등에 맞춰 HomeLab Cluster의 스토리지를 구성한 제 고민과 경험을 쭉 나열해보도록 하겠습니다.
HDD & DAS
HDD
Mini PC의 default SSD 용량은 128GB로 크지 않습니다.
게다가 Slot이 SATA 하나 NVME 하나 밖에 없고 방열판도 붙이기에 공간이 넉넉치 않은 편이며 붙인다고 해도 구조 상 제 성능을 내지 못할게 뻔했습니다. N100 CPU인 것도 한 몫할 것이구요.
하필이면 시기 상 스토리지들이 가격 급상승도 해버린 와중에, 가성비를 목적으로 만들고 있는 HomeLab Cluster에 SSD는 너무 아깝다고 생각이 들었습니다.


어차피 내부 네트워크 노드 간 NFS 구축해서 K8s 상 Dynamic PV Provisiong 용이거나, 저 혼자 사용할 NAS 용인데 SSD 속도 정도는 필요없다고 느껴 HDD를 필요로 하게 되었습니다.
쿠팡에서 Western Digital HDD 리퍼 제품이 너무 싸기도했구요.
WD HDD는 목적에 따라 red, green, purple, blue, yellow, black 등이 나뉘는데 돈 많으면 red가 적합할 것 같습니다. NAS용으로 나와서 장시간 가동이나 물리적인 진동, 충돌에 강하거든요
(돈이 없으면 저처럼 무난한 Blue를 쓰면 됩니다.)

문제는 mini PC를 위 이미지처럼 뚜껑을 까지 않는 이상 HDD를 SATA에 붙이기 어렵다는 거죠.
선택지는 3개로 나뉩니다.
- 뚜껑까고 SATA랑 HDD 연결
- 외장 HDD (인클로져나 실제 외장용 HDD)를 USB 3.0 방식으로 연결
- 내장 HDD를 USB 3.0 방식으로 연결 가능하게 만들기
저는 비용적인 측면과 사후 유지보수 등을 고려해서 3번을 택했습니다.
이왕 3번을 하는 김에 ‘한번에 묶어서 연결할 수 없나? USB 3.0 포트 아까운데’라는 생각이 들어서 방법을 갈구해봤습니다.

DAS (Direct Attached Storage)
마구마구 구글링을 해본 결과 Direct Attached Storage라는 것이 있었습니다. HDD를 저 통안에 넣고 USB 3.0, C type으로 PC와 연결하는 것만으로 ‘직접 연결’이 되는 것이죠. 대개 USB 3.1까지 지원이 가능합니다.
RAID를 자체 지원도 해서, 기존 HDD 1대 대비 대역폭을 늘리거나 복구용 예비 디스크를 구성할 수 있습니다.

vs Docking Station ?
비슷한 목적의 Docking Station이 있습니다. 최근 범죄도시 4에서 내장 HDD를 외부 장치에 넣고 빼는 장면이 있었는데, 그렇게 단순히 USB 연결만 목적으로 하는 장치가 Docking Station입니다.
실제 벤치마크 결과 등이 부족하지만, 각종 포럼에서 나오는 말로는 도킹스테이션은 안정성이 상당히 부족하다고 합니다. 목적 자체가 DAS에 비해서 HDD의 휴대성에 집중하기 때문에, 진동 발생 정도나 SATA 커넥션 불량 발생 확률이 높아서 HDD에 데미지를 쉽게 주나 봅니다.
DAS는 환경에 고정하려는 목적이 커서 상대적으로 안정성이 크다고 합니다.
(직접 비교는 추가로 돈이 들어서 각종 후기들로만…)
DAS도 가격대가 있지만 RAID 자체 지원 및 인클로져 대비 상대적인 안정성이 높아보여 가장 저렴한 것으로 구입했습니다. N사 제품인데 후기는 사람마다 갈리는 것 같은데, 설명서를 제대로 읽고 해보면 문제 없겠다 싶었습니다. (반품 할인가 60000원이여서 ㅋㅋ)

Attached
배송온 것 확인해보니 2015년에 만들어진 HDD들이네요. 싼마이에 만족하겠습니다.
(알리 할인 시즌에 교체해야겠네요 ㅋㅋ)

DAS에 두 개의 HDD를 집어넣고, 집에 짱박아둔 레노버 노트북(Ubuntu Desktop)으로 확인해봤습니다. DAS 자체가 Windows용으로 나왔고 한참 오래전에 출시된 제품이라 뭔가 초기 세팅이 느릿느릿한 것 같습니다. 인식 안되는 줄 알고 식겁했어요.
GSmartControl (리눅스 계의 간단한 Crystal Diskinfo? 정도로 생각하면 됩니다) 돌려보니까 하나는 땡잡은 것 같고 하나는 좀 구르다 온 것 같습니다 ㅋㅋ Power Cycle이 1500정도 돌았더라구요. 뭐 18000원에 랜덤 뽑기한거죠. 그래도 깨끗합니다. 배드섹터는 없습니다.


GSmartControl로 확인.
RAID & LVM
이제 물리적인 디스크가 BIOS 단에서 인식되는 것을 확인했으니 Ubuntu OS에서 사용이 가능하도록 작업해보겠습니다.
Partition은 해당 포스트에서는 이미 RAID로 묶인 상태로 Ubuntu에 연결했으므로 필요가 없어 진행하지 않았으며 fdisk나 parted 관련은 타 포스팅을 참고하시면 될 것 같습니다.
RAID
저도 이번에 Storage 세팅하면서 처음 알게 된 개념입니다. 단순 파티션이나 LVM 등이야 OS Setting 하거나 필요할 때 작업해서 접해봤는데 RAID는 DAS를 사면서 처음 알게되었습니다.
RAID는 Redundant Array of Independent Disk의 약자입니다. 간단하게 Storage 여러 개를 묶어서 어떤 효과를 얻기위한 방법인거죠.
저는 2 Bay DAS에 RAID 내장 컨트롤러(펌웨어 기반)가 있어, 가장 기본이 되는 RAID 0, 1만 알아보았습니다. 이외의 RAID는 대부분 0과 1을 섞어 만든 방법이므로 0와 1만 이해하고 필요에 따라 선택하면 됩니다. 0, 1 이외에는 3개 이상의 HDD가 필요하기도 하구요.
RAID 0

다수의 디스크에 대해서 데이터를 분할하여 번갈아가며 저장하는 방법입니다. 디스크들을 동시에 사용하므로
이론적으로는 성능이 n배가 됩니다. 물론 여기서 하나라도 장애가 나면 다 같이 망가지게 됩니다.저는 RAID 0를 선택했습니다. 어차피 리퍼 HDD를 구매했고, SATA 다이렉트 연결이 아니라 원래 스펙보다 열화되는 것도 고려했을 때 장애 발생 가능성을 감수할 수 있다고 생각했습니다.
(후술하겠지만 성능은 크게 상승하진 않았다)
RAID 1

디스크를 그대로 복제하는 방법입니다. 위의 이미지처럼 0에 기록하는 데이터가 1에도 그대로 입력되는 것이죠. 당연히 장애가 발생한 경우, 장애가 발생하지 않은 복제 디스크를 가져와 메인으로 사용할 수 있습니다.
저는 2 Bay이기 때문에 하나의 디스크 용량도 놓치고 싶지 않아 RAID 1은 고려하지 않았습니다. 4 Bay였다면 고려했을 것 같네요.
RAID 세팅
Ubuntu OS 내에서 RAID를 구성할 수 있습니다. 이 방식을 소프트웨어 RAID라고 합니다.
파티션 후 mdadm command로 구축 자체가 어렵진 않습니다.
하지만 저는 DAS를 구입한 김에 뽕을 뽑아야겠어서(?) DAS 내 내장 컨트롤러를 사용해서 딸깍이는 것으로 RAID 0 구성을 끝내고 곧바로 Ubuntu OS에서 인식시켰습니다.
(해당 DAS에서는 원래 공식적으로 Ubuntu 등의 Linux 계열을 지원하지 않습니다만 다행히 성공)



LVM (Logical Volume Manager)
첫 번째 포스팅에서 부팅 디스크 설정했던 부분입니다.
AWS 등의 클라우드 서비스에서는 EBS 등의 볼륨을 원하는 용량, 원하는 스펙 등으로 필요한 만큼 조절해서 할당할 수 있고, 필요하다면 추가로 EBS를 붙이면 되니 LVM을 크게 신경 안썼던 것 같습니다. 얼마든지 자유롭게 저렴한 가격에 가져다 붙일 수 있으니까요.
하지만 지금은 스토리지의 용량도, 갯수도 한정이 될 수 밖에 없습니다. 그렇기 때문에 한정된 용량, 갯수 안에서 한번에 유동적으로 분할, 할당, 확장을 할 수 있는 방법이 필요합니다. 이걸 가능하게 하는 방법이 LVM입니다.
이미지 그대로 Physical Volume들을 모아서 Volume Group을 생성하고, Volume Group을 논리적으로 나눠 Logical Volume으로 만든다고 생각하시면 됩니다. 최종적으로 Logical Volume을 파일 마운트하면 끝입니다.
말 그대로 Logical이기 때문에 추후 필요한만큼 VG로부터 용량을 꺼내고 넣고하면 됩니다.
Hands-On
위에서 인식 시킨 RAID0 스토리지를 LVM으로 만들어보겠습니다. 위 그림과 다르게 저는 PV 하나만 VG로 쓴다고 보시면 됩니다.

PV까지는 DAS에서 알아서 해줬고 인식도 해줬으니 남은 단계는 VG와 LV 생성 정도가 남았습니다.
먼저
vgcreate 커맨드로 Volume Group을 생성해줍시다. 저는 /dev/sdb 1개를 대상으로 das_vg 라는 VG를 생성했습니다.
그리고 600GB만 떼서 LV 하나를 만들어 볼게요.
lvcreate 커맨드로 600GB 용량의 nfs_lv라는 LV를 생성했습니다.
lsblk 커맨드로 확인해보니 lvm이 잘 생성된 것을 확인할 수 있습니다.
1TB + 1TB == 1.82TB??
저도 이 부분을 의아하게 생각했었는데요. 용량 단위를 1000으로 잡냐 1024로 잡냐의 차이로 2TB로 계산이 될 수 있고, 1.82TB로 계산이 될 수 있습니다.
십진법 기반 단위(si)를 이진법 기반 단위(iec)로 나누면 아래처럼 얼추 1.82가 나오게 됩니다.
2,000,000,000,000 byte ÷ 1,099,511,627,776 byte ≈ 1.82TiB
이제 Ubuntu 디렉토리에 만들어진 LV를 마운트해야합니다.
OS Setting 때처럼 파일 시스템을 Volume에 만들어줘야 마운트가 가능합니다.
먼저
mkfs.ext4 커맨드로 파일 시스템을 생성해줍니다.(호환성 및 안정성으로 ext4가 리눅스에서 default로 사용이 됩니다. 사실 미친듯이 큰 용량의 스토리지에서 대용량 고성능 I/O가 필요한 것 아니라면 XFS를 쓸 일도 없는 것 같습니다. 선택지는 하나라는 거죠.)

이제
sudo mount [목표 Volume] [목표 마운트 디렉토리] 커맨드로 파일시스템을 마운트해주면 됩니다.
대개는 /mnt 디렉토리 (mount 디렉토리) 내에서 처리해주는 것이 일반적입니다. (문제 발생 시에 디버깅이 쉬우니까)
그런데 뭐가 이상합니다. 아무것도 안했는데 이미 30GB(약 5%)를 쓰고 있어요. 또 뭔가 잘못했나 한참 구글링해봅니다.
한참 유튜브를 뒤적이다가 SSD Benchmark 영상을 봤는데, 용량을 다 안채우고 어느정도 남기더라구요? 뭔가 남기는 이유가 있겠지하고 찾아보니, default로 5%를 항상 예약공간으로 둔다고 합니다.
예약공간의 용도는
- 가득 찬 경우, Root 관리자가 시스템 작업이 가능하도록 할당
- 시스템 복구가 가능한 최소한의 공간
- 일정 공간을 제한함으로써 디스크 조각화 방지 → 성능 향상
이라고 합니다.

음… 5%는 너무 많은 걸요? 3% 정도로 줄여봅시다.
tune2fs 커맨드 옵션을 뒤져보니 m으로 줄일 수 있다고 합니다.
이제 다 구성했으니 마지막으로
/etc/fstab 을 편집해줍시다. 매번 킬 때마다 파일마운트를 직접해주기 귀찮잖아요? fstab에 적힌대로 파일시스템의 UUID를 뽑아내서 마운트 경로와 함께 기입해주면 됩니다.
옵션은 0 2 (백업 x, root fs 이후 검사)를 할당해줍시다.
이제 재부팅을 하면 이후에도 문제없이 파일시스템 마운트가 진행됩니다.
NFS (Network File System)
마지막으로 NFS를 구성해봅시다.
아래 이미지와 같이 master node에 연결된 DAS 스토리지를 모든 Worker Node에서 내부 네트워크(라우터 안)를 통해 같이 사용하게 하고 싶습니다.
뭐 남아도는 스토리지를 효율적으로 사용하고 싶은 것도 있고, 말씀드렸던 것처럼 K8s 상 Dynamic PV Provisioning이 목적이기도 합니다.

DAS가 NAS처럼 컴퓨팅 프로세서가 들어간 것도, 네트워크랑 연결된 것도 아니니 Master에서 처리해줘야합니다. 제가 원하는 건, 아래 제 맥북-Google Drive 간의 마운트처럼
Master Node의 /mnt/sdb1/yureutae_nfs와 Worker Node들의 /mnt/yureutae_nfs 간 마운트입니다.
이 과정에서 Network File System이라는 것이 사용됩니다. Remote의 파일 시스템을 마치 로컬에 있는 것처럼 사용하는 것이죠. 뭔가 개념 자체가
RPC(Remote Procedure Call)과 유사해서 찾아보니 RPC 매커니즘을 사용하는 것이 맞다고 합니다.뭐 RPC를 건들이는 것은 아니니 후딱 NFS를 구성해보겠습니다. 저는
nfs-kernel-server 라는 비교적 구성이 쉬운 패키지를 사용했습니다.NFS - Host Setting
Master Node가 Host 역할을 맡기 때문에 Worker들과 별도로 구성을 진행해줍니다.
# 1. 패키지 설치
sudo apt update
sudo apt install nfs-kernel-server
sudo apt install nfs-common
# 2. 디렉토리 세팅
sudo mkdir -p [공유 대상 지정 스토리지 디렉토리 주소]
sudo chmod [옵션] [공유 대상 지정 스토리지 디렉토리 주소]
# 3. nfs host 용 config 구성
sudo vim /etc/exports
# 아래를 추가
## [공유 대상 지정 스토리지 디렉토리 주소] [허용 ip 대역, ip 군](rw,sync,no_subtree_check,no_root_squash,no_all_squash,insecure)
sudo exportfs -a
sudo systemctl restart nfs-kernel-server
# 선택 (귀찮다)
sudo ufw allow from (ip 대역) to any port nfs
sudo ufw enable핵심적인 3번만 보겠습니다.
Host에서 마운트 목표인 디렉토리를 명시해줍니다. 이후 허용 ip 대역을 적어줍니다. CIDR 방식으로 작성해줘도 됩니다. 저는 맥북의 VPN Meshnet ip도 할당해주었습니다.
옵션은 대충 본인의 목적, 환경에 맞게 잘 찾아서 넣어주면 됩니다. 저는 read, write랑 sync, insecure 정도가 중요했던 것 같습니다. 다른 환경에서도 Google Drive처럼 편하게 마운트해서 쓰는게 목적이었거든요.

이후엔 exportfs로 적용해주고 nfs-kernel-server 서비스를 재시작해주면 됩니다. 따로 daemon으로 등록안해줘도 SSH처럼 항상 활성화됩니다.
NFS - Client Setting
이제 Client 역할인 Worker Node에서 Host인 Master Node의 nfs-kernel-server와 연결해서 마운트를 진행하면됩니다.
# 1. 패키지 설치
sudo apt-get update
sudo apt-get install nfs-common
sudo mkdir [마운트할 디렉토리]
# 2. nfs 서버 접근가능 확인 및 마운트
sudo showmount -e [nfs 서버 주소]
sudo mount -t nfs [nfs 서버 주소]:[nfs 서버 내 지정한 스토리지 디렉토리 주소] [클라이언트 내 마운트할 디렉토리]
# 3. 테스트
## 클라이언트에서 만들고 nfs에서 확인
vim [마운트한 디렉토리]/test_mount
# 4. daemon으로 활성화
sudo systemctl enable nfs-common
sudo systemctl is-enabled nfs-common
## (nfs-common 자꾸 다운되면 sudo rm /lib/systemd/system/nfs-common.service 후 restart하고 다시 enable)
# 5. fstab에 추가. 30분동안 마스터와 연결 시도하도록 옵션 설정
# mount nfs-kernel-server
192.168.1.101:/mnt/sdb2/nfs_dir /mnt/nfs_client_dir nfs4 defaults,soft,timeo=600,retrans=30 0 0
# 추가 (필요시)
# unmount 테스트 (unmount 안하고 제거시 sync 프로세스는 좀비로 잔재할 가능성 높음)
sudo umount [마운트한 디렉토리]마찬가지로 핵심적인 부분만 봅시다.
showmount -e 커맨드로 master node의 ip 주소를 던져서 가용가능한 파일시스템을 확인합니다.
위에서 구성한 exports가 바로 보이네요.
이제 mount 해주면 아래처럼 nfs4 파일시스템 포맷으로 잘 나옵니다.
파일시스템 이름은 마치 URL 주소처럼 작성됩니다.
(크롬 브라우져에서 로컬 디렉토리 접근하는 것처럼. 실제로 크롬에서 vnc나 nfs 연결 매개체 역할을 하긴 함)

마지막으로 이 친구도 파일시스템 마운트이긴 하기 때문에 연결이 언제든 활성화될 수 있도록 만들어봅시다.
우선 nfs-common 서비스를 리눅스에서 daemon 활성화 해줍니다.

이러면 daemon으로 활성화는 되지만, host의 nfs-kernel-server에 의존하기 때문에 Client의 daemon은 중요한 문제가 아닙니다. host에서 장애나면 Client는 다시 마운트를 요청하지 않더라구요. 대개는 재부팅으로 되는데 가끔 master node와 worker node들간 부팅 속도가 차이나게 되면 오류가 발생합니다.
그래서 파일마운트 fstab 작성 김에 옵션을 몇개 같이 넣어줬습니다.

이렇게 하면 부팅 후, (600/10)초 간격으로 총 30번 master node에 nfs mount를 요청하게 됩니다.
즉 30분 동안에 master랑 worker간 부팅 속도 차이 걱정할 필요없이 알아서 nfs mount가 된다는 겁니다.
Test & Benchmark
뭐 용량 정상 인식됐고 사용 자체는 문제가 없습니다.
특히 NFS는 관리자 입장에서 활용을 극대화하고 있어요. 온갖 config, keyfile 다 박아넣고 언제든 빼와서 손쉽게 사용하고있습니다.
아래 이미지처럼 맥북도 유닉스 운영체제라 Ubuntu OS와 손쉽게 마운트가 가능하구요.

문제는 RAID0의 성능입니다.
github에 Crystal Diskinfo를 거진 래핑한 느낌의 KDiskMark라는 것이 있어 벤치마킹 테스트를 진행해보고 GUI로 확인했습니다.
Read, Write 평균 170mb/s 정도 나오네요….이론상으론 300mb/s 언저리 한 270mb/s 정도로 생각했는데 말이쥬…

그래서 원인을 몇가지 추정해봤는데,
- HDD 랜덤 뽑기 실패
- SATA가 아닌 DAS - USB 3.0으로 인한 열화
- N100 I/O 성능
- DAS에 있는 RAID 구성 컨트롤러가 구식
- DAS가 윈도우 포맷으로 default 설정되는데, 어거지로 또 밀고 ext4로 만들어놔서
등등인 것 같습니다.
제가 생각하기엔 1, 4, 5인 건 같아요.
우선 우분투 내부 디스크 벤치마크 툴로 한번 더 돌려보니까 밑에 꼬라지가 나옵니다.

기가막힌 그래프네요. 앞서 디스크 정보 뜯어봤을 때도 하나는 구르고 온 것 같아서 짐작했는데, 처참합니다. 뭐 둘다 2015년 정도에 나온 디스크니까 그것도 고려해야겠죠.

또 DAS도 오래된게 한 몫합니다. 사이트도 오래됐더라구요.

무작정 exFAT으로 자꾸 포맷팅 때려서 내부에서 한번더 파일시스템 포맷을 거쳐야한 것도 있고 내장 컨트롤러 내 펌웨어가 구식이라 그럴 수도 있을 것 같습니다.
사실 요즘 그냥 OS 단에서 소프트웨어 RAID하는게 좀 더 좋다고는 하더라구요.
Conclusion
오늘은 HomeLab Cluster에서 공용으로 사용될 스토리지를 세팅했습니다.
유의미한 성능향상은 없었지만 이전 포스팅들과 마찬가지로, 이론과 실습을 탄탄히 한 것 같습니다.
특히 이번엔 까딱 잘못하면 배드섹터가 날 수도 있는 HDD에 구식 DAS를 세팅했기 때문에, 오히려 공부를 많이해서 대응 불가능한 상황 발생을 방지한 것 같습니다.
(사실 한번 DAS 장애가 있었는데 그 때 성능이 10% 토막난 것 같습니다. 그래도 고장은 안났으니 뭐…)
RAID나 LVM 등 요새 클라우드 때문에 잘 사용하지 않는 것들을 공부하고 사용해보았으며, 간단한 벤치마크 등을 진행해서 꼼꼼히 확인해보았습니다. 속도 열화 원인을 찾기 위해 추가 공부를 한 과정도 의미가 있는 것 같습니다.
NFS는 예전에 세팅을 해보았지만, 이번에는 fstab, exports, systemctl service 상에 입력되는 옵션들을 하나하나 뜯어보아서 보다 능숙해진 것 같습니다. 예전엔 좀 무지성으로 옵션 때려박고 안되면 그때서야 원인찾고 반복했던 것 같네요.
다음은 드디어 Kubernetes를 구성합니다. 이미 구성 작업은 완료했는데 커스텀 및 트러블 슈팅 과정이 여간 까다로운게 아니네요. 포스팅도 써야하니까 기존에 미흡한 지식도 최대한 다 찾아서 이해하려고 노력 중입니다. 완전무결한 시스템을 만드는 건 역시 까다로운 것 같습니다.
다음 포스팅에서 뵙겠습니다!



