infra
Platform

모듈 맵

[Linux] 가상화 기초 — KVM/libvirt

0 / 20 완료

펼치기

리눅스 서버 운영 · 18 / 20

[Linux] 가상화 기초 — KVM/libvirt

KVM과 libvirt로 리눅스 가상머신을 생성·관리하고, 온프레미스 서버 환경에서의 가상화 운영 기초를 실습합니다

가상화 기초 — KVM/libvirt

🚨INCIDENT ALERT
HIGH

테스트 서버 한 대가 남아 개발팀 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하이퍼바이저 Type 1·2·1.5를 구분하고 KVM의 위치를 설명할 수 있다
  • 2KVM을 설치하고 하드웨어 가상화 지원 여부를 확인할 수 있다
  • 3virt-install로 명령줄에서 VM을 생성할 수 있다
  • 4virsh로 VM 생명주기(시작·정지·스냅샷)를 관리할 수 있다
  • 5NAT와 브리지 네트워크 차이를 이해하고 VM 네트워크를 진단할 수 있다
  • 6KVM·QEMU·libvirt의 역할을 구분해 클라우드 동작 원리와 연결할 수 있다
실습 환경 준비

💡개념

하이퍼바이저 타입과 KVM 위치

Type 1·Type 2·KVM(Type 1.5) 하이퍼바이저 구조를 비교한 다이어그램확대

  • Type 1 (베어메탈) — 하드웨어 위에 하이퍼바이저를 직접 설치합니다. 예: VMware ESXi, Hyper-V, Xen. 성능이 가장 높아 운영 서버에 씁니다.
  • Type 2 (호스트 OS 위) — 일반 OS 위에서 앱처럼 동작합니다. 예: VirtualBox, VMware Workstation. 데스크톱·개발용이며 OS 계층만큼 오버헤드가 있습니다.
  • KVM (Type 1.5) — 리눅스 커널 자체가 하이퍼바이저 역할을 합니다. CPU의 VT-x/AMD-V 가속을 직접 써서 성능이 Type 1에 근접하며, AWS EC2도 이 기술 위에서 동작합니다.
로컬 터미널
# 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

💡개념

KVM · QEMU · libvirt — 누가 무엇을 하는가

"KVM만 설치하면 된다"는 흔한 오해입니다. KVM은 CPU 가속만 담당하고, 디스크·NIC 같은 장치는 QEMU가 에뮬레이션하며, 그 조합을 libvirt가 관리합니다. 세 계층이 각자 다른 일을 하므로 역할을 구분해 두어야 문제가 났을 때 어디를 봐야 할지 알 수 있습니다.

KVM·QEMU·libvirt 계층 구조와 각 계층의 역할을 정리한 다이어그램확대

  • KVM (커널 모듈) — VT-x/AMD-V로 게스트 CPU 코드를 호스트에서 직접 실행합니다.
  • QEMU — VM이 보는 디스크·네트워크 카드·USB 등 I/O 디바이스를 소프트웨어로 에뮬레이션합니다.
  • libvirt — QEMU-KVM 조합을 표준 API로 추상화합니다. virsh·virt-install이 libvirt를 통해 VM을 제어하며, virsh dominfo는 호스트 측 메타데이터만 보여줍니다(VM 내부 프로세스는 SSH로 접속해 확인).

💡개념

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 출력에서 먼저 State 컬럼을 확인하고 — running이면 정상, shut off면 virsh start로 시작, paused면 virsh resume으로 재개
  • KVM 지원 수치 기준: egrep -c "(vmx|svm)" /proc/cpuinfo 결과가 1 이상이면 사용 가능, 0이면 BIOS에서 VT-x/AMD-V를 활성화하거나 중첩 가상화가 지원되는 환경 필요
  • virsh start 성공 후 virsh console에서 로그인 프롬프트가 안 나오면 → 직렬 콘솔 미설정, virsh console 응답 없이 멈추면 → 게스트 OS 부팅 중 오류(virsh domblkerror로 확인)를 의미

💡개념

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

실습 단계
1

KVM/libvirt 설치 및 하드웨어 가상화 지원 확인

egrep -c '(vmx|svm)' /proc/cpuinfo && sudo apt install qemu-kvm libvirt-daemon-system virtinst -y 2>/dev/null | tail -3

예상 출력

4  (0보다 크면 하드웨어 가상화 지원)
libvirt-daemon-system is already the newest version
2

libvirtd 서비스 시작 및 기본 네트워크 확인

sudo systemctl enable --now libvirtd && virsh net-list --all

예상 출력

 Name      State    Autostart   Persistent
 default    active   yes         yes
3

현재 VM 목록 확인

virsh list --all

예상 출력

 Id   Name   State
-------------------
(VM이 없으면 빈 목록 표시)
4

virbr0 네트워크 브리지 확인

ip addr show virbr0

예상 출력

virbr0: <...> mtu 1500
    inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
로컬 터미널
$ 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 개념 매핑:

KVMAWS
VM 생성 (virt-install)EC2 인스턴스 시작
디스크 이미지 (.qcow2)EBS 볼륨
스냅샷 (virsh snapshot)AMI / EBS 스냅샷
브리지 네트워크VPC + 서브넷
libvirt NATSecurity Group (기본 차단)

클라우드를 쓰더라도 KVM을 알면 "EC2 인스턴스가 결국 이런 것이구나"를 이해하고, 네트워크 문제나 성능 이슈를 훨씬 체계적으로 디버깅할 수 있습니다.

다음 모듈에서는 Ansible 기초 — 에이전트 없이 SSH로 수십 대 서버를 동시에 설정하고 자동화하는 방법을 다룹니다.

지식 확인

퀴즈 — 4문제

Q1

물리 서버 한 대에서 KVM으로 여러 VM을 실행하려 합니다. 팀원이 'KVM만 설치하면 되고 QEMU는 별개 소프트웨어라 필요 없다'고 주장합니다. KVM과 QEMU의 관계를 올바르게 설명한 것은?

Q2

virsh dominfo myvm 명령으로 VM의 상태를 확인하려 했는데, 팀원이 'VM 안에서 어떤 프로세스가 실행 중인지도 여기서 볼 수 있어'라고 말합니다. 이것이 맞는지 판단하세요.

Q3

운영 서버에서 주요 패키지 업그레이드 전에 KVM 스냅샷을 찍어두려 합니다. 스냅샷의 특성과 주의사항으로 올바른 것은?

Q4

새로 만든 KVM VM이 virsh start로 기동됐지만 VM 내부에서 ping 8.8.8.8이 실패합니다. 네트워크 연결 문제를 진단하기 위해 호스트에서 가장 먼저 확인해야 할 것은?

0 / 4 답변

이것도 배워보세요