LabHub
시작하기
배우기 러닝패스 코스

스토리지 실무 — RAID·스냅숏·iSCSI·fio

RAID 는 가용성이지 백업이 아니다 — 재구성하는 동안이 가장 위험하다

LabHub 에서 이어서 보기

한 줄 요약

RAID 는 디스크 한 장이 죽어도 서버가 멈추지 않게 하는 장치다. 지운 파일·틀린 변경·암호화 공격은 모든 디스크에 똑같이 복제되므로 RAID 가 막지 못한다. 그리고 죽은 디스크를 바꾸고 다시 맞추는 재구성 시간이 배열 전체에서 가장 위험한 구간이다.

왜 이게 필요했나

디스크는 소모품이다. 서버 한 대에 디스크가 여러 장이면 그중 하나가 죽는 일은 "만약" 이 아니라 "언제" 의 문제다. 디스크 하나가 죽을 때마다 운영체제를 다시 깔고 백업에서 되살리면 몇 시간씩 서비스가 멈춘다. RAID(Redundant Array of Independent Disks)는 여러 장을 하나처럼 묶어 한 장의 죽음을 흡수한다.

리눅스는 커널의 md(multiple devices) 드라이버로 소프트웨어 RAID 를 제공하고, mdadm(8) 이 배열을 만들고 관리한다. 하드웨어 RAID 카드는 같은 일을 컨트롤러가 하고 운영체제에는 디스크 한 장만 보여 준다. 그래서 카드 뒤의 디스크 상태는 대개 제조사 도구로 봐야 한다. 원리는 같으므로 이 코스는 md 로 배운다.

어떻게 동작하나

md(4) 가 설명하는 수준(level)을 표로 줄이면 이렇다.

수준 방식 견디는 고장 쓸 수 있는 용량
RAID0 줄무늬(stripe) 없음 — 한 장만 죽어도 전부 잃는다 N 장 전부
RAID1 거울(mirror) N−1 장 한 장
RAID5 분산 패리티 1개 1장 N−1 장
RAID6 패리티 2개 2장 N−2 장
RAID10 거울을 줄무늬로 거울 쌍마다 1장 절반

RAID5·6 은 용량이 싸지만 작은 쓰기가 비싸다. 한 블록을 고치려면 옛 데이터와 옛 패리티를 읽어 새 패리티를 계산하고 둘을 다시 써야 하기 때문이다. 쓰기가 많은 데이터베이스 볼륨에 RAID10 을 고르는 이유가 이것이다.

배열의 상태는 /proc/mdstat 한 줄에 다 있다. [2/2] [UU] 는 두 장 중 두 장이 살아 있다는 뜻이고, [2/1] [U_] 는 한 장이 빠진 degraded 상태다. 고장 난 장치는 이름 뒤에 (F) 가 붙는다. mdadm --detailState : 줄은 같은 사실을 clean, degraded, recovering 같은 말로 보여 준다.

디스크 교체는 네 동작이다 — --fail 로 고장을 표시하고, --remove 로 배열에서 빼고, 새 디스크를 --add 로 넣으면 커널이 recovery 를 시작해 살아 있는 쪽의 내용을 새 디스크로 복사한다. 이 복사가 끝나야 다시 clean 이다. mdadm --wait 는 그 작업이 끝날 때까지 기다린다.

재구성이 위험한 이유는 그 동안 살아 있는 한 장이 유일한 사본이기 때문이다. 재구성은 그 디스크의 모든 블록을 읽는다. 평소에 아무도 읽지 않던 구석에 읽을 수 없는 섹터가 숨어 있었다면 바로 이때 드러나고, 그 블록은 되살릴 곳이 없다. 그래서 md 는 평소에 미리 전부 읽어 보는 점검(scrub) 을 제공한다. 커널의 md 문서에 따르면 /sys/block/mdX/md/sync_actioncheck 를 쓰면 모든 사본을 읽어 비교하고, 서로 다른 블록 수를 mismatch_cnt 에 남기며, 끝나면 sync_actionidle 로, last_sync_actioncheck 로 바뀐다. 데비안 계열의 mdadm 패키지는 이 점검을 정기적으로 돌리도록 예약해 둔다.

배열은 부팅 때 다시 조립돼야 한다. mdadm 은 설정 파일의 ARRAY 줄로 어떤 UUID 의 장치들이 한 배열인지 안다. 우분투·데비안에서는 /etc/mdadm/mdadm.conf 이고, 부팅 초기에 조립되게 하려면 update-initramfs -u 로 initramfs 에도 넣는다. mdadm --detail --brief 가 그 줄을 만들어 준다. 명령을 두 번 돌려 >> 로 붙이면 같은 줄이 두 번 쌓이는데, 이 파일은 장애 때 사람이 다시 읽는 문서이기도 하므로 배열마다 한 줄만 남긴다.

현장에서 만나는 모습

가장 흔한 대형 사고는 살아 있는 디스크를 뽑는 것이다. 알림이 "디스크 하나 고장" 이라고 할 때 슬롯 번호만 믿고 뽑았다가 그게 멀쩡한 쪽이면 RAID1 이 통째로 내려간다. 교체 전에 mdadm --detail 로 고장 난 장치 이름을 보고, lsblk -o NAME,SERIAL 이나 smartctl -i 로 시리얼 번호를 확인해 물리 디스크 라벨과 맞춘다. 이 확인을 작업 계획서의 한 줄로 적어 두는 팀이 많다.

두 번째는 "RAID 라서 백업이 필요 없다" 는 믿음이다. rm -rf 는 두 디스크에서 동시에 일어나고, 잘못된 마이그레이션도 거울처럼 정확하게 복제된다. RAID 는 디스크 고장이라는 한 종류의 사고만 막는다. 되돌리기는 스냅숏과 백업의 일이고, 그것은 다음 모듈과 용량·변경 관리 코스에서 다룬다.

세 번째는 재구성이 서비스를 느리게 하는 것이다. 재구성도 디스크 I/O 이므로 업무 트래픽과 경쟁한다. md(4) 는 /proc/sys/dev/raid/speed_limit_min·speed_limit_max 로 재구성 속도의 하한과 상한을 조절하게 해 둔다. 업무 시간에는 상한을 낮추고 밤에 올리는 식으로 운영하지만, 느리게 할수록 위험한 구간이 길어진다는 대가를 치른다.

다음 실습에서 할 것

256MiB 루프 장치 셋을 만들고 둘로 RAID1 /dev/md/sto 를 세운다. ext4 로 포맷해 20MiB 짜리 파일과 그 체크섬을 남기고, mdadm.conf 에 배열을 한 줄로 등록한다. 그다음 한 장을 고장 내고 빼서 degraded 상태를 기록하고, 셋째 장으로 재구성한 뒤 체크섬으로 데이터가 무사한지 확인한다. 마지막으로 점검(check)을 돌려 mismatch_cnt 를 기록한다.