이 글에서는 KubeVirt 환경에서 가상 머신의 라이프사이클 관리, 라이브 마이그레이션, 고가용성(HA) 설정 등 운영 관리 측면에 초점을 맞춰 알아보겠습니다. Docker Desktop 환경에서의 VM 라이프사이클 관리부터 실제 프로덕션 환경에서 활용할 수 있는 스케줄링 및 로깅 기법까지 살펴봅니다.
📌 VM 라이프사이클 관리
KubeVirt는 기본적으로 VM의 전체 생명주기를 관리하는 기능을 제공합니다. 이는 VM의 생성부터 시작, 일시 중지, 중지, 재시작 및 삭제까지 포함합니다.
✅ VM 상태(State) 이해하기
KubeVirt VM은 다음과 같은 주요 상태를 가질 수 있습니다:
- Running: VM이 실행 중인 상태
- Stopped: VM이 중지된 상태
- Paused: VM이 일시 중지된 상태
- Migrating: VM이 다른 노드로 마이그레이션 중인 상태
- Starting: VM이 시작 중인 상태
- Stopping: VM이 중지 중인 상태
다음 명령어로 현재 VM의 상태를 확인할 수 있습니다:
# VM 목록 및 상태 확인
kubectl get vm
# 상세 상태 확인 - VM의 모든 구성과 현재 상태를 YAML 형식으로 출력
kubectl get vm <vm-name> -o yaml
✅ 기본 VM 라이프사이클 명령어
VM을 제어하기 위한 기본 명령어를 살펴보겠습니다.
▶️ VM 시작/중지:
# VM 시작 - 중지된 VM을 실행 상태로 변경
kubectl virt start <vm-name>
# VM 중지 - 실행 중인 VM을 정상적으로 종료 (ACPI 신호 전송)
kubectl virt stop <vm-name>
# VM 재시작 - VM을 순차적으로 중지하고 다시 시작 (OS 재부팅과 유사)
kubectl virt restart <vm-name>
▶️ VM 일시 정지/재개:
# VM 일시 정지 - VM 실행을 일시 중단하지만 메모리 상태는 유지
kubectl virt pause <vm-name>
# VM 재개 - 일시 정지된 VM을 다시 실행 상태로 변경
kubectl virt unpause <vm-name>
이러한 명령어는 내부적으로 VirtualMachine 리소스의 spec.running 필드를 변경하거나 특별한 subresource API를 호출합니다.
✅ YAML 기반 VM 라이프사이클 관리
YAML을 통해 직접 VM의 상태를 관리할 수도 있습니다:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: lifecycle-demo # VM의 고유 이름
labels:
app: demo # VM 식별 및 선택을 위한 라벨
spec:
running: true # VM의 실행 상태 제어 (true: 실행, false: 중지)
template:
metadata:
labels:
kubevirt.io/vm: lifecycle-demo # virt-launcher Pod에 적용될 라벨
spec:
domain:
devices:
disks:
- name: rootdisk # 디스크 참조 이름 (volumes 섹션과 매칭)
disk:
bus: virtio # 디스크 버스 타입 (virtio: 최적화된 가상화 드라이버)
interfaces:
- name: default # 네트워크 인터페이스 이름 (networks 섹션과 매칭)
masquerade: {} # NAT 방식 네트워킹 사용
resources: # VM에 할당할 리소스
requests: # 최소 필요 리소스
memory: 1Gi # 메모리 요청량
cpu: 1 # CPU 요청량
networks:
- name: default # 인터페이스와 매칭되는 네트워크 정의
pod: {} # 기본 Pod 네트워크 사용
volumes:
- name: rootdisk # 디스크와 매칭되는 볼륨 정의
containerDisk: # 컨테이너 이미지 형태의 디스크
image: quay.io/kubevirt/ubuntu:22.04 # Ubuntu 22.04 이미지 사용
spec.running: true를 false로 변경하고 kubectl apply를 실행하면 VM이 중지됩니다:
# VM의 running 상태를 false로 패치하여 VM 중지
kubectl patch vm lifecycle-demo --type merge -p '{"spec":{"running":false}}'
📌 VM 템플릿 활용하기
대규모 환경에서는 표준화된 VM 템플릿을 사용하는 것이 중요합니다. KubeVirt는 VM 템플릿을 통해 일관된 VM 구성을 제공합니다.
✅ VirtualMachineTemplate 이해하기
VirtualMachineInstancePreset 또는 일반적인 K8s 방식으로 커스텀 리소스를 템플릿화할 수 있습니다.
▶️ VM 템플릿 예시:
apiVersion: kubevirt.io/v1
kind: VirtualMachineInstancePreset
metadata:
name: small-vm # 템플릿 이름
spec:
selector:
matchLabels:
size: small # 이 라벨을 가진 VM에 프리셋 적용
domain:
resources:
requests: # 리소스 요청 설정
memory: 2Gi # 기본 메모리 설정 - 2GB
cpu: 2 # 기본 CPU 설정 - 2 코어
---
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: template-demo # VM 이름
labels:
size: small # 위 템플릿과 매칭되는 라벨 (중요!)
spec:
running: false # 초기 상태는 중지 상태
template:
metadata:
labels:
kubevirt.io/vm: template-demo
size: small # 템플릿 선택자와 매칭되는 라벨 포함 (중요!)
spec:
domain:
devices:
disks:
- name: rootdisk # 디스크 참조 이름
disk:
bus: virtio # 디스크 버스 타입
volumes:
- name: rootdisk # 볼륨 정의
containerDisk:
image: quay.io/kubevirt/ubuntu:22.04 # Ubuntu 22.04 이미지
이 방식으로 small, medium, large와 같은 사전 정의된 크기 템플릿을 만들고 VM에 적용할 수 있습니다.
✅ Common Templates 활용하기
KubeVirt 커뮤니티는 다양한 운영체제에 대한 표준 템플릿 모음인 "Common Templates"를 제공합니다.
# Common Templates 설치 - 다양한 OS 유형별 표준 템플릿 제공
kubectl apply -f https://github.com/kubevirt/common-templates/releases/download/v0.15.0/common-templates.yaml
# 사용 가능한 템플릿 확인 - 기본적으로 openshift 네임스페이스에 설치됨
kubectl get templates -n openshift
Common Templates는 주로 OpenShift 환경을 위해 설계되었지만, 일반 Kubernetes에서도 응용할 수 있습니다.
📌 Live Migration 이해하기
KubeVirt는 VM을 한 노드에서 다른 노드로 다운타임 없이 이동하는 Live Migration 기능을 제공합니다. Docker Desktop 환경에서는 노드가 하나뿐이므로 실제 마이그레이션을 테스트할 수는 없지만, 개념과 기본 설정을 살펴보겠습니다.
✅ Live Migration 개념
Live Migration은 다음과 같은 상황에서 유용합니다:
- 노드 유지보수: 노드 업그레이드/패치 시 VM을 다른 노드로 이동
- 부하 분산: 과부하된 노드에서 VM을 다른 노드로 이동
- 장애 복구: 문제가 있는 노드에서 정상 노드로 VM 이동
✅ Migration 설정
실제 클러스터 환경에서 Live Migration을 활성화하려면 다음과 같은 구성이 필요합니다:
- Feature Gate 활성화:
apiVersion: v1
kind: ConfigMap
metadata:
name: kubevirt-config # KubeVirt 구성용 ConfigMap
namespace: kubevirt # kubevirt 네임스페이스에 생성
labels:
kubevirt.io: "" # KubeVirt 컴포넌트가 인식하는 라벨
data:
feature-gates: "LiveMigration" # Live Migration 기능 활성화 설정
migrations: | # 마이그레이션 관련 세부 설정
parallelMigrationsPerCluster: 5 # 클러스터 전체 동시 마이그레이션 수 제한
parallelOutboundMigrationsPerNode: 2 # 노드별 아웃바운드 마이그레이션 수 제한
bandwidthPerMigration: 64Mi # 마이그레이션당 대역폭 제한 (64MiB/s)
completionTimeoutPerGiB: 800 # 1GiB당 타임아웃 시간(초)
progressTimeout: 150 # 진행 확인 타임아웃 시간(초)
- VM에서 마이그레이션 허용:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: migratable-vm # VM 이름
spec:
running: true # 실행 상태로 시작
template:
spec:
domain:
devices: # ...
# Live Migration을 위한 메모리 설정
memory:
guest: 1Gi # VM에 할당할 메모리 크기
# 그 외 필요한 설정들...
✅ Migration 명령어
멀티노드 환경에서 마이그레이션을 시작하려면:
# VM 마이그레이션 시작 - VM을 다른 적합한 노드로 마이그레이션
kubectl virt migrate <vm-name>
# 마이그레이션 상태 확인 - VirtualMachineInstanceMigration 리소스 조회
kubectl get vmim # VirtualMachineInstanceMigration의 약어
# 마이그레이션 취소 - 진행 중인 마이그레이션 중단
kubectl delete vmim <migration-name>
📌 VM 스케줄링 및 Affinity 관리
KubeVirt VM을 특정 노드에 스케줄링하거나 여러 노드에 분산하는 방법을 알아보겠습니다.
✅ 노드 선택기(NodeSelector) 설정
특정 노드에 VM을 배치하려면 NodeSelector를 사용할 수 있습니다:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: node-selector-demo # VM 이름
spec:
template:
spec:
nodeSelector: # 특정 노드에 VM을 스케줄링하기 위한 설정
kubernetes.io/hostname: worker-node-01 # 특정 노드 이름으로 배치
domain:
# VM 도메인 설정...
✅ Affinity 및 Anti-Affinity 설정
노드 Affinity를 사용하여 VM 배치를 더 세밀하게 제어할 수 있습니다:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: affinity-demo # VM 이름
spec:
template:
spec:
affinity:
nodeAffinity: # 노드 어피니티 설정
requiredDuringSchedulingIgnoredDuringExecution: # 반드시 만족해야 함
nodeSelectorTerms:
- matchExpressions:
- key: node-role.kubernetes.io/compute # 노드 라벨
operator: In # 조건 연산자
values:
- "true" # 매칭될 값
# Pod Anti-Affinity 예시 (같은 애플리케이션의 VM들이 서로 다른 노드에 배치되도록)
podAntiAffinity: # Pod 간 분산 배치 설정
preferredDuringSchedulingIgnoredDuringExecution: # 가능하면 만족
- weight: 100 # 우선순위 가중치 (1-100)
podAffinityTerm:
labelSelector:
matchExpressions:
- key: app # Pod 라벨
operator: In
values:
- web-server # 특정 앱 라벨 값
topologyKey: kubernetes.io/hostname # 분산 기준 (호스트 단위)
domain:
# VM 도메인 설정...
이 설정은 node-role.kubernetes.io/compute=true 라벨이 있는 노드에 VM을 배치하며, 가능하면 app=web-server 라벨이 있는 다른 VM과 같은 노드에 배치하지 않습니다.
✅ Descheduler 활용
장기 실행 중인 클러스터에서는 Kubernetes Descheduler를 통해 VM의 재배치를 자동화할 수 있습니다:
# Descheduler 설치 (Helm 사용) - VM 자동 재분배를 위한 도구
helm repo add descheduler https://kubernetes-sigs.github.io/descheduler/
helm install descheduler descheduler/descheduler --namespace kube-system
Descheduler 정책 예시:
apiVersion: descheduler.k8s.io/v1alpha1
kind: DeschedulerPolicy
metadata:
name: kubevirt-policy # 정책 이름
namespace: kube-system # 시스템 네임스페이스
spec:
strategies:
RemoveDuplicates: # 중복 pod 제거 전략
enabled: true # 활성화 여부
LowNodeUtilization: # 노드 자원 활용도 균형화 전략
enabled: true
params:
nodeResourceUtilizationThresholds:
thresholds: # 저활용 노드 기준 (이하)
cpu: 20 # CPU 사용률 20% 이하
memory: 20 # 메모리 사용률 20% 이하
pods: 20 # Pod 사용률 20% 이하
targetThresholds: # 목표 활용도 (이하)
cpu: 70 # CPU 목표 사용률 70% 이하
memory: 70 # 메모리 목표 사용률 70% 이하
pods: 70 # Pod 목표 사용률 70% 이하
📌 VM의 HA(High Availability) 구성
KubeVirt에서 VM의 고가용성을 구성하는 방법을 알아보겠습니다.
✅ LiveMigration을 통한 기본 HA
LiveMigration은 유지보수 또는 계획된 다운타임 시 고가용성을 제공합니다. 노드 장애 시 자동 복구를 위해서는 추가 설정이 필요합니다.
✅ 런타임 클래스 및 우선순위 설정
VM의 재시작 및 복구 우선순위를 설정할 수 있습니다:
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: high-priority-vm # 우선순위가 높은 VM 이름
spec:
template:
spec:
priorityClassName: high-priority # 우선순위 클래스 지정 (높은 우선순위)
terminationGracePeriodSeconds: 30 # 종료 전 유예 시간(초)
domain:
# VM 도메인 설정...
사전에 PriorityClass를 정의해야 합니다:
apiVersion: scheduling.k8s.io/v1
kind: PriorityClass
metadata:
name: high-priority # 우선순위 클래스 이름
value: 1000000 # 우선순위 값 (높을수록 우선순위 높음)
globalDefault: false # 기본 클래스 여부
description: "This priority class is used for high-priority VMs" # 설명
✅ 자동 노드 재부팅 방지
중요한 VM의 경우 노드 재부팅을 방지하는 Pod Disruption Budget을 설정할 수 있습니다:
apiVersion: policy/v1
kind: PodDisruptionBudget
metadata:
name: vm-pdb # PDB 이름
spec:
minAvailable: 1 # 항상 최소 1개 인스턴스 유지 (중단 제한)
selector: # 대상 Pod 선택
matchLabels:
kubevirt.io/vm: high-priority-vm # 특정 VM에 대한 Pod 선택
📌 로그 및 이벤트 확인 방법
KubeVirt VM 관리 시 로그와 이벤트를 확인하는 방법을 알아보겠습니다.
✅ VM 로그 확인
VM 로그는 virt-launcher Pod를 통해 확인할 수 있습니다:
# VM의 Pod 이름 찾기 - VM을 호스팅하는 virt-launcher Pod 조회
kubectl get pods -l kubevirt.io/vm=<vm-name>
# VM Pod 로그 확인 - compute 컨테이너의 로그 확인 (VM 실행 관련 로그)
kubectl logs <vm-pod-name> -c compute
# VM 직접 콘솔 접속 - VM의 직접 콘솔에 연결 (시리얼 콘솔)
kubectl virt console <vm-name>
✅ VM 이벤트 확인
Kubernetes 이벤트를 통해 VM 상태 변경을 추적할 수 있습니다:
# VM 관련 이벤트 확인 - 특정 VM과 관련된 모든 이벤트 조회
kubectl get events --field-selector involvedObject.name=<vm-name>
# 모든 KubeVirt 이벤트 확인 - kubevirt 관련 모든 이벤트 필터링
kubectl get events | grep kubevirt
✅ KubeVirt 컴포넌트 로그 확인
KubeVirt 컴포넌트 자체의 로그도 문제 해결에 유용합니다:
# virt-controller 로그 - VM 라이프사이클 관리 컴포넌트 로그
kubectl logs -n kubevirt -l kubevirt.io=virt-controller
# virt-api 로그 - KubeVirt API 서버 로그
kubectl logs -n kubevirt -l kubevirt.io=virt-api
# virt-handler 로그 - 각 노드에서 실행되는 VM 관리 에이전트 로그
kubectl logs -n kubevirt -l kubevirt.io=virt-handler
📌 예약 스케줄링 설정
KubeVirt VM의 예약 실행 및 중지를 설정하는 방법을 알아보겠습니다.
✅ CronJob을 활용한 VM 자동화
Kubernetes CronJob을 사용하여 VM의 정기적인 시작/중지를 자동화할 수 있습니다:
apiVersion: batch/v1
kind: CronJob
metadata:
name: start-vm-weekdays # CronJob 이름 - 평일 VM 시작
spec:
schedule: "0 8 * * 1-5" # cron 스케줄 표현식 (평일 오전 8시)
jobTemplate:
spec:
template:
spec:
serviceAccountName: vm-operator # 권한을 가진 서비스 계정
containers:
- name: kubectl # kubectl 명령어 실행용 컨테이너
image: bitnami/kubectl:latest # kubectl 이미지
command: # VM 시작 명령어
- /bin/sh
- -c
- "kubectl virt start scheduled-vm"
restartPolicy: OnFailure # 실패 시 재시작 정책
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: stop-vm-weekdays # CronJob 이름 - 평일 VM 중지
spec:
schedule: "0 18 * * 1-5" # cron 스케줄 표현식 (평일 오후 6시)
jobTemplate:
spec:
template:
spec:
serviceAccountName: vm-operator # 권한을 가진 서비스 계정
containers:
- name: kubectl
image: bitnami/kubectl:latest
command: # VM 중지 명령어
- /bin/sh
- -c
- "kubectl virt stop scheduled-vm"
restartPolicy: OnFailure
이를 위해서는 VM을 시작/중지할 수 있는 권한을 가진 서비스 계정이 필요합니다:
apiVersion: v1
kind: ServiceAccount
metadata:
name: vm-operator # 서비스 계정 이름
namespace: default # 네임스페이스
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: vm-operator # 역할 이름
namespace: default # 네임스페이스
rules:
- apiGroups: ["kubevirt.io"] # KubeVirt API 그룹
resources: ["virtualmachines", "virtualmachines/status"] # 접근 가능 리소스
verbs: ["get", "list", "update", "patch"] # 허용 작업
- apiGroups: ["subresources.kubevirt.io"] # 서브리소스 API 그룹
resources: ["virtualmachines/start", "virtualmachines/stop"] # VM 시작/중지 서브리소스
verbs: ["update"] # 허용 작업
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: vm-operator # 역할 바인딩 이름
namespace: default # 네임스페이스
subjects:
- kind: ServiceAccount # 바인딩 대상 종류
name: vm-operator # 서비스 계정 이름
roleRef:
kind: Role # 참조할 역할 종류
name: vm-operator # 역할 이름
apiGroup: rbac.authorization.k8s.io
✅ 자동 스냅샷 설정
CDI(Containerized Data Importer)를 사용하여 VM 디스크의 정기적인 스냅샷을 생성할 수 있습니다:
apiVersion: snapshot.storage.k8s.io/v1
kind: VolumeSnapshot
metadata:
name: vm-disk-snapshot # 스냅샷 이름
spec:
volumeSnapshotClassName: csi-hostpath-snapclass # 스냅샷 클래스 (CSI 드라이버 지원 필요)
source:
persistentVolumeClaimName: vm-disk-pvc # 대상 PVC 이름
CronJob을 사용하여 이 스냅샷을 정기적으로 생성할 수 있습니다.
Summary
이번 글에서는 KubeVirt에서 VM을 효과적으로 관리하는 방법에 대해 알아보았습니다. 핵심 내용을 요약하면:
- VM 라이프사이클 관리는 kubectl virt 명령어나 spec.running 필드를 통해 가능
- VM 템플릿을 활용하여 일관된 VM 구성 유지 가능
- Live Migration을 통해 다운타임 없이 VM을 다른 노드로 이동 가능
- NodeSelector와, Affinity 설정을 통해 VM 배치 최적화 가능
- PriorityClass, PDB 등을 활용한 VM의 HA 구성 가능
- 로그와 이벤트를 통해 VM 상태 모니터링 가능
- CronJob을 활용한 VM 예약 스케줄링 설정 가능
'Kubernetes Tools > Kubevirt' 카테고리의 다른 글
[KubeVirt Ep. 10] kubevirt 운영 고려사항 | 리소스, 모니터링, 보안 (0) | 2025.03.21 |
---|---|
[KubeVirt Ep.8] 🚀 Multus CNI 연동하기 | VM에 다중 네트워크 붙이기 (0) | 2025.03.21 |
[KubeVirt Ep.7] 🚀 기본 네트워크 설정 | VM에서 외부로 나가기 (0) | 2025.03.21 |
[KubeVirt Ep.6] 🚀 VM의 스토리지 설정 | ephemeral vs persistent (0) | 2025.03.21 |
[KubeVirt Ep.5] 🚀 VM 이미지 다루기 | ContainerDisk와 PVC 이해 및 활용 (0) | 2025.03.21 |