- Authors

- Name
- Youngju Kim
- @fjvbn20031
- 들어가며
- KubeVirt란?
- 아키텍처 상세
- CRD (Custom Resource Definitions)
- CDI (Containerized Data Importer)
- 네트워킹
- 스토리지
- 라이브 마이그레이션
- 설치 가이드
- 실전 예제: Ubuntu VM 생성
- 유스케이스
- 마치며
들어가며
컨테이너와 가상머신(VM)은 서로 대체재가 아닌 보완재입니다. 레거시 애플리케이션, Windows 워크로드, 커널 수준 커스터마이징이 필요한 경우에는 여전히 VM이 필수적입니다. KubeVirt는 쿠버네티스 API를 확장하여 VM을 Pod처럼 관리할 수 있게 해주는 프로젝트입니다.
KubeVirt란?
KubeVirt는 쿠버네티스 네이티브 VM 오케스트레이션 솔루션입니다. 쿠버네티스 API를 확장하여 VM 생명주기를 kubectl로 관리할 수 있습니다.
핵심 특징
- 쿠버네티스 CRD(Custom Resource Definition)로 VM 정의
- 기존 쿠버네티스 인프라(네트워킹, 스토리지, 모니터링) 재활용
- 컨테이너와 VM이 동일 클러스터에서 공존
- libvirt/QEMU/KVM 기반의 검증된 가상화 스택 활용
CNCF 프로젝트 현황
KubeVirt는 CNCF(Cloud Native Computing Foundation)의 주요 프로젝트입니다.
| 항목 | 상세 |
|---|---|
| CNCF 레벨 | Incubating (Graduation 신청 중) |
| 도입 기업 | 41개 이상 |
| CNCF 순위 | Top 20 프로젝트 |
| GitHub 스타 | 5,000+ |
| 주요 사용 기업 | Red Hat, NVIDIA, ARM, CoreWeave |
아키텍처 상세
KubeVirt의 전체 아키텍처를 살펴보겠습니다.
+------------------------------------------------------------------+
| Kubernetes Control Plane |
| +------------+ +----------------+ +-------------------------+ |
| | API Server | | etcd | | Controller Manager | |
| +------+-----+ +----------------+ +-------------------------+ |
| | |
| +------v------------------+ |
| | virt-api | <-- API 확장, 유효성 검증 |
| | (Deployment) | |
| +------+------------------+ |
| | |
| +------v------------------+ |
| | virt-controller | <-- VM/VMI 감시, 생명주기 관리 |
| | (Deployment) | |
| +-------------------------+ |
+------------------------------------------------------------------+
+------------------------------------------------------------------+
| Worker Node |
| +-------------------------+ |
| | virt-handler | <-- 노드 수준 DaemonSet |
| | (DaemonSet) | |
| +------+------------------+ |
| | |
| +------v------------------+ +-------------------------------+ |
| | virt-launcher Pod | | virt-launcher Pod | |
| | +------------------+ | | +-------------------------+ | |
| | | libvirt | | | | libvirt | | |
| | | +------------+ | | | | +-------------------+ | | |
| | | | QEMU/KVM | | | | | | QEMU/KVM | | | |
| | | | (VM 1) | | | | | | (VM 2) | | | |
| | | +------------+ | | | | +-------------------+ | | |
| | +------------------+ | | +-------------------------+ | |
| +-------------------------+ +-------------------------------+ |
+------------------------------------------------------------------+
컴포넌트 상세
virt-api
API 서버의 확장 포인트로, VM 관련 API 요청을 처리합니다.
- Admission Webhook을 통한 VM 스펙 유효성 검증
- Subresource API 제공 (start, stop, restart, migrate)
- VNC/Console 프록시 엔드포인트
virt-controller
클러스터 수준 Deployment로, VM과 VMI 리소스를 감시합니다.
- VM CRD 변경 감지 및 VMI 생성/삭제
- virt-launcher Pod 스케줄링 요청
- 라이브 마이그레이션 오케스트레이션
- VM 상태 동기화
virt-handler
노드 수준 DaemonSet으로, 실제 VM 생명주기를 관리합니다.
- libvirt와 직접 통신
- VM 도메인 XML 생성 및 적용
- 노드 수준 네트워킹 설정
- 디바이스 핫플러그 처리
virt-launcher
개별 VM마다 생성되는 Pod입니다.
- libvirt 데몬 실행
- QEMU/KVM 프로세스 관리
- VM 콘솔 접근 제공
- Pod 종료 시 VM 정리(cleanup)
CRD (Custom Resource Definitions)
VirtualMachine (VM)
VM은 가상머신의 선언적 정의입니다. Pod에 대한 Deployment와 유사한 역할을 합니다.
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: my-vm
namespace: default
spec:
running: true
template:
metadata:
labels:
app: my-vm
spec:
domain:
cpu:
cores: 2
memory:
guest: 4Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
volumes:
- name: rootdisk
dataVolume:
name: my-vm-dv
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
hostname: my-vm
ssh_authorized_keys:
- ssh-rsa AAAA...
VirtualMachineInstance (VMI)
VMI는 실행 중인 VM 인스턴스를 나타냅니다. Pod와 유사하게, 실제 실행 상태를 반영합니다.
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstance
metadata:
name: my-vmi
spec:
domain:
cpu:
cores: 1
memory:
guest: 2Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
volumes:
- name: rootdisk
containerDisk:
image: quay.io/kubevirt/fedora-cloud-container-disk-demo:latest
VirtualMachineInstanceReplicaSet
동일한 VMI를 여러 개 복제하여 실행합니다.
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstanceReplicaSet
metadata:
name: my-vmirs
spec:
replicas: 3
selector:
matchLabels:
app: web-vm
template:
metadata:
labels:
app: web-vm
spec:
domain:
cpu:
cores: 1
memory:
guest: 1Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
volumes:
- name: rootdisk
containerDisk:
image: quay.io/kubevirt/fedora-cloud-container-disk-demo:latest
VirtualMachineInstanceMigration
VMI를 다른 노드로 라이브 마이그레이션합니다.
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstanceMigration
metadata:
name: migration-job
spec:
vmiName: my-vmi
CDI (Containerized Data Importer)
CDI는 VM 디스크 이미지를 쿠버네티스 PVC로 가져오는 컴포넌트입니다.
DataVolume CRD
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: ubuntu-dv
spec:
source:
http:
url: 'https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img'
storage:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 10Gi
storageClassName: local-path
다양한 이미지 소스
CDI는 여러 소스에서 디스크 이미지를 가져올 수 있습니다.
+------------------+ +-------+ +------------------+
| HTTP/HTTPS URL | --> | | | |
+------------------+ | | | |
| | | |
+------------------+ | CDI | --> | PersistentVolume|
| Container Registry| --> | | | Claim (PVC) |
+------------------+ | | | |
| | | |
+------------------+ | | | |
| S3 Bucket | --> | | | |
+------------------+ +-------+ +------------------+
| oVirt / VMware | -->
+------------------+
컨테이너 레지스트리에서 가져오기
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: registry-dv
spec:
source:
registry:
url: 'docker://quay.io/kubevirt/fedora-cloud-container-disk-demo:latest'
storage:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
S3에서 가져오기
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: s3-dv
spec:
source:
s3:
url: 's3://my-bucket/images/rhel9.qcow2'
secretRef: s3-credentials
storage:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
네트워킹
기본 Pod 네트워크
기본적으로 VM은 Pod 네트워크를 사용합니다. masquerade 모드가 권장됩니다.
spec:
domain:
devices:
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
Multus를 통한 다중 네트워크
Multus CNI를 사용하면 VM에 여러 네트워크 인터페이스를 연결할 수 있습니다.
apiVersion: k8s.cni.cncf.io/v1
kind: NetworkAttachmentDefinition
metadata:
name: br-vlan100
spec:
config: |
{
"cniVersion": "0.3.1",
"type": "bridge",
"bridge": "br-vlan100",
"vlan": 100,
"ipam": {
"type": "host-local",
"subnet": "10.100.0.0/24"
}
}
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: multi-net-vm
spec:
running: true
template:
spec:
domain:
devices:
interfaces:
- name: default
masquerade: {}
- name: vlan100
bridge: {}
networks:
- name: default
pod: {}
- name: vlan100
multus:
networkName: br-vlan100
스토리지
VM 디스크는 PVC(PersistentVolumeClaim)를 통해 관리됩니다.
스토리지 옵션 비교
| 스토리지 유형 | 용도 | 지속성 |
|---|---|---|
| PVC | 영구 디스크 | 영구 |
| DataVolume | CDI를 통한 이미지 임포트 | 영구 |
| containerDisk | 읽기 전용 부팅 이미지 | 임시 |
| emptyDisk | 임시 데이터 | 임시 |
| cloudInitNoCloud | 초기 설정 데이터 | 임시 |
라이브 마이그레이션
라이브 마이그레이션은 VM을 중단 없이 다른 노드로 이동하는 기능입니다.
요구 사항
- ReadWriteMany(RWX) 접근 모드의 PVC
- 공유 스토리지 (Ceph, NFS 등)
- 소스/대상 노드 간 동일한 CPU 기능 세트
마이그레이션 실행
# kubectl로 마이그레이션 시작
kubectl virt migrate my-vm
# 또는 Migration CRD 생성
cat <<EOF | kubectl apply -f -
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstanceMigration
metadata:
name: migration-my-vm
spec:
vmiName: my-vm
EOF
# 마이그레이션 상태 확인
kubectl get vmim migration-my-vm -o yaml
마이그레이션 정책 설정
apiVersion: migrations.kubevirt.io/v1alpha1
kind: MigrationPolicy
metadata:
name: high-priority-policy
spec:
bandwidthPerMigration: 1Gi
completionTimeoutPerGiB: 800
allowAutoConverge: true
selectors:
namespaceSelector:
matchLabels:
migration-policy: high-priority
설치 가이드
Operator 설치
# 최신 버전 확인
export KUBEVIRT_VERSION=$(curl -s https://api.github.com/repos/kubevirt/kubevirt/releases/latest | grep tag_name | cut -d '"' -f 4)
# Operator 배포
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/$KUBEVIRT_VERSION/kubevirt-operator.yaml"
# KubeVirt CR 생성
kubectl apply -f "https://github.com/kubevirt/kubevirt/releases/download/$KUBEVIRT_VERSION/kubevirt-cr.yaml"
# 설치 완료 대기
kubectl wait kv kubevirt -n kubevirt --for=condition=Available --timeout=300s
virtctl CLI 설치
# virtctl 다운로드
curl -L -o virtctl \
"https://github.com/kubevirt/kubevirt/releases/download/$KUBEVIRT_VERSION/virtctl-$KUBEVIRT_VERSION-linux-amd64"
chmod +x virtctl
sudo mv virtctl /usr/local/bin/
CDI 설치
export CDI_VERSION=$(curl -s https://api.github.com/repos/kubevirt/containerized-data-importer/releases/latest | grep tag_name | cut -d '"' -f 4)
kubectl apply -f "https://github.com/kubevirt/containerized-data-importer/releases/download/$CDI_VERSION/cdi-operator.yaml"
kubectl apply -f "https://github.com/kubevirt/containerized-data-importer/releases/download/$CDI_VERSION/cdi-cr.yaml"
실전 예제: Ubuntu VM 생성
apiVersion: cdi.kubevirt.io/v1beta1
kind: DataVolume
metadata:
name: ubuntu-22-04
spec:
source:
http:
url: 'https://cloud-images.ubuntu.com/jammy/current/jammy-server-cloudimg-amd64.img'
storage:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 20Gi
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: ubuntu-server
labels:
app: ubuntu-server
spec:
running: true
template:
metadata:
labels:
app: ubuntu-server
spec:
domain:
cpu:
cores: 2
memory:
guest: 4Gi
devices:
disks:
- name: rootdisk
disk:
bus: virtio
- name: cloudinitdisk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {}
networks:
- name: default
pod: {}
volumes:
- name: rootdisk
dataVolume:
name: ubuntu-22-04
- name: cloudinitdisk
cloudInitNoCloud:
userData: |
#cloud-config
hostname: ubuntu-server
user: ubuntu
password: changeme
chpasswd:
expire: false
ssh_authorized_keys:
- ssh-rsa AAAA...your-key
packages:
- qemu-guest-agent
runcmd:
- systemctl enable --now qemu-guest-agent
유스케이스
1. 하이브리드 컨테이너/VM 워크로드
마이크로서비스(컨테이너)와 레거시 모놀리스(VM)를 하나의 클러스터에서 운영합니다.
2. 레거시 애플리케이션 마이그레이션
VMware, OpenStack 등에서 실행 중인 기존 VM을 쿠버네티스로 점진적으로 이전합니다.
3. Windows 워크로드
.NET Framework 애플리케이션이나 Active Directory 서버를 쿠버네티스 클러스터에서 실행합니다.
4. 개발/테스트 환경
다양한 OS 환경을 빠르게 프로비저닝하고 테스트에 활용합니다.
마치며
KubeVirt는 컨테이너와 VM의 경계를 허물어 통합 인프라 관리를 가능하게 합니다. CNCF 프로젝트로서 활발한 커뮤니티 지원을 받고 있으며, Red Hat OpenShift Virtualization의 핵심 기술이기도 합니다.
다음 글에서는 NVIDIA GPU Operator를 통해 쿠버네티스에서 GPU를 자동으로 관리하는 방법을 알아보겠습니다.
퀴즈: KubeVirt 이해도 점검
Q1. KubeVirt에서 VM의 선언적 정의를 담당하는 CRD는?
A) VirtualMachineInstance B) VirtualMachine C) VirtualMachineInstanceReplicaSet D) VirtualMachineInstanceMigration
정답: B) VirtualMachine - Deployment와 유사하게 VM의 원하는 상태(desired state)를 선언합니다.
Q2. virt-launcher의 역할은?
A) 클러스터 수준에서 VM 리소스를 감시 B) API 요청 유효성 검증 C) 개별 VM마다 생성되는 Pod로 libvirt/QEMU 실행 D) 노드 수준에서 libvirt와 통신
정답: C) virt-launcher는 각 VM에 대해 하나의 Pod로 생성되며, 내부에서 libvirt와 QEMU/KVM 프로세스를 관리합니다.
Q3. CDI의 DataVolume이 지원하지 않는 이미지 소스는?
A) HTTP/HTTPS URL B) 컨테이너 레지스트리 C) Git 리포지토리 D) S3 버킷
정답: C) Git 리포지토리는 CDI 소스로 지원되지 않습니다. HTTP, Registry, S3, oVirt, VMware가 지원됩니다.
Q4. 라이브 마이그레이션의 필수 요구 사항은?
A) ReadWriteOnce PVC B) ReadWriteMany PVC + 공유 스토리지 C) emptyDisk 볼륨 D) containerDisk 볼륨
정답: B) 라이브 마이그레이션은 소스/대상 노드에서 동시에 접근 가능한 공유 스토리지(RWX)가 필요합니다.