XCP-ng → Proxmox 마이그레이션 2편: 서비스 중단을 최소화하는 '대량 VM' 자동화 전략
안녕하세요, 13년 차 서버/스토리지 엔지니어입니다.
지난 1편에서는 개별 VM을 수동으로 옮기는 기초를 다졌다면, 이번 글에서는 수십 대 이상의 VM을 효율적으로 이관하는 자동화 전략을 다룹니다.
"VM이 50대인데 이걸 언제 다 옮기지?"라고 막막해하는 엔지니어분들께, 이 글이 야근을 줄여주는 실무 가이드가 되길 바랍니다.
1. 왜 대량 마이그레이션은 수동으로 하면 안 되는가?
VM이 3~5대 정도라면 수동으로 꼼꼼히 옮기는 것도 괜찮습니다. 하지만 50대, 100대가 넘어가면 이야기가 달라집니다.
- 시간 소요 폭증: 대당 30분씩만 잡아도 50대면 25시간입니다. 꼬박 밤을 새워도 모자란 시간입니다.
- 휴먼 에러(Human Error): 반복 작업은 필연적으로 실수를 부릅니다. VMID를 헷갈리거나, 네트워크 브릿지 설정을 실수로 빠뜨릴 확률이 100%에 수렴합니다.
- 일관성 붕괴: 작업하다 지치면 어떤 VM은
VirtIO로, 어떤 VM은IDE로 설정하는 등 구성 표준이 깨지게 됩니다.
즉, 대량 이관에서 자동화는 '선택'이 아니라 '생존'의 문제입니다.
2. 자동화 전략: 리스트 추출 → 변환 → 병렬 처리
가장 효율적인 흐름은 다음과 같습니다.
- (XCP-ng) 마이그레이션 대상 VM 목록(UUID, 이름) 추출
- (Shell) 스크립트를 통한 일괄 Export & 전송
- (Proxmox)
qm importdisk를 활용한 일괄 생성 및 연결
이 과정에서 Bash 스크립트와 병렬 처리(Parallelism)를 활용해 작업 시간을 획기적으로 단축할 수 있습니다.
3. 핵심 자동화 로직 설계
3-1. XCP-ng에서 VM 리스트 뽑기
먼저 무엇을 옮길지 목록화해야 합니다. xe 명령어로 실행 중인 VM의 리스트를 뽑아냅니다.
# 실행 중인 VM의 UUID와 이름(Name-Label) 추출
xe vm-list power-state=running --minimal | tr ',' '\n' | while read -r uuid; do
name=$(xe vm-param-get uuid="$uuid" param-name=name-label)
echo "${uuid},${name}" >> migration_list.csv
done
- 이렇게 만든
migration_list.csv파일은 자동화 스크립트의 입력값(Input)이 됩니다.
3-2. Cold vs Warm Migration 전략 선택
서비스 중요도에 따라 전략을 나눠야 합니다.
| 구분 | Cold Migration (추천) | Warm Migration |
|---|---|---|
| 방식 | VM 종료 → 디스크 복사 → Proxmox 부팅 | 데이터 선복제(rsync/zfs) → 컷오버 시점에 짧은 중단 |
| 장점 | 데이터 정합성 완벽 보장, 스크립트 단순 | 서비스 다운타임 최소화 (수 분 이내) |
| 단점 | 복사 시간만큼 서비스 중단 | 구현 난이도 높음, 데이터 변경분(Dirty block) 처리 복잡 |
| 대상 | 웹 서버, 개발 서버, 내부 시스템 | DB, 메인 서비스 |
Tip: 대량 이관 시에는 복잡도를 낮추기 위해 가능하면 Cold Migration을 야간/주말에 수행하는 것이 정신 건강에 이롭습니다.
4. [실전] 대량 임포트 Bash 스크립트 (bulk-import.sh)
XCP-ng에서 추출한 디스크 파일(qcow2 또는 raw)들이 이미 Proxmox 서버의 /mnt/migrate 경로에 업로드되어 있다고 가정하고 작성한 스크립트입니다.
주의: 이 스크립트는 예시입니다. 반드시 테스트 환경(VM 1~2대)에서 먼저 검증 후 운영에 적용하세요.
#!/bin/bash
set -e # 에러 발생 시 즉시 중단
# --- [설정 구간] ---
SRC_DIR="/mnt/migrate" # 업로드된 디스크 파일 경로
STORAGE="local-lvm" # Proxmox 타겟 스토리지
BRIDGE="vmbr0" # 네트워크 브릿지
START_VMID=2000 # 시작 VMID
CONCURRENCY=2 # 동시에 작업할 프로세스 수 (너무 높으면 디스크 I/O 병목 발생)
# ------------------
# 의존성 체크
command -v qm >/dev/null 2>&1 || { echo "Proxmox 'qm' command not found."; exit 1; }
# 작업 함수 정의
import_vm() {
local img_path="$1"
local vmid="$2"
local vm_name=$(basename "$img_path" | cut -d. -f1) # 파일명에서 확장자 제거
echo "[Start] VMID:$vmid Name:$vm_name Importing..."
# 1. VM 껍데기 생성 (Core 2, Mem 4G, VirtIO Net)
# 실제 환경에 맞춰 CPU/Mem 사양을 변수화하면 더 좋습니다.
qm create $vmid --name "$vm_name" --memory 4096 --cores 2 --net0 virtio,bridge=$BRIDGE --scsihw virtio-scsi-pci > /dev/null
# 2. 디스크 Import (자동으로 변환됨)
# qm importdisk는 성공 시 'unused0' 같은 형태로 디스크를 붙임
qm importdisk $vmid "$img_path" $STORAGE --format raw > /dev/null
# 3. Unused 디스크 찾아서 연결
# (importdisk 직후엔 보통 unused0으로 잡힘. 환경에 따라 파싱 필요)
local imported_disk=$(qm config $vmid | grep "unused" | awk '{print $2}')
if [ -n "$imported_disk" ]; then
# SCSI0번으로 연결 및 부팅 순서 지정
qm set $vmid --scsi0 $imported_disk --boot order=scsi0 > /dev/null
echo "[Done] VMID:$vmid Import Complete!"
else
echo "[Error] VMID:$vmid Disk import failed or not found."
fi
}
export -f import_vm
export STORAGE BRIDGE
# 파일 리스트를 읽어서 병렬 처리 (xargs 활용)
# VMID를 1씩 증가시키며 실행
count=0
find "$SRC_DIR" -name "*.qcow2" -o -name "*.raw" | while read img; do
vmid=$((START_VMID + count))
echo "$img $vmid"
count=$((count + 1))
done | xargs -n 2 -P $CONCURRENCY bash -c 'import_vm "$1" "$2"' _
5. 병목(Bottleneck) 관리 및 운영 팁
(1) 스토리지 I/O 제어
qm importdisk는 디스크 I/O를 엄청나게 잡아먹습니다.
- 병렬 개수(
CONCURRENCY) 조절: 처음엔1로 시작해서 스토리지 부하를 보고2~3으로 늘리세요. 무턱대고 10개씩 돌리면 스토리지 전체가 멈출(Hang) 수 있습니다.
(2) 네트워크 대역폭 제한
데이터 전송 시 rsync나 scp가 대역폭을 다 써버리면 다른 서비스에 장애가 납니다.
rsync --bwlimit=50000(약 50MB/s) 옵션 등으로 대역폭을 강제로 제한하세요.
(3) 부팅 후 체크리스트 (Fail-over)
자동화가 끝났다고 안심하면 안 됩니다. 다음 3가지는 수동으로라도 샘플링 체크해야 합니다.
- 네트워크 인터페이스 명칭: 리눅스의 경우
eth0가ens18로 바뀌면서 IP가 안 올라오는 경우가 90%입니다. - 부트 순서(Boot Order): 스크립트 오류로 디스크가 연결 안 되어 있으면 부팅이 안 됩니다.
- UEFI vs BIOS: 원본이 UEFI였다면, Proxmox에서도 BIOS 옵션을
OVMF(UEFI)로 바꿔줘야 합니다. (위 스크립트는 Default BIOS 기준입니다.)
마무리
대량 마이그레이션의 핵심은 "도구(Script)"가 아니라 "설계(Design)"입니다.
스크립트는 거들 뿐, 실제로는 언제 롤백할 것인가, 데이터 정합성은 어떻게 검증할 것인가를 고민하는 시간이 더 길어야 합니다.
오늘 소개한 스크립트를 기반으로, 여러분만의 환경에 맞는 '이관 자동화 도구'를 만들어 보시길 바랍니다.
다음 편에서는 "마이그레이션 후 필수 최적화: VirtIO 드라이버와 Guest Agent 세팅"에 대해 다뤄보겠습니다.
'IT > Proxmox' 카테고리의 다른 글
| [Infra] Broadcom이 쏘아 올린 공: VMware 버리고 Proxmox로 갈아타기 (feat. 네이티브 임포트 마법사) (2) | 2026.01.26 |
|---|---|
| [HomeLab] 10G 네트워크 구축, 아직도 비싸다고 생각하시나요? (3노드 풀메쉬 가성비 세팅법) (3) | 2026.01.22 |
| [Proxmox] 2대는 장난감, 3대부터가 진짜다: HA(High Availability) 설정 정석 가이드 (0) | 2026.01.22 |
| XCP-ng → Proxmox 마이그레이션 3편: 성능을 200% 끌어올리는 필수 최적화 가이드 (0) | 2026.01.21 |
| [Proxmox] 서버 2대로 클러스터 묶다가 피 보지 않으려면? (13년 차의 클러스터 구축 가이드) (5) | 2026.01.20 |
| XCP-ng 8.3 → Proxmox VE 9.1: 실무 엔지니어를 위한 VM 마이그레이션 가이드 (0) | 2026.01.18 |