02. KVM & QEMU Architecture
Proxmox의 심장 — Linux 커널에 내장된 하이퍼바이저 KVM과 하드웨어 에뮬레이터 QEMU의 동작 원리
📌 이 글의 목적
Proxmox VE는 KVM과 QEMU 위에 관리 레이어를 얹은 구조임. “VM을 만든다”는 행위의 이면에서 KVM과 QEMU가 각각 무슨 역할을 하고, 어떻게 협력하는지를 이해하면 성능 튜닝, 트러블슈팅, 아키텍처 설계의 기반이 됨.
이 글을 읽고 나면:
- KVM이 Linux 커널 안에서 어떻게 하드웨어 가상화를 수행하는지 이해할 수 있음
- QEMU의 역할(장치 에뮬레이션, I/O 처리)과 KVM과의 분업 구조를 설명할 수 있음
- VirtIO 준가상화가 왜 성능에 중요한지 이해할 수 있음
- VMware ESXi의 VMkernel 아키텍처와 구조적 차이를 비교할 수 있음
1. KVM 개요
1.1 KVM이란
KVM(Kernel-based Virtual Machine) 은 Linux 커널에 내장된 하이퍼바이저 모듈임. 2007년 Linux 2.6.20에 머지되었으며, 커널 모듈(kvm.ko, kvm-intel.ko 또는 kvm-amd.ko) 형태로 동작함.
핵심 특징:
- Linux 커널 자체를 하이퍼바이저로 전환함
- CPU의 하드웨어 가상화 확장(Intel VT-x, AMD-V)을 직접 활용함
- 각 VM은 Linux의 일반 프로세스로 표현됨 (
/proc에서 확인 가능) - 메모리 관리, 스케줄링, 장치 드라이버 등 Linux 커널의 기존 기능을 그대로 활용함
flowchart TB subgraph Userspace["사용자 공간 (User Space)"] QEMU1["QEMU 프로세스<br/>(VM 1)"] QEMU2["QEMU 프로세스<br/>(VM 2)"] MgmtTools["관리 도구<br/>(Proxmox, libvirt, virsh)"] end subgraph Kernel["커널 공간 (Kernel Space)"] KVM_Module["KVM 모듈<br/>(kvm.ko)"] KVM_Intel["kvm-intel.ko<br/>/ kvm-amd.ko"] Scheduler["Linux CFS 스케줄러"] MM["메모리 관리<br/>(mm subsystem)"] NetStack["네트워크 스택"] BlockLayer["블록 I/O 레이어"] end subgraph Hardware["하드웨어"] CPU["CPU<br/>(VT-x / AMD-V)"] RAM["RAM<br/>(EPT / NPT)"] NIC["NIC"] Disk["Disk"] end QEMU1 -->|"ioctl(/dev/kvm)"| KVM_Module QEMU2 -->|"ioctl(/dev/kvm)"| KVM_Module MgmtTools --> QEMU1 MgmtTools --> QEMU2 KVM_Module --> KVM_Intel KVM_Intel --> CPU KVM_Module --> Scheduler KVM_Module --> MM QEMU1 --> NetStack QEMU1 --> BlockLayer NetStack --> NIC BlockLayer --> Disk MM --> RAM
1.2 Type 1인가 Type 2인가
KVM의 하이퍼바이저 분류는 논란이 있음.
| 관점 | 분류 | 근거 |
|---|---|---|
| 전통적 분류 | Type 2 | Linux(Host OS) 위에서 동작함 |
| 실질적 분류 | Type 1 | 커널 모듈이 하드웨어에 직접 접근하여 VM을 실행함 |
| 현대적 해석 | 하이브리드 | Linux 커널 = 호스트 OS이자 하이퍼바이저 |
flowchart LR subgraph Type1["Type 1 (Bare-metal)"] direction TB VM_T1["VM"] HV_T1["Hypervisor<br/>(ESXi, Xen)"] HW_T1["Hardware"] VM_T1 --> HV_T1 --> HW_T1 end subgraph KVM_Type["KVM (하이브리드)"] direction TB VM_KVM["VM (QEMU 프로세스)"] Kernel_KVM["Linux Kernel + KVM 모듈"] HW_KVM["Hardware (VT-x/AMD-V)"] VM_KVM --> Kernel_KVM --> HW_KVM end subgraph Type2["Type 2 (Hosted)"] direction TB VM_T2["VM"] HV_T2["Hypervisor<br/>(VirtualBox, VMware Workstation)"] OS_T2["Host OS"] HW_T2["Hardware"] VM_T2 --> HV_T2 --> OS_T2 --> HW_T2 end
실질적으로 KVM은 Type 1에 가까움. KVM이 활성화되면 Linux 커널 자체가 하이퍼바이저가 되며, 호스트 OS의 프로세스들도 KVM 관점에서는 “또 다른 게스트”와 유사한 위치에 놓임. CPU 가상화는 하드웨어(VT-x/AMD-V)가 직접 수행하므로 소프트웨어 에뮬레이션 오버헤드가 없음.
💡 VMware ESXi와의 핵심 차이: ESXi는 전용 마이크로커널(VMkernel) 위에서 동작하여 범용 OS 기능이 없음. KVM은 범용 Linux 커널 위에서 동작하여 Linux의 모든 드라이버, 파일시스템, 네트워크 스택을 그대로 활용함. 이것이 장점(호환성, 유연성)이자 단점(공격 표면이 넓음)임.
2. KVM 내부 동작
2.1 CPU 가상화
KVM은 CPU의 하드웨어 가상화 확장을 활용하여 게스트 OS의 코드를 물리 CPU에서 직접 실행함.
Intel VT-x의 핵심 개념:
| 개념 | 설명 |
|---|---|
| VMX Root Mode | 하이퍼바이저(KVM)가 실행되는 모드. 모든 권한을 가짐 |
| VMX Non-Root Mode | 게스트 OS가 실행되는 모드. 특정 명령어가 제한됨 |
| VMCS | Virtual Machine Control Structure — VM 상태를 저장하는 하드웨어 구조체 |
| VM Entry | Root → Non-Root 전환 (게스트 실행 시작) |
| VM Exit | Non-Root → Root 전환 (게스트가 특권 명령 실행 시 하이퍼바이저로 제어 반환) |
sequenceDiagram participant KVM as KVM (VMX Root) participant CPU as 물리 CPU participant Guest as Guest OS (VMX Non-Root) KVM ->> CPU: VMLAUNCH/VMRESUME (VM Entry) CPU ->> Guest: 게스트 코드 직접 실행 Note over Guest: 일반 명령어는 네이티브 속도로 실행 Guest ->> CPU: 특권 명령어 실행 (I/O, MSR 접근 등) CPU ->> KVM: VM Exit (제어 반환) Note over KVM: Exit 원인 분석 및 처리 KVM ->> CPU: VMRESUME (VM Entry) CPU ->> Guest: 게스트 실행 재개
VM Exit의 주요 원인:
| Exit 원인 | 설명 | 빈도 |
|---|---|---|
| I/O 포트 접근 | 게스트가 하드웨어 I/O 수행 | 높음 |
| MSR 접근 | 모델 고유 레지스터 읽기/쓰기 | 중간 |
| CPUID 실행 | CPU 정보 조회 | 낮음 |
| EPT Violation | 메모리 매핑 실패 (페이지 폴트) | 상황에 따라 |
| 외부 인터럽트 | 물리 인터럽트 발생 | 높음 |
| HLT 명령 | 게스트 CPU 유휴 | 높음 |
💡 성능의 핵심은 VM Exit 최소화임. VM Exit가 발생할 때마다 컨텍스트 스위칭 비용이 발생함. VirtIO 장치는 VM Exit를 줄이도록 설계된 준가상화 인터페이스임.
2.2 메모리 가상화
KVM은 2단계 주소 변환(Two-Level Address Translation) 을 사용함.
Guest Virtual Address (GVA)
↓ [Guest Page Table — 게스트 OS가 관리]
Guest Physical Address (GPA)
↓ [Extended Page Table (EPT/NPT) — 하드웨어가 관리]
Host Physical Address (HPA)
→ 실제 물리 메모리
| 기술 | Intel | AMD | 설명 |
|---|---|---|---|
| 확장 페이지 테이블 | EPT | NPT (RVI) | 하드웨어가 GPA → HPA 변환을 직접 수행 |
| TLB 태깅 | VPID | ASID | VM 전환 시 TLB 플러시 방지 |
EPT 이전 (소프트웨어 방식 — Shadow Page Table):
- KVM이 게스트 페이지 테이블의 “그림자”를 소프트웨어로 유지함
- 모든 페이지 테이블 변경 시 VM Exit 발생 → 성능 저하
EPT 이후 (하드웨어 방식):
- CPU가 2단계 변환을 하드웨어로 직접 수행함
- 페이지 테이블 변경 시 VM Exit 불필요 → 성능 대폭 향상
- 현재 모든 최신 CPU가 EPT/NPT를 지원함
💡 VMware ESXi도 동일한 EPT/NPT를 사용함. 메모리 가상화 수준에서는 KVM과 ESXi의 성능 차이가 거의 없음.
2.3 인터럽트 가상화
VM에 인터럽트를 전달하는 방식도 하드웨어 지원으로 진화함.
| 세대 | 방식 | 설명 |
|---|---|---|
| 1세대 | 소프트웨어 에뮬레이션 | KVM이 가상 APIC를 소프트웨어로 구현 |
| 2세대 | APICv (Intel) / AVIC (AMD) | 하드웨어가 인터럽트를 게스트에 직접 주입. VM Exit 없음 |
| Posted Interrupts | Intel VT-x | 외부 인터럽트를 VM Exit 없이 게스트에 직접 전달 |
APICv/AVIC가 활성화되면 인터럽트 처리 관련 VM Exit가 크게 줄어 I/O 성능이 향상됨.
3. QEMU의 역할
3.1 KVM과 QEMU의 분업
KVM은 CPU와 메모리 가상화만 담당함. 나머지 모든 하드웨어(디스크, 네트워크, USB, GPU 등)의 에뮬레이션은 QEMU가 담당함.
flowchart LR subgraph KVM_Scope["KVM 담당"] CPU_Virt["CPU 가상화<br/>(VT-x/AMD-V)"] Mem_Virt["메모리 가상화<br/>(EPT/NPT)"] Interrupt["인터럽트 가상화<br/>(APICv/AVIC)"] end subgraph QEMU_Scope["QEMU 담당"] DiskEmu["디스크 컨트롤러<br/>(IDE, SCSI, VirtIO)"] NetEmu["네트워크 장치<br/>(e1000, VirtIO-net)"] DisplayEmu["디스플레이<br/>(VGA, QXL, VirtIO-GPU)"] USBEmu["USB 컨트롤러"] AudioEmu["오디오, 시리얼 등"] MachineEmu["머신 타입<br/>(i440fx, Q35)"] end subgraph Together["협력"] IOLoop["이벤트 루프<br/>(I/O 처리)"] DeviceModel["장치 모델 + KVM 가속"] end KVM_Scope --> Together QEMU_Scope --> Together
QEMU의 핵심 역할:
| 역할 | 설명 |
|---|---|
| 장치 에뮬레이션 | 가상 하드웨어(NIC, 디스크 컨트롤러, USB 등)를 소프트웨어로 구현 |
| 머신 타입 정의 | PC의 칩셋(i440fx, Q35)과 버스 토폴로지를 정의 |
| 이미지 관리 | QCOW2, RAW 등 디스크 이미지 포맷 처리 |
| 마이그레이션 | 라이브 마이그레이션 시 VM 상태 직렬화/전송 |
| 콘솔 접근 | VNC, SPICE 프로토콜로 VM 디스플레이 제공 |
| 모니터(QMP) | QEMU Machine Protocol — VM 제어용 JSON 기반 프로토콜 |
3.2 VM 프로세스 구조
Proxmox에서 VM 하나는 QEMU 프로세스 하나에 대응함.
# Proxmox에서 VM 100번의 프로세스 확인
ps aux | grep 'kvm.*-id 100'
# 출력 예시 (간략화)
/usr/bin/kvm \
-id 100 \
-name my-vm \
-machine type=pc-q35-9.0 \
-cpu host \
-m 4096 \
-smp 4,cores=4,sockets=1 \
-drive file=/dev/pve/vm-100-disk-0,format=raw,if=none,id=drive-scsi0 \
-device virtio-scsi-pci,id=scsihw0 \
-device scsi-hd,drive=drive-scsi0 \
-netdev type=tap,id=net0 \
-device virtio-net-pci,netdev=net0,mac=AA:BB:CC:DD:EE:FF \
-vnc 0.0.0.0:0이 프로세스는 Linux의 일반 프로세스이므로:
top,htop에서 CPU/메모리 사용량을 확인할 수 있음taskset으로 CPU affinity를 설정할 수 있음- Linux CFS 스케줄러가 다른 프로세스와 동일하게 스케줄링함
/proc/<pid>/에서 프로세스 정보를 조회할 수 있음kill명령으로 강제 종료도 가능함 (권장하지 않지만)
3.3 QEMU 스레드 모델
하나의 QEMU 프로세스 내부에는 여러 스레드가 존재함.
flowchart TB subgraph QEMU_Process["QEMU 프로세스 (VM 100)"] MainThread["메인 스레드<br/>(이벤트 루프, QMP)"] vCPU1["vCPU 0 스레드"] vCPU2["vCPU 1 스레드"] vCPU3["vCPU 2 스레드"] vCPU4["vCPU 3 스레드"] IOThread1["I/O 스레드<br/>(디스크 I/O)"] VNCThread["VNC/SPICE 스레드"] end
| 스레드 | 역할 | 개수 |
|---|---|---|
| vCPU 스레드 | 게스트 CPU 실행 (KVM ioctl 호출) | vCPU 수만큼 |
| 메인 스레드 | 이벤트 루프, 장치 에뮬레이션, QMP | 1 |
| I/O 스레드 | 디스크 I/O를 메인 스레드에서 분리 (iothread) | 설정에 따라 |
| Worker 스레드 | 비동기 작업 (라이브 마이그레이션, 스냅샷 등) | 상황에 따라 |
💡 iothread: 기본적으로 디스크 I/O는 메인 스레드에서 처리하는데, 이 경우 I/O가 많은 VM에서 장치 에뮬레이션이 병목이 될 수 있음. Proxmox에서
iothread=1옵션을 활성화하면 디스크 I/O를 별도 스레드로 분리하여 성능을 향상시킬 수 있음.
4. 머신 타입과 장치 모델
4.1 머신 타입
QEMU는 다양한 PC 칩셋을 에뮬레이션할 수 있음. Proxmox에서 사용하는 주요 머신 타입:
| 머신 타입 | 칩셋 | 특징 | 추천 |
|---|---|---|---|
| i440fx | Intel 440FX (1996) | 전통적 PCI 버스, 레거시 호환성 높음 | 레거시 OS |
| q35 | Intel ICH9 (2007) | PCIe 네이티브, IOMMU 지원, 핫플러그 | ✅ 기본값 |
flowchart TB subgraph i440fx["i440fx 머신"] PCI_Bus["PCI 버스"] IDE["IDE 컨트롤러"] PIIX3["PIIX3 사우스브릿지"] end subgraph q35["q35 머신"] PCIe_Bus["PCIe 버스"] AHCI["AHCI (SATA)"] ICH9["ICH9 사우스브릿지"] IOMMU_q35["IOMMU (VT-d)"] end
q35를 권장하는 이유:
- PCIe 패스스루(GPU, NIC 등)에 필수임
- PCIe 핫플러그를 지원하여 디스크/NIC를 VM 가동 중 추가/제거 가능
- 최신 OS(Windows 10+, Linux 5.x+)에서 더 나은 성능과 호환성
4.2 디스크 컨트롤러
| 컨트롤러 | 인터페이스 | 성능 | 호환성 | 추천 |
|---|---|---|---|---|
| IDE | ATA | 낮음 | 매우 높음 | ❌ (레거시용) |
| SATA (AHCI) | SATA | 중간 | 높음 | Windows 설치 시 |
| VirtIO SCSI | VirtIO | 높음 | Linux 기본, Windows는 드라이버 필요 | ✅ |
| VirtIO Block | VirtIO | 매우 높음 | 동일 | 단순 디스크 |
4.3 네트워크 장치
| 장치 | 에뮬레이션 | 성능 | 호환성 | 추천 |
|---|---|---|---|---|
| e1000 | Intel 82540EM | 중간 | 매우 높음 | 레거시/Windows 초기 설치 |
| vmxnet3 | VMware 호환 | 중간 | VMware 마이그레이션 | 마이그레이션 시 |
| VirtIO-net | 준가상화 | 높음 | Linux 기본, Windows는 드라이버 필요 | ✅ |
5. VirtIO — 준가상화 프레임워크
5.1 왜 VirtIO인가
전통적인 장치 에뮬레이션은 실제 하드웨어를 소프트웨어로 흉내내는 방식이므로 오버헤드가 큼. 게스트가 I/O를 수행할 때마다 VM Exit가 발생하고, QEMU가 에뮬레이션을 처리한 뒤 다시 게스트로 돌아감.
VirtIO는 게스트 OS가 “자신이 가상 환경에 있다는 것을 인지하고” 하이퍼바이저와 직접 효율적으로 통신하는 준가상화(Paravirtualization) 인터페이스임.
flowchart LR subgraph Emulation["전통적 에뮬레이션 (e1000)"] G1["게스트 드라이버<br/>(e1000)"] -->|"I/O → VM Exit"| Q1["QEMU<br/>(HW 에뮬레이션)"] -->|"실제 I/O"| H1["호스트 NIC"] end subgraph VirtIO_Path["VirtIO (준가상화)"] G2["게스트 VirtIO 드라이버"] -->|"Virtqueue<br/>(공유 메모리)"| Q2["QEMU VirtIO 백엔드<br/>/ vhost-net"] -->|"실제 I/O"| H2["호스트 NIC"] end
5.2 Virtqueue 구조
VirtIO의 핵심은 Virtqueue임. 게스트와 호스트가 공유 메모리 링 버퍼를 통해 데이터를 교환함.
flowchart TB subgraph SharedMem["공유 메모리"] DescTable["Descriptor Table<br/>(버퍼 주소/길이)"] AvailRing["Available Ring<br/>(게스트 → 호스트)"] UsedRing["Used Ring<br/>(호스트 → 게스트)"] end Guest["게스트 드라이버"] -->|"1. 버퍼 등록"| DescTable Guest -->|"2. 사용 가능 알림"| AvailRing Host["호스트 백엔드"] -->|"3. 버퍼 소비"| AvailRing Host -->|"4. 완료 알림"| UsedRing Guest -->|"5. 완료 확인"| UsedRing
동작 흐름 (네트워크 송신 예시):
- 게스트 드라이버가 전송할 패킷 데이터를 Descriptor Table에 등록함
- Available Ring에 “이 버퍼를 처리해줘”라고 알림
- 호스트 백엔드(QEMU 또는 vhost-net)가 Available Ring에서 버퍼를 꺼내 실제 전송
- 전송 완료 후 Used Ring에 “처리 완료”를 기록
- 게스트가 Used Ring을 확인하고 버퍼를 회수
이 구조는 배치 처리에 유리함. 여러 패킷을 한 번에 Virtqueue에 넣고 한 번의 알림으로 처리할 수 있어 VM Exit 횟수를 크게 줄임.
5.3 vhost — 커널 레벨 가속
기본 VirtIO는 QEMU(유저 공간)에서 I/O를 처리하지만, vhost는 이를 커널 공간으로 이동시켜 성능을 더 향상시킴.
flowchart LR subgraph Default["기본 VirtIO"] GD1["게스트"] -->|"Virtqueue"| QEMU_IO["QEMU<br/>(User Space)"] -->|"시스템 콜"| Kernel1["커널"] --> HW1["HW"] end subgraph Vhost["vhost-net"] GD2["게스트"] -->|"Virtqueue"| VhostNet["vhost-net<br/>(Kernel Space)"] --> HW2["HW"] end
| 방식 | I/O 처리 위치 | 컨텍스트 스위치 | 성능 |
|---|---|---|---|
| VirtIO (기본) | QEMU (User Space) | 많음 | 좋음 |
| vhost-net | 커널 (Kernel Space) | 적음 | 매우 좋음 |
| vhost-user | 별도 유저 프로세스 (DPDK 등) | 최소 | 최고 |
💡 Proxmox에서는 VirtIO NIC 사용 시 vhost-net이 기본으로 활성화됨. 추가 설정 없이도 커널 레벨 가속 혜택을 받음.
5.4 VirtIO 장치 목록
| VirtIO 장치 | 용도 | Proxmox 설정 |
|---|---|---|
| virtio-net | 네트워크 | NIC 모델에서 VirtIO 선택 |
| virtio-blk | 블록 스토리지 (단순) | 디스크 버스에서 VirtIO Block 선택 |
| virtio-scsi | SCSI 스토리지 (고급) | 디스크 버스에서 VirtIO SCSI 선택 |
| virtio-balloon | 메모리 동적 조절 | 기본 활성화 |
| virtio-serial | 시리얼 통신 (QEMU Guest Agent) | Guest Agent 연동 |
| virtio-rng | 난수 생성기 | 보안 강화용 |
| virtio-gpu | GPU (2D/3D) | 디스플레이 용도 |
| virtio-fs | 파일시스템 공유 | 호스트-게스트 파일 공유 |
⚠️ Windows VM에서 VirtIO를 사용하려면
virtio-winISO에서 드라이버를 설치해야 함. Linux는 커널에 VirtIO 드라이버가 기본 내장되어 있음.
6. 디스크 이미지 포맷
6.1 QCOW2 vs RAW
| 항목 | QCOW2 | RAW |
|---|---|---|
| 정식 명칭 | QEMU Copy-On-Write v2 | Raw disk image |
| 파일 크기 | 사용한 만큼 (Thin Provisioning) | 할당한 전체 크기 |
| 스냅샷 | ✅ 내장 지원 | ❌ (외부 스냅샷만) |
| 암호화 | ✅ LUKS 통합 | ❌ |
| 압축 | ✅ zlib/zstd | ❌ |
| 성능 | 약간의 오버헤드 | 최고 (직접 I/O) |
| 백킹 파일 | ✅ (오버레이 구조) | ❌ |
Proxmox에서의 선택 기준:
| 스토리지 | 권장 포맷 | 이유 |
|---|---|---|
| LVM / LVM-thin | RAW | LVM 자체가 Thin Provisioning과 스냅샷 지원 |
| ZFS | RAW | ZFS가 CoW와 스냅샷을 제공하므로 QCOW2 기능이 중복 |
| 디렉토리 (dir) | QCOW2 | 파일 기반이므로 QCOW2의 Thin Provisioning 활용 |
| NFS | QCOW2 | 동일 이유 |
| Ceph (RBD) | RAW | Ceph가 자체 스냅샷/씬 프로비저닝 지원 |
6.2 QCOW2 내부 구조
flowchart TB subgraph QCOW2["QCOW2 파일 구조"] Header["Header<br/>(매직 넘버, 버전, 클러스터 크기)"] L1Table["L1 Table<br/>(최상위 인덱스)"] L2Tables["L2 Tables<br/>(2차 인덱스)"] DataClusters["Data Clusters<br/>(실제 데이터)"] RefcountTable["Refcount Table<br/>(참조 카운트 — 스냅샷용)"] end Header --> L1Table L1Table --> L2Tables L2Tables --> DataClusters Header --> RefcountTable
- 2단계 매핑: 게스트의 디스크 오프셋을 L1 → L2 테이블을 통해 실제 파일 내 오프셋으로 변환
- Refcount: 각 클러스터의 참조 횟수를 추적하여 스냅샷 시 Copy-on-Write를 구현
- 클러스터 크기: 기본 64KB. 큰 순차 I/O에는 큰 클러스터, 작은 랜덤 I/O에는 작은 클러스터가 유리
7. PCI Passthrough와 IOMMU
7.1 개념
PCI Passthrough는 물리 장치(GPU, NIC, NVMe 등)를 VM에 직접 할당하여 네이티브에 가까운 성능을 제공하는 기술임.
flowchart LR subgraph Without["에뮬레이션 (기본)"] VM_emu["VM"] -->|"VirtIO"| QEMU_emu["QEMU"] --> HW_emu["물리 장치"] end subgraph With["PCI Passthrough"] VM_pt["VM"] -->|"직접 접근"| HW_pt["물리 장치"] end
7.2 IOMMU (VT-d / AMD-Vi)
PCI Passthrough가 안전하게 동작하려면 IOMMU가 필수임. IOMMU는 장치의 DMA(Direct Memory Access)를 격리하여 VM이 다른 VM이나 호스트의 메모리에 접근하는 것을 방지함.
| 항목 | 설명 |
|---|---|
| Intel | VT-d (Virtualization Technology for Directed I/O) |
| AMD | AMD-Vi (AMD I/O Virtualization Technology) |
| 역할 | 장치 DMA를 VM 단위로 격리 |
| 활성화 | BIOS + 커널 파라미터 (intel_iommu=on 또는 amd_iommu=on) |
IOMMU 그룹: 물리적으로 같은 PCIe 슬롯이나 브릿지에 연결된 장치들은 하나의 IOMMU 그룹을 형성함. Passthrough 시 그룹 내 모든 장치를 함께 할당해야 함.
💡 GPU Passthrough는 홈랩에서 인기 있는 사용 사례임. NVIDIA/AMD GPU를 VM에 직접 할당하여 게이밍, AI/ML 워크로드, VDI 등에 활용 가능. q35 머신 타입에서 가장 잘 동작함.
8. QEMU Guest Agent
8.1 역할
QEMU Guest Agent(qemu-ga)는 VM 내부에 설치하는 에이전트로, 호스트가 게스트 OS와 통신할 수 있게 함.
| 기능 | 설명 |
|---|---|
| 파일시스템 Freeze/Thaw | 백업 시 데이터 일관성 보장 (스냅샷 전 freeze) |
| IP 주소 보고 | 호스트에서 게스트 IP를 확인 가능 |
| 시간 동기화 | 호스트와 게스트 시간 동기화 |
| 게스트 명령 실행 | 호스트에서 게스트 내부 명령 실행 |
| 정상 종료 | ACPI 대신 에이전트를 통한 안전 종료 |
💡 VMware Tools와 대응하는 기능임. VMware Tools가 더 많은 기능(드라이버 포함)을 제공하지만, QEMU Guest Agent + VirtIO 드라이버의 조합이 유사한 역할을 함.
9. VMware ESXi와의 아키텍처 비교
| 항목 | KVM + QEMU | VMware ESXi |
|---|---|---|
| 커널 | Linux 커널 (범용) | VMkernel (전용 마이크로커널) |
| 하이퍼바이저 위치 | 커널 모듈 | 커널 자체가 하이퍼바이저 |
| VM 표현 | Linux 프로세스 (QEMU) | VMX 프로세스 (World) |
| CPU 가상화 | VT-x/AMD-V (동일) | VT-x/AMD-V (동일) |
| 메모리 가상화 | EPT/NPT (동일) | EPT/NPT (동일) |
| 장치 에뮬레이션 | QEMU (소프트웨어) | VMkernel 내장 |
| 준가상화 | VirtIO | VMware Paravirtual (PVSCSI, VMXNET3) |
| I/O 가속 | vhost-net, io_uring | VMkernel 직접 I/O |
| 디스크 포맷 | QCOW2 / RAW | VMDK |
| 드라이버 모델 | Linux 드라이버 (광범위) | VIB 기반 (HCL 제한적) |
| 오버헤드 | Linux 커널 서비스 포함 | 최소 (전용 커널) |
| 유연성 | 높음 (Linux 생태계 전체) | 제한적 (VMware 생태계 내) |
| 보안 표면 | 넓음 (범용 OS) | 좁음 (최소 커널) |
flowchart TB subgraph KVM_Stack["KVM/QEMU 스택"] direction TB KVM_VM["VM (QEMU 프로세스)"] KVM_Kernel["Linux Kernel<br/>+ KVM 모듈<br/>+ 모든 Linux 드라이버"] KVM_HW["Hardware"] KVM_VM --> KVM_Kernel --> KVM_HW end subgraph ESXi_Stack["ESXi 스택"] direction TB ESXi_VM["VM (VMX World)"] ESXi_Kernel["VMkernel<br/>(마이크로커널)<br/>+ VIB 드라이버"] ESXi_HW["Hardware"] ESXi_VM --> ESXi_Kernel --> ESXi_HW end
핵심 트레이드오프:
- KVM: Linux 생태계의 모든 드라이버/도구를 활용할 수 있지만, 범용 OS의 오버헤드와 보안 표면이 있음
- ESXi: 전용 커널로 오버헤드가 최소이지만, HCL에 있는 하드웨어만 지원하고 유연성이 제한됨
💡 성능 면에서는 CPU/메모리 가상화는 둘 다 동일한 하드웨어 가속(VT-x, EPT)을 사용하므로 차이가 거의 없음. I/O 성능은 VirtIO + vhost vs PVSCSI + VMXNET3로 비슷한 수준. 실질적 차이는 관리 도구, 생태계, 라이선스에서 나옴.
정리
KVM과 QEMU는 각각 명확한 역할 분담이 있음.
- KVM: CPU와 메모리 가상화를 하드웨어 가속으로 처리. Linux 커널 모듈로 동작
- QEMU: 나머지 모든 하드웨어를 에뮬레이션. 각 VM이 하나의 QEMU 프로세스로 표현됨
- VirtIO: 에뮬레이션 오버헤드를 줄이는 준가상화 인터페이스. 성능 최적화의 핵심
- vhost: VirtIO I/O를 커널 공간으로 이동시켜 추가 성능 향상
이 아키텍처를 이해하면 VM 성능 튜닝(VirtIO 사용, iothread 활성화, CPU Pinning), 장치 선택(q35 vs i440fx, SCSI vs Block), Passthrough 설정 등의 판단 기준이 됨.
다음 글
→ #3 Proxmox 관리 아키텍처 — 웹 UI, API, CLI, 권한, 클러스터 통신 구조
🔗 관련 문서
- Proxmox VE Overview — 시리즈 #1, 전체 그림
- Hypervisor Virtualization — Type 1/2 하이퍼바이저 개념
- VMware ESXi Architecture — ESXi 아키텍처 비교
- Proxmox VE Series Index — 시리즈 목차