TL;DR — 프라이빗 클라우드 제품의 VM 라이브 마이그레이션을 0→1로 구현했다. “동작하게” 만드는 것과 “운영에서 믿고 쓰게” 만드는 것 사이의 간극에서, 다운타임·CPU 이기종·동시성/deadlock·관측성·이동 불가 케이스를 하나씩 막았다. 이 글은 그 전체 여정의 지도이고, 깊은 이야기는 각각 따로 링크한다.
프라이빗 클라우드 IaaS 제품 **CloudiA**의 VM 라이브 마이그레이션을 0→1로 구현했다. “실행 중인 VM을 멈추지 않고 다른 물리 호스트로 옮긴다” — 말은 한 줄이지만, 처음 동작하게 만드는 것과 운영에서 믿고 쓸 수 있게 만드는 것 사이엔 큰 간극이 있었다.
먼저, 라이브 마이그레이션이 하는 일
간단히: source 호스트의 VM 메모리를 target으로 반복 전송 → 충분히 따라잡으면 아주 짧게 멈췄다 target에서 깨움(cutover) → target에서 네트워크를 다시 붙임. 메모리 전송 자체는 libvirt/QEMU가 해주지만, “언제, 어떤 순서로, 무엇을 하고, 실패하면 어떻게 되돌리나”는 관리 플레인의 몫이었다.
0→1: 일단 동작하게
첫 구현은 다단계 절차였다 — 대상 호스트 선정 → 자원 예약 → 메모리 전송 → cutover → target 네트워크 설정 → source 정리. 각 단계는 실패할 수 있고, 중간에 실패하면 VM이 어느 호스트에도 없는 상태가 될 수 있다. 그래서 처음부터 핵심은 “어디까지 진행됐는지”를 상태로 추적해 정확히 되돌리는 rollback이었다. 예를 들어 source VM을 이미 내린 뒤 실패하면, source에 VM을 다시 살려내는 전체 복구 경로가 돌아야 한다.
그다음이 진짜 일이었다 — 단단하게
동작은 시작일 뿐이었다. 운영에서 부딪힌 문제들을 하나씩 막았다.
1. 네트워크 다운타임 약 20s → 1–2s
마이그레이션 직후 VM 네트워크가 약 20초 끊겼다. 원인은 cutover 이후 직렬로 실행되던 방화벽 체인 생성. 그 idempotent한 작업을 마이그레이션 시작 _전_으로 옮기는 것만으로 1–2초로 줄였다. → 다운타임을 1–2초로 줄인 과정 (deep-dive)
2. CPU 이기종 호환성 — 런타임 실패를 사전 차단
Intel 세대 간(예: Cascadelake ↔ Icelake)이나 AMD ↔ Intel 호스트로 옮기면 CPU 기능(flags) 불일치로
런타임에 실패했다. virsh 로그로 원인(CPUID/feature 불일치)을 분석한 뒤, 접근을 바꿨다 —
이동 대상 호스트를 고르는 시점에 호환성을 미리 검사해 불가능한 조합을 아예 후보에서 제외했다.
런타임에 QEMU가 “missing features…”를 토하는 것보다, API 레벨에서 먼저 막는 게 운영자 경험과 VM 안전성
모두에 낫다. (사전 검증 > 런타임 실패 — 이 시스템 전체를 관통한 교훈.)
3. 동시성과 deadlock
동시에 너무 많은 마이그레이션이 돌면 호스트가 흔들린다 → 동시 실행 수를 제한하고 초과 요청은 즉시 거절(409)했다. 또 source·target 두 호스트의 락을 잡는 순서가 마이그레이션 방향에 따라 뒤집히면 deadlock이 났다 → **락 획득 순서를 항상 고정(ID 오름차순)**해 구조적으로 막고, 회귀 테스트로 묶었다.
4. 관측성 — 한 건을 끝까지 추적
마이그레이션 1건은 여러 단계 + 비동기 정리까지 걸쳐 로그가 흩어진다. 마이그레이션마다 ID를 부여해 비동기 작업에서도 그 ID로 따라가게 했다. “이 마이그레이션 한 건”을 로그에서 통째로 grep할 수 있게 되자 장애 분석 시간이 크게 줄었다.
5. 이동할 수 없는 VM — cold migration
일부 VM(메모리 암호화 같은 보안 가상화)은 라이브 마이그레이션 자체가 불가능하다. 이건 무리하게 시도하는 대신 전원을 내렸다 target에서 올리는 cold migration 경로로 분리하고, 전원 off 전/후의 rollback을 각각 다르게 처리했다.
관통하는 패턴
여러 문제를 풀고 나니 같은 원리가 반복됐다:
- rollback은 “어디까지 됐나”를 상태로 추적해야 신뢰할 수 있다.
- idempotent한 작업은 critical path 밖으로 빼라 (다운타임 글의 핵심).
- 사전 검증 > 런타임 실패 (CPU 호환성).
- 순서를 고정하면 deadlock은 구조적으로 사라진다.
시리즈
- (이 글) 전체 개요 — 0→1 구현과 하드닝
- 네트워크 다운타임 약 20s → 1–2s
- CPU 이기종 호환성 — 작성 예정
- 동시성·deadlock — 작성 예정