이 글에서는 KubeVirt의 핵심인 VirtualMachine 리소스를 자세히 살펴보고, 기본 템플릿 없이 직접 VM을 생성하는 방법을 알아보겠습니다. VirtualMachine과 VirtualMachineInstance의 관계, 리소스 구조, 그리고 CLI 기반으로 VM을 배포하고 라이프사이클을 관리하는 방법을 실습해 보겠습니다.
📌 VirtualMachine과 VirtualMachineInstance 리소스 이해하기
KubeVirt에는 VM을 정의하고 관리하기 위한 두 가지 주요 리소스가 있습니다: VirtualMachine(VM)과 VirtualMachineInstance(VMI)입니다. 이 두 리소스의 역할과 관계를 명확히 이해하는 것이 중요합니다.
✅ VirtualMachine vs VirtualMachineInstance
VirtualMachine(VM) 리소스는:
- VM의 원하는 상태를 정의하는 선언적 리소스
- VMI의 라이프사이클을 관리 (생성, 삭제, 재시작 등)
- VM 설정이 유지되는 영구적 리소스
- 쿠버네티스 Deployment와 유사한 역할
VirtualMachineInstance(VMI) 리소스는:
- 실제 실행 중인 VM 인스턴스를 나타내는 리소스
- 항상 실행 중인 상태만 표현 (Running 또는 생성 중/종료 중 상태)
- VM이 중지되면 삭제됨
- 쿠버네티스 Pod와 유사한 역할
# VirtualMachine과 VirtualMachineInstance의 관계
apiVersion: kubevirt.io/v1 # KubeVirt API 버전
kind: VirtualMachine # 리소스 종류: VM 정의
metadata:
name: example-vm # VM 이름
spec:
running: true # true면 VMI가 생성됨, false면 VMI가 삭제됨
template: # VMI를 생성하기 위한 템플릿
metadata:
labels:
kubevirt.io/vm: example-vm # VMI에 적용될 레이블
spec: # VMI 스펙 정의 시작
# VM 하드웨어 및 설정... (이 부분은 VMI의 spec과 동일한 구조)
# 이 부분은 실제 VM 인스턴스의 설정을 정의함
VM은 spec.template에 VMI의 정의를 포함하고 있으며, spec.running 필드를 통해 VMI의 생성 및 삭제를 제어합니다.
✅ VM 라이프사이클 상태
VM은 다양한 상태를 가질 수 있으며, 이는 status.printableStatus 필드에서 확인할 수 있습니다:
- Running: VM이 실행 중이며 VMI가 존재함
- Stopped: VM이 중지되었으며 VMI가 존재하지 않음
- Provisioning: VMI가 생성 중이지만 아직 완전히 실행되지 않음
- Terminating: VMI가 종료 중인 상태
- Migrating: VM이 한 노드에서 다른 노드로 마이그레이션되는 중
- Unknown: VM 상태를 확인할 수 없음
▶️ VM과 VMI의 관계 이해: "쿠버네티스에서 Deployment가 Pod의 생명주기를 관리하는 것처럼, KubeVirt에서는 VirtualMachine이 VirtualMachineInstance의 생명주기를 관리합니다. VM을 중지해도 VM 리소스 자체는 계속 존재하므로, 설정이 유지되며 나중에 동일한 구성으로 다시 시작할 수 있습니다."
📌 VM 스펙 상세 분석
VirtualMachine 리소스의 구조를 자세히 살펴보겠습니다. VM 스펙은 하드웨어 리소스, 부팅 옵션, 디스크, 네트워크 등 다양한 설정을 포함합니다.
✅ VM 스펙의 주요 구성 요소
apiVersion: kubevirt.io/v1 # KubeVirt API 버전
kind: VirtualMachine # 리소스 종류: VM 정의
metadata:
name: example-vm # VM 이름
spec:
running: true # VM 실행 여부: true면 시작, false면 중지
runStrategy: Always # 실행 전략(Optional):
# - Always: 항상 실행 유지
# - Manual: 수동 제어
# - RerunOnFailure: 실패 시 재시작
# - Halted: 항상 중지 상태 유지
template: # VMI 템플릿 정의 시작
metadata:
labels: # VMI에 적용될 레이블
kubevirt.io/vm: example-vm # VM 식별 레이블
spec:
domain: # VM 도메인(하드웨어) 설정 시작
cpu:
cores: 2 # CPU 코어 수
sockets: 1 # CPU 소켓 수
threads: 1 # 코어당 스레드 수 (총 vCPU = cores*sockets*threads)
memory:
guest: 2Gi # VM에 할당할 메모리 크기
devices: # 디바이스 정의 섹션
disks: # 디스크 장치 설정
- name: rootdisk # 디스크 이름 (volumes 섹션과 매핑됨)
disk:
bus: virtio # 디스크 버스 유형: 성능 최적화된 virtio 사용
- name: cloudinitdisk # cloud-init 설정용 디스크
disk:
bus: virtio # 디스크 버스 유형
interfaces: # 네트워크 인터페이스 설정
- name: default # 인터페이스 이름 (networks 섹션과 매핑됨)
masquerade: {} # NAT 네트워킹 사용 (외부 통신 가능)
# 선택적 설정
features: # 하드웨어 기능 설정
acpi: {} # ACPI 지원 활성화
firmware: # 부팅 설정
bootloader:
efi: {} # UEFI 부팅 사용
machine:
type: q35 # 머신 유형: 최신 PC 아키텍처 에뮬레이션
networks: # VM 네트워크 정의
- name: default # 인터페이스 이름과 일치해야 함
pod: {} # Pod 네트워크 사용 (기본 쿠버네티스 네트워크)
volumes: # VM 볼륨 정의
- name: rootdisk # 디스크 이름과 일치해야 함
persistentVolumeClaim:
claimName: my-vm-rootdisk # PVC 이름: 미리 생성된 PVC 사용
- name: cloudinitdisk # cloud-init 디스크 이름
cloudInitNoCloud: # cloud-init 설정 유형
userData: | # VM 초기화 스크립트
#cloud-config
password: password # 기본 비밀번호 설정
chpasswd: { expire: False } # 비밀번호 만료 비활성화
✅ 도메인(domain) 섹션 상세 분석
spec.template.spec.domain 섹션은 VM의 하드웨어 스펙을 정의하는 부분으로, libvirt 도메인 XML과 유사한 구조를 가집니다:
- CPU 설정:
- cores, sockets, threads: VM에 할당되는 CPU 리소스 구성
- dedicatedCpuPlacement: CPU 핀닝 (전용 CPU 코어 할당)
- model: CPU 모델 (host-model, host-passthrough 등)
- 메모리 설정:
- guest: VM에 할당되는 메모리 양
- hugepages: 대용량 페이지 사용 여부
- 디바이스 설정:
- disks: VM의 디스크 장치 설정
- interfaces: 네트워크 인터페이스 설정
- inputs: 마우스, 키보드 등의 입력 장치
- graphics: VNC, SPICE 등의 그래픽 디스플레이
- gpu: GPU 장치 설정
- 기능(features) 설정:
- acpi: ACPI 지원
- apic: APIC 지원
- hyperv: Hyper-V 기능 지원 (Windows VM용)
- smm: 시스템 관리 모드 지원
✅ 볼륨(volumes)과 네트워크(networks) 섹션
volumes 섹션은 VM에 연결할 스토리지를 정의하며, 다양한 유형이 있습니다:
- persistentVolumeClaim: 쿠버네티스 PVC 사용
- containerDisk: 컨테이너 이미지에 포함된 디스크 이미지
- cloudInitNoCloud: cloud-init 설정 데이터
- dataVolume: CDI(Containerized Data Importer)를 통한 데이터 볼륨
- emptyDisk: 임시 빈 디스크
networks 섹션은 VM 네트워크 연결을 정의합니다:
- pod: 기본 Pod 네트워크 사용
- multus: Multus CNI를 통한 다중 네트워크 인터페이스
▶️ VM 구성 팁: "VM 구성에서 devices.disks와 volumes의 이름이 일치해야 하며, 마찬가지로 devices.interfaces와 networks의 이름도 일치해야 합니다. 이는 장치와 해당 리소스를 연결하는 방식입니다."
📌 나만의 VM 직접 생성하기
이제 기본 템플릿 없이 VM을 직접 정의하고 생성해 보겠습니다. 알파인 리눅스 기반의 간단한 VM을 만들어 보겠습니다.
✅ Alpine Linux VM 정의
먼저 alpine-vm.yaml 파일을 만들어 다음 내용을 작성합니다:
apiVersion: kubevirt.io/v1 # KubeVirt API 버전
kind: VirtualMachine # 리소스 종류
metadata:
name: alpine-vm # VM 이름
annotations:
description: "Alpine Linux VM" # VM 설명(메타데이터)
spec:
running: true # 생성 즉시 VM 실행
template:
metadata:
labels:
kubevirt.io/vm: alpine-vm # VM 식별 레이블
spec:
domain: # VM 하드웨어 정의 시작
cpu:
cores: 1 # 1개의 CPU 코어 할당
devices:
disks: # 디스크 장치 정의
- name: containerdisk # 컨테이너 디스크(OS 이미지)
disk:
bus: virtio # virtio 버스 사용(성능 최적화)
- name: cloudinitdisk # cloud-init 설정 디스크
disk:
bus: virtio
interfaces: # 네트워크 인터페이스 정의
- name: default
masquerade: {} # NAT 모드 네트워킹(외부 통신 가능)
rng: {} # 난수 발생기 추가(부팅 속도 향상)
resources:
requests:
memory: 256Mi # 256MB 메모리 요청
networks: # 네트워크 정의
- name: default # 인터페이스 이름과 일치
pod: {} # 기본 Pod 네트워크 사용
volumes: # 볼륨 정의
- name: containerdisk # 컨테이너 디스크 정의
containerDisk:
image: quay.io/kubevirt/alpine-container-disk-demo:latest # Alpine Linux 이미지
- name: cloudinitdisk # cloud-init 볼륨 정의
cloudInitNoCloud:
userData: |- # cloud-init 설정
#cloud-config
password: alpine # 기본 비밀번호 설정
chpasswd: { expire: False } # 비밀번호 만료 비활성화
ssh_pwauth: True # SSH 비밀번호 인증 허용
✅ VM 배포 및 상태 확인
# VM 생성
$ kubectl apply -f alpine-vm.yaml
virtualmachine.kubevirt.io/alpine-vm created
# YAML 파일을 적용하여 VM 리소스 생성
# VM 상태 확인
$ kubectl get vm
NAME AGE STATUS READY
alpine-vm 10s Running True
# VM이 Running 상태이고 Ready가 True인지 확인
# STATUS: VM의 현재 상태, READY: VM이 정상적으로 실행 중인지 여부
# 상세 정보 확인
$ kubectl describe vm alpine-vm
# VM 리소스의 상세 정보 확인
# 이벤트, 상태, 구성 등 모든 정보가 표시됨
주목할 만한 부분:
- containerdisk: 컨테이너 이미지로 패키징된 Alpine Linux 디스크 이미지
- cloudinitdisk: cloud-init 설정으로 기본 사용자 비밀번호 설정
- masquerade: NAT 네트워킹 모드 (Pod 외부와 통신 가능)
- rng: 난수 발생기 추가 (VM 부팅 시 필요한 엔트로피 제공)
✅ VM 콘솔 접속
# VM 콘솔 접속
$ virtctl console alpine-vm
# virtctl 명령을 사용하여 VM의 직렬 콘솔에 접속
# 이 명령은 VM의 직렬 콘솔 출력을 표시하고 입력을 VM으로 전달함
# 로그인 (사용자: root, 비밀번호: alpine)
alpine-vm login: root
Password: alpine
# VM 내부에 로그인 (cloud-init에서 설정한 인증 정보 사용)
# 시스템 정보 확인
# hostname -f
alpine-vm
# VM의 호스트명 확인
# uname -a
Linux alpine-vm 5.15.0-generic #1 SMP Alpine 5.15 x86_64 Linux
# 커널 버전 및 시스템 정보 확인
# 네트워크 정보 확인
# ip addr show
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP
link/ether 52:54:00:XX:XX:XX brd ff:ff:ff:ff:ff:ff
inet 10.X.X.X/24 brd 10.X.X.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::XX:XX:XX:XX/64 scope link
valid_lft forever preferred_lft forever
# 네트워크 인터페이스 정보 확인
# eth0: Pod 네트워크로부터 IP 주소를 할당받은 인터페이스
# 종료
# exit
▶️ 기본 Alpine VM 특징: "Alpine Linux는 매우 가벼운 리눅스 배포판으로, 컨테이너 이미지 크기가 작고 부팅이 빠르기 때문에 테스트용 VM으로 적합합니다. 기본적인 패키지 관리는 apk 명령어를 사용합니다."
📌 다양한 VM 구성 예제
이제 다양한 사용 사례에 맞는 VM 구성 예제를 살펴보겠습니다.
✅ Ubuntu VM 직접 생성하기
Ubuntu VM을 위한 ubuntu-vm.yaml 파일을 만들어 보겠습니다:
apiVersion: kubevirt.io/v1 # KubeVirt API 버전
kind: VirtualMachine # 리소스 종류
metadata:
name: ubuntu-vm # VM 이름
annotations:
description: "Ubuntu Server VM" # VM 설명
spec:
running: true # 생성 즉시 실행
template:
metadata:
labels:
kubevirt.io/vm: ubuntu-vm # VM 식별 레이블
spec:
domain:
cpu:
cores: 2 # 2개 CPU 코어 할당(Ubuntu는 리소스가 더 필요함)
devices:
disks:
- name: containerdisk
disk:
bus: virtio # virtio 버스 사용(성능 최적화)
- name: cloudinitdisk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {} # NAT 모드 네트워킹
rng: {} # 난수 발생기 추가(부팅 속도 향상)
resources:
requests:
memory: 1Gi # 1GB 메모리 할당(Ubuntu는 더 많은 메모리 필요)
networks:
- name: default
pod: {} # 기본 Pod 네트워크 사용
volumes:
- name: containerdisk
containerDisk:
image: quay.io/kubevirt/ubuntu-container-disk-demo:22.04 # Ubuntu 22.04 이미지
- name: cloudinitdisk
cloudInitNoCloud:
userData: |- # cloud-init 설정
#cloud-config
hostname: ubuntu-vm # 호스트명 설정
user: ubuntu # 사용자 이름
password: ubuntu # 사용자 비밀번호
chpasswd: { expire: False } # 비밀번호 만료 비활성화
ssh_pwauth: True # SSH 비밀번호 인증 허용
package_update: true # 패키지 저장소 업데이트
packages: # 자동 설치할 패키지 목록
- qemu-guest-agent # VM 모니터링 및 관리를 위한 에이전트
runcmd: # 초기 실행 명령어
- systemctl enable qemu-guest-agent # 에이전트 활성화
- systemctl start qemu-guest-agent # 에이전트 시작
이 Ubuntu VM은:
- 2개의 CPU 코어와 1GB 메모리 할당 (Alpine보다 많은 리소스)
- cloud-init을 통한 사용자 및 패키지 설정
- QEMU 게스트 에이전트 설치 및 활성화 (VM 모니터링 및 관리 개선)
✅ 개인화된 VM 구성: 스토리지와 SSH 키
지속적인 데이터 스토리지와 SSH 키 인증을 사용하는 VM 예제입니다:
apiVersion: kubevirt.io/v1 # KubeVirt API 버전
kind: VirtualMachine # 리소스 종류
metadata:
name: personal-vm # VM 이름
spec:
running: true # 생성 즉시 실행
template:
metadata:
labels:
kubevirt.io/vm: personal-vm # VM 식별 레이블
spec:
domain:
cpu:
cores: 2 # CPU 코어 수
sockets: 1 # CPU 소켓 수
threads: 1 # 코어당 스레드 수
memory:
guest: 2Gi # 2GB 메모리 할당
devices:
disks:
- name: rootdisk # 루트 디스크(OS)
disk:
bus: virtio # virtio 버스 사용
- name: datadisk # 데이터 저장용 추가 디스크
disk:
bus: virtio
- name: cloudinitdisk # cloud-init 설정 디스크
disk:
bus: virtio
interfaces:
- name: default
masquerade: {} # NAT 모드 네트워킹
networks:
- name: default
pod: {} # 기본 Pod 네트워크 사용
volumes:
- name: rootdisk # 루트 디스크 볼륨 정의
containerDisk:
image: quay.io/kubevirt/fedora-container-disk-demo:latest # Fedora 이미지
- name: datadisk # 데이터 디스크 볼륨 정의
persistentVolumeClaim:
claimName: personal-vm-data # 미리 생성된 PVC 사용
# 이 PVC는 VM이 삭제되어도 유지됨
- name: cloudinitdisk # cloud-init 볼륨 정의
cloudInitNoCloud:
userData: |- # cloud-init 설정
#cloud-config
hostname: personal-vm # 호스트명 설정
ssh_authorized_keys: # SSH 공개 키 추가(비밀번호 대신 키 인증)
- ssh-rsa AAAAB3NzaC1y...YOUR_SSH_PUBLIC_KEY
runcmd: # 초기 실행 명령어
- mkdir -p /mnt/data # 데이터 디스크 마운트 포인트 생성
- echo '/dev/vdb /mnt/data ext4 defaults 0 0' >> /etc/fstab # 자동 마운트 설정
- mount -a # 모든 디스크 마운트
이 VM 구성은:
- SSH 키 인증을 통한 보안 강화 (비밀번호 대신 키 사용)
- PVC를 사용한 영구 데이터 디스크 연결 (VM 재시작/삭제 후에도 데이터 유지)
- cloud-init을 통한 디스크 마운트 자동화 (VM 부팅 시 자동 설정)
✅ 고급 VM 설정: 부팅 옵션 및 하드웨어 기능
특수 부팅 옵션과 하드웨어 기능을 사용하는 고급 VM 예제입니다:
apiVersion: kubevirt.io/v1 # KubeVirt API 버전
kind: VirtualMachine # 리소스 종류
metadata:
name: advanced-vm # VM 이름
spec:
running: true # 생성 즉시 실행
template:
metadata:
labels:
kubevirt.io/vm: advanced-vm # VM 식별 레이블
spec:
domain:
cpu:
cores: 4 # 4개 CPU 코어 할당
model: host-passthrough # 호스트 CPU 모델 그대로 사용
# 호스트 CPU 기능을 VM에 직접 전달(최상의 성능)
dedicatedCpuPlacement: true # CPU 핀닝 활성화
# VM의 vCPU를 특정 물리 CPU에 고정하여 성능 향상
memory:
guest: 4Gi # 4GB 메모리 할당
features: # 하드웨어 기능 설정
acpi: {} # ACPI 지원 활성화(전원 관리)
apic: {} # APIC 지원 활성화(인터럽트 제어)
smm:
enabled: true # 시스템 관리 모드 활성화
firmware: # 펌웨어/부팅 설정
bootloader: # 부트로더 설정
efi: # UEFI 부팅 사용
secure: true # 보안 부팅 활성화(부팅 이미지 검증)
machine:
type: q35 # 머신 타입: 최신 QEMU PC 모델
# 향상된 I/O 및 현대적 디바이스 지원
devices:
disks:
- name: rootdisk
disk:
bus: virtio # virtio 버스 사용
- name: cloudinitdisk
disk:
bus: virtio
interfaces:
- name: default
masquerade: {} # NAT 모드 네트워킹
volumes:
- name: rootdisk
containerDisk:
image: quay.io/kubevirt/fedora-container-disk-demo:latest # Fedora 이미지
- name: cloudinitdisk
cloudInitNoCloud:
userData: |- # cloud-init 설정
#cloud-config
hostname: advanced-vm # 호스트명 설정
이 VM은:
- 호스트 CPU 모델 직접 사용 (최대 성능, 호스트의 모든 CPU 기능 활용)
- 전용 CPU 코어 할당 (CPU 핀닝, 다른 워크로드와 CPU 공유 없음)
- EFI 펌웨어 및 보안 부팅 지원 (UEFI 기반 보안 부팅)
- Q35 머신 타입 사용 (최신 QEMU 머신 모델, PCIe 지원)
▶️ VM 구성 선택 팁: "VM 구성은 워크로드 요구사항에 맞게 조정해야 합니다. 개발/테스트 환경에서는 가벼운 VM과 ContainerDisk가 적합하며, 프로덕션 환경에서는 영구 스토리지와 적절한 리소스 할당이 중요합니다."
📌 VM 라이프사이클 관리
VM의 라이프사이클을 virtctl 명령어와 YAML 수정을 통해 관리하는 방법을 알아보겠습니다.
✅ virtctl을 이용한 VM 제어
virtctl CLI 도구를 사용하면 다양한 VM 작업을 쉽게 수행할 수 있습니다:
# VM 시작
$ virtctl start alpine-vm
VM alpine-vm was scheduled to start
# VM을 시작하는 명령어
# VM이 중지 상태에서 실행 상태로 전환됨
# VM 중지
$ virtctl stop alpine-vm
VM alpine-vm was scheduled to stop
# VM을 중지하는 명령어
# VM이 실행 상태에서 중지 상태로 전환됨
# VM 구성은 유지되지만 VMI는 삭제됨
# VM 재시작
$ virtctl restart alpine-vm
VM alpine-vm was scheduled to restart
# VM을 재시작하는 명령어
# 실행 중인 VMI를 삭제하고 새 VMI를 생성함
# VM 일시 중지
$ virtctl pause alpine-vm
VM alpine-vm was scheduled to pause
# VM을 일시 중지하는 명령어
# VM 실행은 유지되지만 CPU 실행이 일시 정지됨
# VM 재개
$ virtctl unpause alpine-vm
VM alpine-vm was scheduled to unpause
# 일시 중지된 VM을 다시 실행하는 명령어
# VM 콘솔 접속
$ virtctl console alpine-vm
# VM의 직렬 콘솔에 접속하는 명령어
# 부팅 메시지 및 텍스트 콘솔 접근 가능
# VNC 콘솔 접속
$ virtctl vnc alpine-vm
# VM의 그래픽 콘솔(VNC)에 접속하는 명령어
# GUI 환경이 있는 VM에 유용
# 포트 포워딩 설정
$ virtctl port-forward alpine-vm 22:22
# VM의 특정 포트를 로컬 포트로 포워딩하는 명령어
# 예: VM의 22번 포트(SSH)를 로컬 22번 포트로 연결
✅ YAML 수정을 통한 VM 제어
VM의 실행 상태는 YAML의 spec.running 필드를 수정하여 제어할 수도 있습니다:
# VM 시작 (running: true로 설정)
$ kubectl patch vm alpine-vm --type merge -p '{"spec":{"running":true}}'
virtualmachine.kubevirt.io/alpine-vm patched
# VM의 running 상태를 true로 변경하는 명령어
# 패치(patch) 방식으로 특정 필드만 수정
# VM 중지 (running: false로 설정)
$ kubectl patch vm alpine-vm --type merge -p '{"spec":{"running":false}}'
virtualmachine.kubevirt.io/alpine-vm patched
# VM의 running 상태를 false로 변경하는 명령어
# VM이 중지되고 VMI가 삭제됨
✅ runStrategy 설정을 통한 고급 VM 라이프사이클 관리
VM의 라이프사이클을 더 세밀하게 제어하려면 runStrategy 필드를 사용할 수 있습니다:
spec:
runStrategy: Always # VM이 항상 실행 상태 유지
# 노드 장애나 시스템 재시작 후에도 자동으로 재시작
# 또는
runStrategy: RerunOnFailure # 오류 발생 시 자동 재시작
# 정상 종료 시에는 재시작하지 않음
# 또는
runStrategy: Manual # 수동 시작/중지만 허용
# virtctl이나 API 호출로만 제어 가능
# 또는
runStrategy: Halted # VM이 항상 중지 상태 유지
# VM을 정의만 하고 실행하지 않을 때 사용
이 설정을 적용하려면:
# runStrategy 설정 변경
$ kubectl patch vm alpine-vm --type merge -p '{"spec":{"runStrategy":"RerunOnFailure"}}'
# VM의 재시작 정책을 변경하는 명령어
# 'RerunOnFailure'로 설정하면 비정상 종료 시 자동으로 재시작됨
▶️ VM 관리 베스트 프랙티스: "프로덕션 환경에서는 runStrategy: RerunOnFailure를 사용하여 VM이 비정상 종료 시 자동으로 재시작되도록 하는 것이 좋습니다. 또한 리소스 관리를 위해 중요하지 않은 VM은 사용하지 않을 때 중지(virtctl stop)하는 습관을 들이는 것이 좋습니다."
✅ VM 삭제 및 정리
실습이 끝난 후 VM 리소스를 정리하는 방법입니다:
# VM 삭제
$ kubectl delete vm alpine-vm
virtualmachine.kubevirt.io "alpine-vm" deleted
# VM 리소스를 완전히 삭제하는 명령어
# VM 구성 및 관련 VMI가 모두 삭제됨
# 주의: PVC 등의 영구 볼륨은 별도로 삭제해야 함
# 모든 VM 삭제
$ kubectl delete vm --all
# 현재 네임스페이스의 모든 VM 삭제
# 대규모 정리 작업 시 유용
📌 VM에 메타데이터 및 태그 추가
VM에 메타데이터와 태그를 추가하여 관리 및 구성을 더 효율적으로 할 수 있습니다.
✅ 레이블과 어노테이션 추가
apiVersion: kubevirt.io/v1
kind: VirtualMachine
metadata:
name: labeled-vm # VM 이름
labels: # 레이블 정의(검색 및 필터링에 사용)
environment: development # 환경 구분 레이블
app: webserver # 애플리케이션 유형 레이블
team: devops # 담당 팀 레이블
annotations: # 어노테이션 정의(비검색용 메타데이터)
description: "Web server VM for development" # VM 설명
owner: "john.doe@example.com" # 소유자 정보
version: "1.0.0" # 버전 정보
spec:
# VM 스펙...
이런 방식으로 레이블을 추가하면 쿠버네티스의 레이블 셀렉터를 사용하여 VM을 필터링하고 그룹화할 수 있습니다:
# 개발 환경의 VM만 조회
$ kubectl get vm -l environment=development
# 레이블 셀렉터를 사용한 VM 필터링
# environment=development 레이블이 있는 VM만 표시
# 웹 서버 VM만 조회
$ kubectl get vm -l app=webserver
# app=webserver 레이블이 있는 VM만 표시
# 여러 조건 조합
$ kubectl get vm -l 'environment=development,app=webserver'
# 여러 레이블 조건을 조합한 필터링
# 개발 환경의 웹 서버 VM만 표시
✅ 태그 기반 VM 관리
VM에 설정된 레이블과 어노테이션은 다양한 관리 작업에 활용할 수 있습니다:
# 개발 환경의 모든 VM 중지
$ kubectl get vm -l environment=development -o name | xargs -I {} virtctl stop {}
# 1. 개발 환경 VM 목록 조회
# 2. 이름만 추출(-o name)
# 3. 각 VM에 대해 virtctl stop 명령 실행
# 특정 팀의 VM에 리소스 제한 적용
$ kubectl get vm -l team=devops -o name | xargs -I {} kubectl patch {} --type merge -p '{"spec":{"template":{"spec":{"domain":{"resources":{"requests":{"memory":"1Gi"}}}}}}}}'
# 1. devops 팀 VM 목록 조회
# 2. 이름만 추출
# 3. 각 VM에 메모리 요청을 1Gi로 패치
▶️ 메타데이터 관리 팁: "VM에 환경(dev/staging/prod), 역할(web/db/cache), 소유자, 비용 센터 등의 메타데이터를 일관되게 추가하면 클라우드 네이티브 방식으로 VM을 관리할 수 있습니다. 이는 특히 많은 수의 VM을 관리할 때 유용합니다."
📌 VM 모니터링 및 디버깅
VM의 상태를 모니터링하고 문제를 진단하는 방법을 알아보겠습니다.
✅ VM 상태 및 이벤트 확인
VM에 문제가 생겼을 때 첫 번째로 확인해야 할 것은 VM의 상태와 관련 이벤트입니다:
# VM 상태 자세히 확인
$ kubectl get vm alpine-vm -o yaml
# VM 리소스의 전체 YAML 출력
# 모든 설정 및 상태 정보 확인 가능
# VM 상태 요약 확인
$ kubectl get vm alpine-vm -o jsonpath='{.status.printableStatus}'
Running
# jsonpath를 사용하여 특정 필드만 추출
# printableStatus 필드는 VM의 현재 상태를 간결하게 표시
# VM 관련 이벤트 확인
$ kubectl get events | grep alpine-vm
# 쿠버네티스 이벤트 중 VM 이름이 포함된 이벤트만 필터링
# VM 생성, 시작, 오류 등의 이벤트 확인 가능
✅ VM 로그 확인
VM을 실행하는 virt-launcher Pod의 로그를 확인하여 문제를 진단할 수 있습니다:
# VM의 virt-launcher Pod 찾기
$ kubectl get pods | grep virt-launcher-alpine-vm
virt-launcher-alpine-vm-abc123 1/1 Running 0 10m
# VM을 실행하는 virt-launcher Pod 조회
# Pod 로그 확인
$ kubectl logs virt-launcher-alpine-vm-abc123
# Pod의 기본 컨테이너 로그 확인
# VM 시작 및 실행 과정의 로그 메시지 확인
# 특정 컨테이너 로그 확인
$ kubectl logs virt-launcher-alpine-vm-abc123 -c compute
# 'compute' 컨테이너의 로그만 확인
# VM 실행과 관련된 세부 로그 확인
✅ VM 콘솔 로그 확인
VM의 직렬 콘솔 로그를 확인하면 부팅 과정이나 VM 내부의 문제를 진단하는 데 도움이 됩니다:
# 직렬 콘솔 로그 확인
$ virtctl console alpine-vm
# VM의 직렬 콘솔에 접속
# 부팅 메시지 및 커널 로그 확인 가능
# 이미 실행 중인 VM의 로그 확인
$ virtctl console alpine-vm --follow
# --follow 옵션을 사용하여 실시간 로그 스트림 확인
# 부팅 과정이나 시스템 로그를 실시간으로 모니터링
▶️ 문제 해결 팁: "VM이 시작되지 않거나 예상대로 작동하지 않을 경우, 먼저 VM 이벤트와 virt-launcher Pod 로그를 확인하세요. 가장 흔한 문제로는 리소스 부족, 볼륨 마운트 오류, 네트워크 구성 오류 등이 있습니다."
📌 Summary
이 글에서는 KubeVirt의 핵심인 VirtualMachine 리소스에 대해 알아보고, 직접 VM을 생성하고 관리하는 방법을 실습해보았습니다. 주요 내용을 요약하면:
- VirtualMachine(VM)과 VirtualMachineInstance(VMI)는 각각 쿠버네티스의 Deployment와 Pod와 유사한 관계를 가집니다.
- VM 스펙은 CPU, 메모리, 디스크, 네트워크 등 다양한 하드웨어 구성을 정의합니다.
- ContainerDisk, PersistentVolumeClaim, DataVolume 등 다양한 스토리지 옵션을 활용할 수 있습니다.
- virtctl을 통해 VM의 시작, 중지, 재시작, 콘솔 접속 등 다양한 작업을 수행할 수 있습니다.
- 레이블과 어노테이션을 활용하여 VM을 효과적으로 관리하고 그룹화할 수 있습니다.
- VM 모니터링 및 디버깅을 위해 이벤트, 로그, 콘솔 출력 등 다양한 도구를 활용할 수 있습니다
'Kubernetes Tools > Kubevirt' 카테고리의 다른 글
[KubeVirt Ep.6] 🚀 VM의 스토리지 설정 | ephemeral vs persistent (0) | 2025.03.21 |
---|---|
[KubeVirt Ep.5] 🚀 VM 이미지 다루기 | ContainerDisk와 PVC 이해 및 활용 (0) | 2025.03.21 |
[KubeVirt Ep.3] 🚀 kubevirt 설치하기 | Docker Desktop으로 실습 환경 구성 (0) | 2025.03.21 |
[KubeVirt Ep.2] 🚀 kubevirt 아키텍처 이해하기 | 주요 구성요소와 동작 흐름 (0) | 2025.03.21 |
[KubeVirt Ep.1] 🚀 kubevirt란 무엇인가? | VM과 컨테이너의 공존을 위한 해법 (0) | 2025.03.21 |