가상화 기초 — KVM/libvirt
테스트 서버 한 대가 남아 개발팀 3개 팀이 서로 쓰겠다고 다툽니다. 물리 서버를 더 사기엔 예산이 없고, 한 대를 셋이 나눠 쓰자니 패키지 충돌로 매번 환경이 깨집니다.
선임이 "그거 그냥 KVM으로 VM 세 개 띄워"라고 합니다. virsh list 를 쳐보니 이미 죽어 있는 VM 두 개가 있고, 하나는 virsh start 하자마자 "cannot access storage file: Permission denied" 로 거부됩니다. qcow2 이미지의 소유권과 SELinux 레이블 문제였습니다.
가상화는 "서버 한 대를 여러 대처럼" 쓰는 가장 기본적인 인프라 기술입니다. 클라우드 인스턴스의 정체이기도 합니다. KVM/libvirt로 VM을 만들고, 띄우고, 안 뜰 때 어디를 봐야 하는지를 이 모듈에서 직접 해봅니다.
클라우드 이전의 온프레미스 환경에서, 그리고 지금도 프라이빗 클라우드 환경에서 KVM은 현역입니다. "서버 1대에 10개의 가상 서버"를 만드는 기술 — 이게 가상화입니다. AWS EC2도 내부적으로는 이런 기술 위에서 돌아갑니다.
KVM을 알면 AWS EC2가 어떻게 동작하는지 이해가 됩니다. 원리를 알면 클라우드도 더 잘 쓸 수 있습니다.
- 1하이퍼바이저 타입과 KVM 아키텍처
- 2KVM 설치와 하드웨어 가상화 지원 확인
- 3virt-install — 명령줄로 VM 생성
- 4virsh — VM 생명주기 관리 (시작/정지/스냅샷)
- 5VM 네트워크 — NAT vs 브리지
- 6실무 운영 패턴과 클라우드 연결 개념
하이퍼바이저 타입과 KVM 위치
Type 1 하이퍼바이저 (베어메탈) Type 2 하이퍼바이저 (호스트 OS 위)
───────────────────────── ─────────────────────────
VM1 VM2 VM3 VM1 VM2
│ │ │ │ │
하이퍼바이저 하이퍼바이저
│ │
물리 하드웨어 호스트 OS
│
물리 하드웨어
예: VMware ESXi, Hyper-V 예: VirtualBox, VMware Workstation
KVM은 사실상 Type 1.5:
VM1 (QEMU 프로세스) VM2 (QEMU 프로세스)
│ │
Linux 커널 (KVM 모듈 포함)
│
물리 하드웨어 (CPU VT-x)
KVM은 리눅스 커널 자체가 하이퍼바이저 역할 — 성능이 Type 1에 근접합니다.
# KVM 커널 모듈 확인
lsmod | grep kvm
# kvm_intel (Intel CPU) 또는 kvm_amd (AMD CPU)
# 가상화 가속 지원 확인
sudo kvm-ok
# INFO: /dev/kvm exists
# KVM acceleration can be used ← OK
virt-install — VM 생성
# Ubuntu 22.04 VM 생성 예시
sudo virt-install \
--name ubuntu-test \
--ram 2048 \
--vcpus 2 \
--disk path=/var/lib/libvirt/images/ubuntu-test.qcow2,size=20 \
--os-variant ubuntu22.04 \
--cdrom /tmp/ubuntu-22.04-server-amd64.iso \
--network network=default \
--graphics none \
--console pty,target_type=serial \
--extra-args 'console=ttyS0,115200n8 serial'
# 주요 옵션 설명
# --name: VM 이름
# --ram: 메모리 MB
# --vcpus: 가상 CPU 수
# --disk: 디스크 경로 + 크기(GB)
# --os-variant: OS 최적화 설정 (osinfo-query os 로 목록 확인)
# --network: NAT (default) 또는 bridge=br0 (브리지)
# 지원 OS 목록 확인
osinfo-query os | grep ubuntu
# 기존 이미지로 빠르게 VM 만들기 (클라우드 이미지 활용)
# Ubuntu cloud image 다운로드
wget https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img
# 이미지 크기 확장
qemu-img resize jammy-server-cloudimg-amd64.img +20G
# cloud-init 설정 ISO 생성
cat > user-data << 'EOF'
#cloud-config
password: mypassword
chpasswd: { expire: False }
ssh_pwauth: True
EOF
cloud-localds user-data.iso user-data
# VM 생성
sudo virt-install \
--name ubuntu-cloud \
--ram 2048 --vcpus 2 \
--disk jammy-server-cloudimg-amd64.img \
--disk user-data.iso,device=cdrom \
--os-variant ubuntu22.04 \
--network network=default \
--import --noautoconsole
virsh — VM 생명주기 관리
# ── 기본 관리 ──
virsh list --all # 전체 VM 목록 (실행 중 + 중지된 것)
virsh dominfo ubuntu-test # VM 상세 정보 (메모리, CPU, 상태)
virsh domstate ubuntu-test# 현재 상태만
# 시작/정지/재시작
virsh start ubuntu-test
virsh shutdown ubuntu-test # 정상 종료 (OS shutdown 신호)
virsh destroy ubuntu-test # 강제 종료 (전원 차단)
virsh reboot ubuntu-test
# 콘솔 접속
virsh console ubuntu-test # 직렬 콘솔 (Ctrl+] 로 나가기)
# ── 스냅샷 ──
# 스냅샷 생성 (OS 업그레이드 전)
virsh snapshot-create-as ubuntu-test \
--name "before-upgrade" \
--description "Ubuntu 22.04 → 24.04 업그레이드 전"
# 스냅샷 목록
virsh snapshot-list ubuntu-test
# 스냅샷으로 롤백
virsh snapshot-revert ubuntu-test before-upgrade
# 스냅샷 삭제 (누적되면 성능 저하)
virsh snapshot-delete ubuntu-test before-upgrade
# ── 리소스 조정 ──
# 메모리 런타임 조정 (최대값 내에서)
virsh setmem ubuntu-test 4096M --live
# CPU 런타임 조정
virsh setvcpus ubuntu-test 4 --live --maximum
# ── VM 설정 편집 ──
virsh edit ubuntu-test # XML 설정 편집 (저장 후 재시작 필요)
virsh dumpxml ubuntu-test # 현재 설정 XML 출력
- virsh list --all 에서 생성한 VM이 보이고, start 후 상태가 running 으로 바뀌는가?
- egrep -c "(vmx|svm)" /proc/cpuinfo 가 0보다 커서 하드웨어 가상화가 켜져 있는가?
- virsh start 가 Permission denied 로 실패하면 qcow2 이미지 소유권(qemu:qemu)과 경로를 확인했는가?
- virsh console 또는 virt-viewer 로 게스트에 실제 로그인까지 되는가?
VM 네트워크 — NAT vs 브리지
# ── 현재 네트워크 확인 ──
virsh net-list --all
# Name State Autostart Persistent
# default active yes yes
virsh net-info default
# Bridge: virbr0 ← 호스트의 가상 브리지
ip addr show virbr0
# inet 192.168.122.1/24 ← VM들의 게이트웨이
# ── NAT 모드 (기본) ──
# VM → 외부: 가능 (호스트 NAT 통해)
# 외부 → VM: 포트 포워딩 필요
# 용도: 개발/테스트 환경
# VM에서 호스트 접근
# 게이트웨이: 192.168.122.1 (호스트)
# ── 브리지 모드 (실제 네트워크 직접 연결) ──
# VM이 물리 스위치에 직접 연결된 것처럼 동작
# DHCP에서 실제 IP 할당
# 용도: 운영 서버, 외부 접근 필요한 환경
# 브리지 생성 (/etc/netplan/01-netcfg.yaml)
network:
version: 2
ethernets:
ens3:
dhcp4: false
bridges:
br0:
interfaces: [ens3]
dhcp4: true
# VM을 브리지에 연결
virt-install ... --network bridge=br0
$ virsh start myvm
error: Failed to start domain 'myvm'
error: internal error: process exited while connecting to monitor:
qemu-system-x86_64: -drive file=/var/lib/libvirt/images/myvm.qcow2:
Could not open '/var/lib/libvirt/images/myvm.qcow2':
Permission denied
원인: QEMU 프로세스는 libvirt-qemu 사용자로 실행됩니다. 디스크 이미지 파일의 소유권이나 권한이 맞지 않으면 접근 불가.
# 권한 확인
ls -la /var/lib/libvirt/images/myvm.qcow2
# 수정
sudo chown libvirt-qemu:kvm /var/lib/libvirt/images/myvm.qcow2
sudo chmod 660 /var/lib/libvirt/images/myvm.qcow2
# 또는 이미지를 libvirt 기본 경로에 복사
sudo mv myvm.qcow2 /var/lib/libvirt/images/
sudo chown root:root /var/lib/libvirt/images/myvm.qcow2
AppArmor가 막는 경우 (Ubuntu):
# AppArmor 로그 확인
sudo aa-status | grep qemu
sudo journalctl -k | grep apparmor | grep DENIED
# 임시 해제 (테스트용)
sudo aa-complain /usr/sbin/libvirtd
# 근본 해결: 이미지를 /var/lib/libvirt/images/ 아래에만 사용
KVM이 쓰이는 실제 환경
온프레미스 서버 운영 환경:
─────────────────────────────
물리 서버 (64GB RAM, 32 코어)
│
├── VM: web-server-01 (4GB RAM, 2 core) → Nginx
├── VM: web-server-02 (4GB RAM, 2 core) → Nginx
├── VM: db-primary (16GB RAM, 8 core) → PostgreSQL
├── VM: db-replica (16GB RAM, 8 core) → PostgreSQL
└── VM: monitoring (4GB RAM, 2 core) → Grafana
실무 운영 명령 모음:
# VM 일괄 상태 확인
virsh list --all
# VM 디스크 사용량 확인
du -sh /var/lib/libvirt/images/*.qcow2 | sort -rh
# VM 복제 (템플릿에서 빠르게 생성)
virt-clone --original ubuntu-template \
--name web-server-03 \
--file /var/lib/libvirt/images/web-server-03.qcow2
# 백업 (디스크 이미지 복사)
virsh suspend myvm # 일시 정지
cp /var/lib/libvirt/images/myvm.qcow2 /backup/myvm-$(date +%Y%m%d).qcow2
virsh resume myvm # 재개
# 호스트 종료 전 VM 전부 종료
for vm in $(virsh list --name); do virsh shutdown "$vm"; done
KVM vs 클라우드 VM 개념 매핑:
| KVM | AWS |
|---|---|
| VM 생성 (virt-install) | EC2 인스턴스 시작 |
| 디스크 이미지 (.qcow2) | EBS 볼륨 |
| 스냅샷 (virsh snapshot) | AMI / EBS 스냅샷 |
| 브리지 네트워크 | VPC + 서브넷 |
| libvirt NAT | Security Group (기본 차단) |
클라우드를 쓰더라도 KVM을 알면 "EC2 인스턴스가 결국 이런 것이구나"를 이해하고, 네트워크 문제나 성능 이슈를 훨씬 체계적으로 디버깅할 수 있습니다.