LabHub

가상화와 QEMU/KVM · VM 생성과 부팅 · 이론

QEMU 커맨드라인 읽는 법

LabHub 에서 이어서 보기

한 줄 요약

QEMU 커맨드라인은 가상 하드웨어의 부품 목록이다. 플래그 하나하나가 게스트가 보게 될 장치를 정한다.

왜 이게 필요했나

실무에서는 대부분 libvirt 나 클라우드 콘솔을 쓴다. 그런데 문제가 생기면 결국 그 아래의 QEMU 커맨드라인을 읽어야 한다. libvirt 의 XML 도 결국 이 커맨드라인으로 변환되고, ps aux | grep qemu 로 실제 실행 인자를 확인하는 것이 진단의 첫걸음이다.

어떻게 동작하나

최소한의 VM 은 이렇게 생겼다.

qemu-system-x86_64 \  -accel tcg \  -m 512 \  -smp 2 \  -drive file=/root/vm/vm01.qcow2,if=virtio,format=qcow2 \  -netdev user,id=n0,hostfwd=tcp::12222-:22 \  -device virtio-net-pci,netdev=n0 \  -nographic \  -serial mon:stdio

각 플래그의 의미.

| 플래그 | 의미 | 실무 포인트 |
| --- | --- | --- |
| -accel kvm / tcg | 가속기 선택 | -accel help 로 쓸 수 있는 것 확인 |
| -m 512 | 메모리(MB) | 단위 생략 시 MB |
| -smp 2 | vCPU 개수 | -smp 2,sockets=1,cores=2 로 토폴로지 지정 가능 |
| -drive ...,if=virtio | 디스크 + 인터페이스 | format= 를 명시해야 안전 |
| -netdev / -device | 백엔드 / 프론트엔드 | 둘은 항상 쌍이다 |
| -nographic | 그래픽 없음 | 서버 환경 기본 |
| -serial mon:stdio | 시리얼을 stdio 로, 모니터 겸용 | Ctrl-a c 로 전환 |
| -monitor unix:<경로>,server,nowait | 모니터를 유닉스 소켓으로 | 자동화에 적합 |

-netdev-device 의 분리가 처음엔 헷갈린다. -netdev호스트 쪽 백엔드(패킷이 어디로 가는가), -device게스트가 보는 NIC(어떤 카드로 보이는가)다. 둘을 id= 로 연결한다.

네트워크 모드

| 모드 | 특징 | 언제 |
| --- | --- | --- |
| user (SLIRP) | 유저 공간 NAT. 특권 불필요 | 개발/테스트. 이 실습 환경의 유일한 선택 |
| tap | 커널 TAP 장치 | 프로덕션. 특권 필요 |
| bridge | TAP 을 브리지에 연결 | VM 간 통신, 외부 노출 |
| vhost-net | 링 처리를 커널에서 | 고성능 |

user 모드는 게스트가 밖으로 나가는 것은 되지만 밖에서 게스트로 들어오는 것은 안 된다. 그래서 hostfwd 로 포트를 뚫는다.

-netdev user,id=n0,hostfwd=tcp::12222-:22

호스트의 12222 로 들어온 TCP 를 게스트의 22 로 보낸다. 이 리슨 소켓은 QEMU 가 시작하는 즉시 열린다 — 게스트가 아직 부팅 중이어도 ss -ltn 에 보인다. 게스트가 안 떴으면 연결이 거부될 뿐이다.

모니터

QEMU 모니터는 실행 중인 VM 에게 말을 거는 콘솔이다.

-monitor unix:/root/vm/mon.sock,server,nowaitecho 'info status' | nc -U /root/vm/mon.sockecho 'info block'  | nc -U /root/vm/mon.sock

info status(실행/정지), info block(디스크), info network, system_powerdown(ACPI 종료 요청), savevm/loadvm(실행 중 스냅샷) 같은 명령이 있다. 자동화에서는 소켓으로 붙이는 것이 표준이다.

콘솔

-nographic-serial 조합으로 시리얼 콘솔을 쓴다. 게스트 커널에 console=ttyS0 을 넘겨야 커널 메시지가 시리얼로 나온다. 로그를 파일로 남기려면 -serial file:/root/vm/console.log 를 쓴다.

부팅 초기에 보이는 것들의 순서를 알아 두면 어디까지 진행됐는지 알 수 있다.

1. SeaBIOS (version ...) — 펌웨어가 떴다
2. Booting from Hard Disk... — 부트로더로 넘어갔다
3. Linux version ... — 커널이 시작됐다
4. 로그인 프롬프트 — 유저 공간까지 왔다

1번은 QEMU 가 시작되자마자 나온다. TCG 라서 3번까지 오래 걸려도, 1~2번이 보이면 디스크와 부트로더는 정상이라는 뜻이다.

현장에서 만나는 모습

ps aux | grep qemu 로 실제 인자 확인. libvirt 의 XML 과 실제 실행 인자가 다른 경우가 있다(캐시된 도메인 정의, 핫플러그된 장치). 진짜는 프로세스 커맨드라인에 있다.

format= 을 생략해 생기는 문제. QEMU 가 파일 내용을 보고 포맷을 추측하는데, 게스트가 디스크 첫 부분에 qcow2 헤더처럼 보이는 데이터를 쓰면 다음 부팅에서 오인할 수 있다. 항상 명시한다.

다음 실습에서 할 것

/opt/vm/ 의 이미지를 백킹으로 오버레이를 만들고, 실행 스크립트를 정확한 플래그로 작성하고, 실제로 띄워 시리얼 로그 · 모니터 응답 · hostfwd 리슨 소켓 세 가지를 확인한다.