===== VM deployment -- confirmed live trace ===== Device: ''c86eddc2-9a2f-4a0e-a761-25e70e7cbb89''\\ App Instance UUID: ''01859d42-b9c5-48f4-a7c3-d40be41b5877''\\ Network Instance: ''60321c32-0825-478c-905f-d9a8f698ff20'' (Switch type, eth0)\\ Image volume: ''cbd8bf0c-3683-4f99-912c-92a81442cf40'' (20Gi Longhorn) ==== Phase timeline (confirmed live) ==== 15:06:52 → Pending VMI created by zedkube in k3s 15:06:53 → Scheduling KubeVirt scheduler running 15:07:11 → Scheduled placed on node tf-demo-adv-en-1 15:07:15 → Running VM booted **Total time: 23 seconds from VMI creation to running.** ==== EVE host side (confirmed) ==== ^ Pubsub object ^ Path ^ State ^ | AppInstanceConfig | ''/run/zedagent/AppInstanceConfig/01859d42...json'' | Present | | AppNetworkStatus | ''/run/zedrouter/AppNetworkStatus/01859d42...json'' | ''Activated: true'' | | VolumeStatus | ''/run/volumemgr/VolumeStatus/cbd8bf0c...#0.json'' | Ready | | DomainStatus | ''/run/domainmgr/DomainStatus/01859d42...json'' | Present | | CloudInit disk | ''/run/domainmgr/cloudinit/01859d42...cidata'' | 374KB | ==== k3s objects created (confirmed) ==== ^ Object ^ Name ^ Namespace ^ Detail ^ | ''VirtualMachineInstanceReplicaSet'' | ''tf-stnd-atl-vm-1-01859-0'' | ''eve-kube-app'' | Owner of the VMI -- zedkube creates VMIRS not VM | | ''VirtualMachineInstance'' | ''tf-stnd-atl-vm-1-01859-0kpr7l'' | ''eve-kube-app'' | Running · node: tf-demo-adv-en-1 | | ''PersistentVolumeClaim'' | ''cbd8bf0c...-pvc-0'' | ''eve-kube-app'' | 20Gi · RWO · Block mode · Longhorn | | ''NetworkAttachmentDefinition'' | ''network-instance-attachment'' | ''eve-kube-app'' | Bootstrap NAD -- eve-bridge CNI | ==== Key finding: VMIRS not VM ==== ''zedkube'' creates a ''VirtualMachineInstanceReplicaSet'' (VMIRS), not a ''VirtualMachine'' or bare ''VirtualMachineInstance''. The VMI is owned by the VMIRS. This is why ''kubectl get vms -n eve-kube-app'' returns nothing while ''kubectl get vmis -n eve-kube-app'' shows the running instance. kubectl get vmirs -n eve-kube-app # the actual object zedkube creates kubectl get vmis -n eve-kube-app # the running instance owned by VMIRS kubectl get vms -n eve-kube-app # empty -- EVE does not use VirtualMachine objects ==== Key finding: single bootstrap NAD ==== EVE does NOT create a separate ''NetworkAttachmentDefinition'' per Network Instance. It uses the single bootstrap NAD ''network-instance-attachment'' created at cluster initialisation. The ''eve-bridge'' CNI plugin handles NI routing at runtime using context passed by EVE -- not via separate NAD objects per NI. This corrects the earlier assumption that a NAD would be created per NI on app deploy. ==== VM spec (confirmed from kubectl) ==== === CPU and memory === ^ Field ^ Value ^ | CPU cores | 2 | | CPU model | ''host-model'' | | Machine type | ''pc-q35-rhel9.6.0'' (KubeVirt Q35) | | Memory guest | 2Gi | | Memory maxGuest | 8Gi (hotplug capable) | | QoS class | Burstable | === Disk layout === ^ Disk ^ Target ^ Type ^ Source ^ Size ^ | ''disk1'' | ''vda'' | Longhorn PVC · virtio bus | ''cbd8bf0c...-pvc-0'' | 20Gi Block | | ''disk2'' | ''sda'' | hostDisk · SATA CDROM · read-only | ''/run/domainmgr/cloudinit/01859d42...cidata'' | 374KB | ''disk1'' is the VM boot disk -- a Longhorn PVC in Block mode (not filesystem).\\ ''disk2'' is the cloud-init config disk -- written by ''domainmgr'' on the host and mounted directly into the VMI via KubeVirt ''hostDisk''. This means cloud-init config is generated by the EVE pillar layer, not by Kubernetes. === Network === networks: - multus: networkName: network-instance-attachment # bootstrap NAD name: net1 interfaces: - bridge: {} # bridge mode = Switch NI (L2) macAddress: "02:11:22:33:44:55" # EVE-assigned MAC name: net1 podInterfaceName: pod6c270ef2f25 # Multus VIF on the pod linkState: up # confirmed UP infoSource: domain, multus-status # confirmed by both KubeVirt AND Multus ''infoSource: domain, multus-status'' means both the QEMU domain and Multus independently confirm the interface is up and connected. ''VifList: null'' in ''AppNetworkStatus'' confirms Switch NI behaviour -- EVE does not assign or track the VM's IP address. The VM gets its IP from the upstream network on ''eth0''. ==== Node affinity ==== The VMI has a strong node affinity preference (weight 100) for ''tf-demo-adv-en-1'': affinity: nodeAffinity: preferredDuringSchedulingIgnoredDuringExecution: - preference: matchExpressions: - key: kubernetes.io/hostname operator: In values: - tf-demo-adv-en-1 weight: 100 EVE pins VMs to specific nodes via node affinity. This is a preference not a requirement -- KubeVirt can schedule elsewhere if the preferred node is unavailable. ==== EVE domain name label ==== labels: App-Domain-Name: 01859d42-b9c5-48f4-a7c3-d40be41b5877.1.1 Format: ''..'' -- EVE's internal domain name scheme carried into k8s as a label on the VMI. ==== Migration status ==== ^ Type ^ Status ^ Reason ^ | Live migration | Not possible | PVC is ''ReadWriteOnce'' -- not shared across nodes | | Storage live migration | Possible | ''StorageLiveMigratable: true'' | | Migration method | ''BlockMigration'' | Copies block device across nodes | | Migration transport | ''Unix'' | Local Unix socket | Live migration requires ''ReadWriteMany'' PVCs. EVE uses ''ReadWriteOnce'' Longhorn volumes by default which means VMs cannot be live migrated without reconfiguration. ==== How to inspect a running VM ==== # k3s side kubectl get vmirs -n eve-kube-app kubectl get vmis -n eve-kube-app kubectl get vmis -n eve-kube-app -o yaml kubectl get pvc -n eve-kube-app kubectl describe vmi -n eve-kube-app # EVE host side cat /run/domainmgr/DomainStatus/.json | jq '{State, VifList, DiskList}' cat /run/zedrouter/AppNetworkStatus/.json | jq ls -lh /run/domainmgr/cloudinit/ See also: [[eve-k:how-vm-is-created:nad|NAD - NetworkAttachmentDefinition explained]]