리눅스 커널 dm-vdo 메타데이터 오버헤드 분석: 블록 디바이스 크기별 비교

dm-vdo를 도입할 때 흔히 하는 실수가 압축률과 중복제거율만 보고 “물리 디스크의 몇 배를 담을 수 있는가”로 용량 산정을 끝내는 것이다. 하지만 VDO는 논리-물리 블록 매핑(block map), 슬랩별 참조 카운터, 복구 저널, 그리고 중복 판별을 위한 UDS 인덱스까지 자체 메타데이터를 물리 볼륨 안에 함께 저장한다. 이 메타데이터는 고정 크기가 아니라 물리/논리 볼륨 크기에 비례해서 커지기 때문에, 볼륨을 100GB로 만들 때와 100TB로 만들 때 오버헤드의 절대량과 구성 비율이 상당히 달라진다. 이 글에서는 dm-vdo의 메타데이터 구성 요소별 공식을 정리하고, 볼륨 크기에 따라 오버헤드가 어떻게 달라지는지 실제 수치로 비교한다.

dm-vdo 메타데이터 구성 요소

VDO 볼륨 내부의 메타데이터는 크게 세 갈래로 나뉜다.

block map은 논리 블록 주소(LBA)를 물리 블록 주소로 변환하는 매핑 테이블이다. 엔트리 하나가 5바이트(물리 블록 번호 36비트 + 매핑 상태 4비트)이며, 4KB 블록 하나에 812개의 매핑 엔트리를 담는 라딕스 트리 구조로 60개의 논리 존(zone)에 나뉘어 관리된다.

슬랩 depot(slab depot)은 물리 공간을 슬랩 단위로 나눠 관리하는데, 슬랩마다 4KB 데이터 블록당 1바이트의 참조 카운터와 참조 갱신 내역을 담는 저널을 따로 갖는다. 여기에 슬랩별 사용량·정합성 상태를 요약하는 slab summary가 더해진다.

복구 저널(recovery journal)은 쓰기 연산의 논리 주소와 이전/이후 물리 매핑을 기록해 두었다가 비정상 종료 후 재시작 시 일관성을 복구하는 데 쓰인다.

UDS 인덱스는 앞의 셋과 성격이 다르다. block map·slab depot·recovery journal은 물리/논리 볼륨 크기에 비례해 자동으로 커지는 반면, UDS 인덱스는 관리자가 별도로 할당하는 RAM 양에 따라 디스크 사용량과 커버할 수 있는 “중복제거 윈도우” 크기가 결정된다.

메타데이터 크기 공식

커널 문서와 lvmvdo(7) 매뉴얼이 제시하는 공식은 다음과 같다.

  • block map + slab depot 메타데이터: 물리 스토리지 4GiB당 약 1MiB, 여기에 슬랩 1개당 1MiB 추가
  • recovery journal 관련 메타데이터: 논리 스토리지 1GiB당 약 1.25MiB, 슬랩 단위로 올림
  • UDS dense 인덱스: RAM 1GiB당 디스크 17GiB 사용, 1TiB 중복제거 윈도우 커버
  • UDS sparse 인덱스: RAM 1GiB당 디스크 170GiB 사용, 10TiB 중복제거 윈도우 커버

여기서 흥미로운 점은 dense와 sparse의 “윈도우 1TiB당 디스크 사용량”을 계산해 보면 둘 다 17GiB로 동일하다는 것이다. dense는 RAM 1GiB로 1TiB를, sparse는 RAM 0.1GiB로 1TiB를 커버하지만 디스크에 쓰는 인덱스 양은 두 방식 모두 윈도우 크기에 비례해 같다. 즉 sparse 인덱스는 디스크 비용을 줄이는 옵션이 아니라 같은 디스크 비용으로 훨씬 넓은 윈도우를 RAM을 적게 쓰면서 커버하되, 블록 단위 판별 정밀도(따라서 중복제거율)를 낮추는 옵션이다.

슬랩 크기와 물리 볼륨 상한

슬랩 크기는 128MiB의 2의 거듭제곱 배수 중에서 최대 32GiB까지 고를 수 있고 기본값은 2GiB다. 슬랩은 볼륨당 최대 8192개까지만 만들 수 있기 때문에, 기본 2GiB 슬랩을 쓰면 물리 볼륨 최대 크기는 16TiB로 제한된다. 그 이상으로 볼륨을 만들려면 슬랩 크기를 32GiB로 올려야 하며, 이 경우 최대 256TiB까지 지원한다. 슬랩 크기는 성능에는 영향을 주지 않고 순전히 메타데이터 관리 단위와 최대 볼륨 크기에만 관여한다.

볼륨 크기별 오버헤드 비교

아래 표는 물리 볼륨과 논리 볼륨을 1:1(씬 프로비저닝 없이)로 만들고, dense 인덱스를 물리 볼륨 전체를 커버할 만큼(1TiB당 RAM 1GiB) 할당했다고 가정했을 때의 계산 결과다. 16TiB 이하는 2GiB 슬랩, 그 초과는 32GiB 슬랩 기준이다.

물리 볼륨 크기슬랩 크기 / 개수block map + 저널 메타데이터dense 인덱스(전체 윈도우)총 오버헤드오버헤드 비율
1 TiB2 GiB / 512개약 2.75 GiB17 GiB약 19.75 GiB약 1.93%
10 TiB2 GiB / 5,120개약 21.5 GiB170 GiB약 191.5 GiB약 1.87%
16 TiB2 GiB / 8,192개(상한)약 32 GiB272 GiB약 304 GiB약 1.86%
50 TiB32 GiB / 1,600개약 78.1 GiB850 GiB약 928 GiB약 1.81%
100 TiB32 GiB / 3,200개약 156.1 GiB1.7 TiB약 1.81 TiB약 1.81%
256 TiB32 GiB / 8,192개(상한)약 392 GiB4.25 TiB약 4.63 TiB약 1.81%

두 가지가 눈에 띈다. 첫째, 총 오버헤드 비율은 볼륨이 커져도 1.8~1.9% 선에서 거의 수렴한다. block map·저널 메타데이터가 물리/논리 크기에 정확히 비례해서 커지고, 슬랩 개수 증가에 따른 고정 오버헤드(슬랩당 1MiB)도 상수 배로 늘어날 뿐이라 비율 자체는 크게 변하지 않는다. 둘째, 전체 오버헤드에서 UDS 인덱스가 차지하는 비중이 85~90%에 달한다. block map·slab depot·recovery journal은 상대적으로 미미하고, 실제 용량 산정에서 신경 써야 할 대상은 사실상 인덱스 크기다.

단, 이 표는 인덱스가 물리 볼륨 전체를 “중복제거 윈도우”로 커버하도록 넉넉히 잡은 경우다. 실무에서는 이렇게까지 크게 잡지 않고 예상되는 유니크 데이터 양에 맞춰 인덱스 메모리를 훨씬 작게(예: 0.25GiB, 1GiB 단위) 설정하는 경우가 많으며, 그럴 경우 총 오버헤드와 비율은 표의 값보다 크게 낮아진다. 또한 씬 프로비저닝으로 논리 크기를 물리 크기보다 크게 잡으면 두 번째 메타데이터(저널 관련) 항목이 논리 크기 기준으로 늘어나므로 별도로 재계산해야 한다.

실제 오버헤드 확인하기

계산값과 실제 값을 맞춰보려면 vdostatslvs로 직접 조회하면 된다.

# 사람이 읽기 쉬운 형태로 사용량/절감률 확인
sudo vdostats --human-readable

# verbose 모드: 메타데이터가 차지하는 물리 블록 수를 포함한 상세 통계
sudo vdostats --verbose /dev/mapper/vg_data-vdopool0-vpool | grep -i overhead

# LVM 계층에서 VDO 풀의 데이터/메타데이터 사용량 확인
sudo lvs -a -o+devices,vdo_operating_mode vg_data

vdostats --verbose 출력에는 데이터 저장에 쓰인 물리 블록 수와 VDO 메타데이터 저장에 쓰인 물리 블록 수가 별도 항목으로 나뉘어 있어, 위 표의 계산식이 실제 배포 환경에서도 맞아떨어지는지 검증할 수 있다.

주의사항

UDS 인덱스 메모리는 사후에 무한정 늘릴 수 있는 값이 아니다. 인덱스 크기를 늘리려면 볼륨을 재생성하거나 VDO를 재구성해야 하는 경우가 많으므로, 처음 설계할 때 예상 데이터 증가량을 감안해 여유 있게 잡는 편이 낫다. 반대로 필요 이상으로 dense 인덱스를 크게 잡으면 위 표처럼 전체 오버헤드의 대부분을 인덱스가 차지하게 되므로, 유니크 데이터가 그리 많지 않은 워크로드라면 sparse 인덱스로 전환해 같은 디스크 비용으로 RAM을 아끼는 편이 합리적이다.

16TiB를 넘는 볼륨을 기본 슬랩 크기(2GiB)로 만들려고 하면 슬랩 8192개 상한에 걸려 lvcreate가 실패한다. 처음부터 대용량 스토리지 풀을 계획하고 있다면 슬랩 크기를 32GiB로 지정해 생성해야 한다.

앞의 비교표는 TiB 단위 볼륨에서만 성립하는 값이다. 볼륨을 수백 MB~수 GB 단위로 작게 잡으면 비율이 전혀 다르게 움직이는데, 이는 두 가지 “바닥값(floor)”이 있기 때문이다.

  • 슬랩 최소 예약 — VDO는 슬랩 depot용으로 슬랩을 최소 1개 통째로 예약한다. 슬랩 크기의 최솟값이 128MiB이므로 이 예약분은 물리 볼륨이 아무리 작아져도 줄어들지 않는다. 500MB 볼륨이라면 슬랩 예약 1개(128MiB)만으로 이미 25% 이상이 메타데이터로 소모된다.
  • UDS 인덱스 최소 요구량 — dense 인덱스는 RAM 최소 250MiB가 강제되고, 이는 디스크로 환산하면 0.25GiB × 17 = 4.25GiB에 해당한다. 500MB~1.5GB 볼륨은 전부 이 인덱스 하나의 최소 요구량보다 작다.

Red Hat 문서가 제시하는 실측 예시도 이를 뒷받침한다. “기본 설정(2GiB 슬랩 + 0.25 dense 인덱스) 기준 최소 디스크 사용량 약 4.7GiB”라는 수치가 사실상 VDO를 정상적으로 배포할 수 있는 최저 볼륨 크기에 가깝다.

볼륨 크기슬랩 개수(128MiB)구조적 메타데이터
(block map+저널)
구조적 오버헤드 비율dense 인덱스 최소 요구량배포 가능 여부
500 MB4개약 132 MiB약 26.4%4.25 GiB (고정)불가
750 MB6개약 134 MiB약 17.9%4.25 GiB (고정)불가
1 GB8개약 136 MiB약 13.3%4.25 GiB (고정)불가
1.5 GB12개약 140 MiB약 9.1%4.25 GiB (고정)불가

정리하면 오버헤드 비율은 크기 구간에 따라 다음과 같이 갈린다.

크기 구간오버헤드 비율 특성
TB 이상block map/저널/슬랩 개수가 크기에 정확히 비례해서 커지므로 약 1.8~2%로 수렴
GB 초반~그 이하슬랩 1개 예약 + 인덱스 최소 요구량 같은 고정비가 지배적이라 비율이 급격히 커짐 (수십~수백%)
수백 MB사실상 VDO 배포 불가능 영역 (메타데이터가 볼륨보다 큼)

마무리

dm-vdo의 메타데이터 오버헤드는 볼륨 크기가 커져도 비율 자체는 크게 벌어지지 않지만, 절대량은 무시할 수 없는 수준으로 커진다. 특히 UDS 인덱스가 전체 오버헤드의 대부분을 차지하기 때문에, 용량 산정 시 block map이나 저널보다 인덱스 메모리/디스크 크기를 어떻게 잡을지가 실질적인 변수다. dense와 sparse 인덱스는 디스크 비용이 아니라 RAM 비용과 판별 정밀도의 트레이드오프라는 점을 이해하고 나면, 워크로드 특성(유니크 데이터 비율, 가용 RAM)에 맞춰 더 정확하게 용량을 설계할 수 있다.

참고

답글 남기기