Skip to content

필사 모드: VMI spec가 libvirt domain XML로 변환되는 과정

한국어
0%
정확도 0%
💡 왼쪽 원문을 읽으면서 오른쪽에 따라 써보세요. Tab 키로 힌트를 받을 수 있습니다.
원문 렌더가 준비되기 전까지 텍스트 가이드로 표시합니다.

들어가며

사용자는 Kubernetes 스타일의 YAML로 VMI를 선언한다. 하지만 libvirt와 QEMU는 결국 domain spec와 XML을 기준으로 guest를 실행한다. 따라서 KubeVirt에는 두 세계를 이어 주는 굉장히 중요한 translation layer가 필요하다. 이 역할을 하는 것이 `pkg/virt-launcher/virtwrap/converter`다.

이 글의 핵심 질문은 다음이다. **VMI spec는 어떤 과정을 거쳐 libvirt domain XML이 되는가?**

변환은 단순한 필드 복사가 아니다

처음에는 `spec.domain.cpu`가 libvirt CPU 필드로, `spec.domain.devices.disks`가 libvirt disk 항목으로 그냥 복사될 것 같지만 실제로는 훨씬 복잡하다.

이유는 세 가지다.

1. guest 장치 이름을 계산해야 한다

2. Pod에 준비된 실제 디스크 경로를 찾아야 한다

3. architecture, virtio 모델, security, migration 같은 정책을 반영해야 한다

즉 converter는 serialization layer가 아니라 **정책 포함 변환기**다.

핵심 진입점

`converter.go`에서 가장 중요한 함수 이름은 다음과 같다.

- `Convert_v1_VirtualMachineInstance_To_api_Domain`

- `Convert_v1_Disk_To_api_Disk`

- `Convert_v1_Volume_To_api_Disk`

- `Convert_v1_BlockSize_To_api_BlockIO`

이 이름만 봐도 구조가 보인다. 최종 목표는 VMI 전체를 `api.Domain`으로 바꾸는 것이고, 그 안에서 디스크, 볼륨, 블록 IO, CPU, NIC 같은 세부 변환 함수가 계층적으로 호출된다.

`api.Domain`은 왜 중요한가

KubeVirt 내부에서 `api.Domain`은 guest 실행을 위한 canonical intermediate representation에 가깝다.

- VMI는 Kubernetes 친화적 선언 모델

- `api.Domain`은 libvirt 친화적 실행 모델

- 최종적으로 XML marshal이 가능

즉 `api.Domain`은 KubeVirt 내부의 "가상화 중간 언어" 같은 역할을 한다.

디스크 변환에서 어떤 일이 일어나는가

`Convert_v1_Disk_To_api_Disk`를 보면 단순 매핑 이상의 일이 많이 보인다.

1. bus별 device name 계산

virtio, scsi, cdrom, lun에 따라 target bus와 device name이 달라진다. 예를 들어 virtio 디스크는 `vda`, `vdb` 식의 guest-visible 이름이 생긴다.

2. PCI 주소 검증

일부 bus 타입에서는 PCI 주소를 임의로 주는 것이 허용되지 않는다. converter는 이 제약을 적용한다.

3. shareable, cache, discard 정책 적용

shared disk면 cache가 `none`이어야 하는 등 단순히 YAML 값을 복사하는 것이 아니라 조합 제약을 검사한다.

4. boot order와 alias 추가

guest boot 순서와 사용자 정의 alias도 변환 과정에서 만들어진다.

즉 디스크 하나만 봐도 converter는 단순 serializer가 아니라 guest 하드웨어 모델 설계기다.

볼륨과 디스크는 왜 분리되어 있는가

Kubernetes 쪽 VMI spec에는 `volumes`와 `disks`가 분리되어 있다.

- `volumes`: 데이터 소스가 무엇인가

- `disks`: guest에 어떤 장치로 붙일 것인가

예를 들면 같은 PVC라도:

- 일반 디스크로 붙일 수도 있고

- cdrom처럼 노출할 수도 있고

- boot order를 다르게 줄 수도 있다

converter는 이 둘을 결합해 "이 소스를 guest에 어떤 libvirt disk로 붙일지"를 계산한다.

변환 컨텍스트가 필요한 이유

`convertertypes.ConverterContext` 계열을 보면 converter가 단순 stateless 함수가 아니라는 것을 알 수 있다. 변환에는 주변 문맥이 필요하다.

대표적으로 다음 정보가 context에 들어간다.

- architecture

- allowEmulation 여부

- hypervisor device availability

- block PVC 또는 filesystem PVC 여부

- disk creator

- launch security 옵션

- virtio transitional 모델 사용 여부

이 말은 같은 VMI spec라도 **노드 아키텍처와 실행 환경에 따라 최종 domain spec가 달라질 수 있다**는 뜻이다.

네트워크와 CPU도 같은 방식으로 변환된다

디스크만 특별한 것이 아니다. NIC, CPU topology, NUMA, launch security, EFI, iothreads 같은 것들도 converter가 libvirt domain representation으로 변환한다.

예를 들어:

- dedicated CPU면 pinning 관련 필드가 달라진다

- launch security가 켜지면 IOMMU 같은 옵션이 들어간다

- architecture가 바뀌면 machine type과 일부 장치 표현이 바뀐다

즉 converter는 guest 하드웨어 구성 전체를 책임진다.

domain XML은 언제 완성되는가

실무적으로는 다음 순서로 이해하면 된다.

1. VMI spec를 읽는다.

2. converter가 `api.Domain`을 만든다.

3. 필요하면 hook이나 sidecar가 domain spec를 추가 수정한다.

4. 최종 domain XML이 libvirt에 전달된다.

5. libvirt가 이를 기반으로 QEMU를 실행한다.

따라서 "어떤 guest 장치가 왜 그렇게 보이는가"를 알고 싶다면 거의 항상 converter부터 읽어야 한다.

migration 시에는 왜 domain XML을 다시 다루는가

`live-migration-source.go`에는 `migratableDomXML` 같은 로직이 있다. migration 때는 source domain XML을 그대로 넘기면 안 되고, 메타데이터를 정리하거나 target 쪽 경로에 맞게 디스크 파일 경로를 수정해야 할 수 있다.

즉 domain XML은 launch 직전 한 번만 중요한 것이 아니라:

- 초기 boot 시

- migration 시

- 일부 hotplug와 target 준비 시

여러 단계에서 계속 핵심 데이터 구조로 사용된다.

왜 이 레이어가 디버깅의 핵심인가

많은 문제는 YAML과 QEMU 사이의 어딘가에서 생긴다. 그 중간이 바로 converter다.

이런 문제를 설명해 준다

- 왜 guest 디스크 이름이 예상과 다를까

- 왜 특정 옵션 조합이 거부될까

- 왜 virtio 대신 다른 모델이 들어갔을까

- 왜 migration 시 디스크 경로를 다시 바꾸는가

만약 launcher Pod는 살아 있고 libvirt define 단계에서 실패한다면, converter 결과가 가장 먼저 의심해야 할 대상이다.

자주 하는 오해

오해 1: VMI spec는 거의 libvirt XML과 같다

아니다. VMI spec는 Kubernetes 선언 모델이고, libvirt XML은 하이퍼바이저 실행 모델이다. 둘 사이에는 KubeVirt가 해석해야 할 정책이 많다.

오해 2: 디스크는 volume 경로만 맞으면 끝이다

아니다. bus, boot order, discard, cache, reservation, block size 같은 guest-visible 속성이 모두 중요하다.

오해 3: converter는 launch 때 한 번만 중요하다

아니다. migration과 hotplug, target 준비 과정에서도 domain spec와 XML 변형이 다시 중요해진다.

마무리

KubeVirt의 converter는 VMI spec를 libvirt domain model로 번역하는 가장 중요한 중간 계층이다. 이 레이어는 단순 필드 복사가 아니라, guest 하드웨어 모델, 실행 환경, 보안 옵션, migration 제약을 함께 반영한다. 그래서 KubeVirt를 깊게 이해하려면 controller 다음에 꼭 읽어야 할 패키지가 바로 `pkg/virt-launcher/virtwrap/converter`다.

다음 글에서는 이 변환 결과가 실제 스토리지 소스와 어떻게 만나며, PVC, DataVolume, container disk, hotplug 디스크가 guest에 어떤 경로로 붙는지 살펴보겠다.

현재 단락 (1/73)

사용자는 Kubernetes 스타일의 YAML로 VMI를 선언한다. 하지만 libvirt와 QEMU는 결국 domain spec와 XML을 기준으로 guest를 실행한다. 따라서 ...

작성 글자: 0원문 글자: 3,523작성 단락: 0/73