Files
document-haness/docs/virtualization/tech-log-studio/storage-virtualization/concept/concept-qemu-block-backend-forms.md
T

9.2 KiB

id, kind, slug, title, topic, topicName, project, status, basisVersion, studio, sourceRevision, source
id kind slug title topic topicName project status basisVersion studio sourceRevision source
892b6087-8961-486c-b4d9-d3dd46bc2605 CONCEPT qemu-block-backend-forms /dev/vda 뒤에 있는 것 — qcow2 · RAW · Host block device storage-virtualization 스토리지 가상화 virtualization 초안 QEMU block backend 세 형태 — qcow2 파일 · RAW 파일 · Host block device. libvirt 로 정의한 VM 기준이고 SSOT 가 QEMU 와 libvirt 버전을 적지 않았다 https://hyeonworks.com/studio/documents/892b6087-8961-486c-b4d9-d3dd46bc2605/edit no-commit · 밖에서 반입한 문서 한 편. 고정할 저장소 리비전이 없다
final/document.md#140-vm-boundary를-넘으면-qemu가-등장
final/document.md#141-qemu가-물리-ssd를-직접-제어하는-것은-아니다
final/document.md#142-qcow2-host에서는-파일-guest에서는-디스크
final/document.md#143-qcow2-virtual-size와-실제-host-사용량
final/document.md#144-raw-image
final/document.md#145-host-block-device를-직접-backend로-사용-가능
final/document.md#146-실제-연결-확인
final/document.md#128-전체-구조
final/document.md#172-storage-virtualization-canonical-flow
final/document.md#174-핵심-claim

/dev/vda 뒤에 있는 것 — qcow2 · RAW · Host block device

게스트 안에서 /dev/vda 를 보는 것만으로는 호스트에 무엇이 있는지 알 수 없다. 가상 머신 경계를 넘으면 QEMU 의 virtio-blk 장치 모델과 블록 백엔드가 그 요청을 받는데, 그 백엔드는 qcow2 파일일 수도, RAW 파일일 수도, 호스트의 실제 블록 장치일 수도 있다. 갈래마다 바뀌는 것이 다르다. 파일 백엔드면 게스트 스토리지 계층 아래에 호스트 파일시스템과 블록 계층이 한 겹 더 놓이고, qcow2 면 게스트가 보는 크기와 호스트가 실제로 쓰는 크기가 갈린다. 무엇에 붙어 있는지는 게스트가 아니라 호스트에서 virsh domblklist 로 확인한다. 가상 머신에 디스크를 붙여 본 사람을 독자로 둔다.

관계

  • Guest 의 write() 가 virtqueue 에 실리기까지 — VFS · Filesystem · Page Cache · Block Layer · virtio-blk 게스트 안에서 virtqueue 까지 내려온 요청을 이 글이 이어받는다.
  • 완료라는 말의 네 가지 뜻 — write · writeback · flush · 전원 장애 생존 파일 백엔드면 호스트 페이지 캐시가 한 겹 더 생기고, 그 위에서 완료가 무엇을 보장하는지가 갈린다.
  • VM 아래에 한 번 더 있는 Host block stack — blk-mq · I/O Scheduler · NVMe 이 글은 백엔드 형태까지만 본다. 그 아래에서 요청이 어떻게 줄을 서는지는 그 글이 본다.
  • Guest 안에서 본 disk 로 backend 를 단정하지 않는다 이 글이 적은 세 갈래가 그 규칙의 근거다.
  • 이 호스트의 /dev/vda 는 어떤 backend 에 붙어 있는가 세 갈래 가운데 어느 것인지 이 장비에서 확인하지 않았다.
  • 이 disk image 는 qcow2 인가 RAW 인가, 그리고 Guest 가 보는 크기와 Host 가 실제로 쓰는 크기는 얼마나 다른가 이 글이 든 크기 차이는 SSOT 의 예시 값이고, 이 장비의 값은 그 질문이 잰다.
  • disk image 는 최종적으로 어느 Host block device 위에 있는가 파일 백엔드라면 그 파일이 놓인 호스트 장치까지 따라가야 경로가 끝난다.

본문

가상 머신 경계를 넘으면 QEMU 가 받는다

게스트의 virtio-blkvirtqueue 에 게시한 요청은 가상 머신 경계를 넘어 호스트 사용자 공간의 QEMU 로 간다. QEMU 안에서는 virtio-blk 장치 모델과 블록 백엔드가 그 요청을 받는다. QEMU 는 게스트에게 가상 블록 장치를 노출하고, 게스트의 가상 I/O 를 호스트 백엔드에 연결한다.

SSOT 는 제4부의 전체 구조를 그린 뒤 이 갈림을 핵심 문장 하나로 따로 뽑아 두었다.

Guest는 /dev/vda를 실제 block device처럼 보지만, Host에서는 그 disk가 qcow2 파일, RAW 파일, 또는 실제 block device에 연결되어 있을 수 있다.

이 글이 다루는 것이 그 문장이 남긴 세 갈래다.

QEMU 가 물리 SSD 를 직접 제어하지는 않는다

백엔드가 qcow2 파일이면 QEMU 는 결국 호스트 Linux 에 파일 I/O 를 요청한다. preadpwrite 같은 호출이 호스트 커널로 들어가고, 그 뒤로 호스트 파일시스템과 호스트 블록 계층, NVMe 드라이버를 지나 물리 NVMe 에 닿는다. 그 경로가 호스트 커널을 한 번 더 지나기 때문에, 게스트 스토리지 계층 아래에 호스트 스토리지 계층이 한 번 더 존재할 수 있다.

같은 대상을 호스트는 파일로, 게스트는 디스크로 본다

호스트에 /var/lib/libvirt/images/keycloak-node1.qcow2 라는 파일이 있다고 하자. 호스트 관점에서 그것은 파일 하나인데, 같은 대상을 게스트는 /dev/vda 라는 디스크로 보고 그 안을 /dev/vda1/dev/vda2 로 나눠 쓴다. 두 관점 모두 맞다.

qcow2 는 게스트가 보는 크기와 호스트가 쓰는 크기가 다르다

qcow2 는 가상 디스크 크기와 실제 호스트 할당량이 다를 수 있다. SSOT 가 든 예시에서는 게스트가 /dev/vda 를 100 GB 로 보는 동안 호스트의 vm1.qcow2 가 3GB 를 쓴다. 게스트가 데이터를 기록하면서 가상 크기 100GB 는 그대로인 채 실제 할당량이 1GB 에서 10GB 로, 다시 40GB 로 늘 수 있다. 이 숫자들은 SSOT 가 설명하려고 든 값이고 이 호스트에서 잰 값이 아니다.

qemu-img info vm1.qcow2

출력의 virtual size 와 실제 할당량은 서로 다른 값이다.

RAW 와 qcow2 를 성능으로 먼저 가르지 않는다

RAW 는 qcow2 보다 구조가 단순하다. 게스트의 블록 요청이 qcow2 에서는 QEMU 의 매핑과 메타데이터 처리를 지나 qcow2 파일 I/O 가 되고, RAW 에서는 상대적으로 직접적인 오프셋 대응을 지나 RAW 파일 I/O 가 된다. qcow2 는 Copy-on-Write 와 sparse allocation, 스냅샷에 유리하지만 그 대신 매핑과 메타데이터 처리가 붙는다.

그렇다고 RAW 가 무조건 빠르고 qcow2 가 무조건 느리다고 일반화하면 안 된다. SSOT 는 실제 성능이 캐시 모드와 스토리지 백엔드, 작업 부하 패턴, 큐 깊이, 스냅샷 체인, 그 아래 파일시스템, 물리 장치에 영향을 받는다고 적었다. 형식 이름만으로는 어느 쪽이 빠른지 정해지지 않는다.

백엔드가 파일이 아니라 호스트 블록 장치일 수도 있다

백엔드는 파일이 아니어도 된다. 게스트의 /dev/vdavirtio-blk 와 QEMU 를 지나 호스트의 /dev/nvme0n1p3 같은 블록 장치에 바로 연결될 수 있고, SSOT 가 그린 이 경로에는 호스트 파일시스템이 없다. 같은 이름 아래에서 경로가 세 갈래로 갈리기 때문에, 게스트에 /dev/vda 가 있다는 정보만으로는 백엔드 구조를 알 수 없다.

세 갈래가 각각 바꾸는 것

호스트에서는 무엇인가 그래서 무엇이 달라지나
qcow2 파일 게스트 파일시스템 아래에 호스트 파일시스템과 블록 계층이 한 겹 더 놓인다. Copy-on-Write 와 sparse allocation, 스냅샷을 쓸 수 있고 매핑과 메타데이터 처리가 붙는다. 게스트가 보는 가상 크기와 호스트 실제 할당량이 갈린다
RAW 파일 게스트 파일시스템 아래에 호스트 파일시스템과 블록 계층이 한 겹 더 놓인다. 블록 위치가 파일 오프셋에 상대적으로 직접 대응한다
호스트 블록 장치 SSOT 가 그린 경로에 호스트 파일시스템이 없다

무엇에 붙어 있는지는 호스트에서 확인한다

게스트에서 lsblk 로 장치를 보고, 호스트에서 virsh domblklist 로 그 장치의 Source 를 본다.

lsblk
virsh domblklist <VM_NAME>
Target   Source
-----------------------------------------------
vda      /var/lib/libvirt/images/vm1.qcow2

이 출력이 나오면 게스트의 /dev/vdavirtio-blk 와 QEMU 를 지나 /var/lib/libvirt/images/vm1.qcow2 에 닿는 연결이 확인된다.

확인하지 못한 것

이 호스트의 백엔드가 셋 중 무엇인지는 SSOT 에 없다. SSOT 가 열린 질문 넷을 적어 두었는데, 그 확인을 아직 돌리지 않았다. /dev/vda 가 어떤 백엔드에 붙어 있는지, 백엔드가 qcow2 인지 RAW 인지, qcow2 의 가상 크기와 실제 호스트 사용량이 얼마나 다른지, 그 이미지가 최종적으로 어느 호스트 블록 장치 위에 있는지 넷이다. 앞에서 든 100 GB 와 3GB, 1GB 에서 40GB 까지의 증가는 SSOT 가 설명하려고 든 예시 값이다.

qcow2 와 RAW 의 성능 비교도 이 저장소에 없다. SSOT 는 실제 성능을 가르는 조건만 열거했고 어느 쪽이 이 환경에서 빠른지는 재지 않았다.