Skip to content

Commit ec72f81

Browse files
committed
fix: prevent GC from deleting KubeVirt VM interfaces
The garbage collector introduced in PR kubeovn#5789 incorrectly identifies KubeVirt VM interfaces as 'lost' and deletes them, breaking network connectivity for VMs within ~60 seconds of creation. Root cause: For KubeVirt VMs, the pod_name in OVS external_ids is set to the VM name (e.g., 'ubuntu-vm-br'), not the launcher pod name (e.g., 'virt-launcher-ubuntu-vm-br-xyz'). When gcInterfaces() tries to look up the pod by the VM name, it fails and incorrectly deletes the interface. Solution: When a pod is not found by direct lookup, check if it might be a KubeVirt VM by searching for launcher pods with the label 'vm.kubevirt.io/name' matching the pod_name from OVS. If a matching launcher pod exists, keep the interface instead of deleting it. This fix maintains backward compatibility with non-KubeVirt pods while preventing false-positive deletions for KubeVirt VMs. Signed-off-by: dnugmanov <damir_nug@mail.ru>
1 parent 1633e46 commit ec72f81

File tree

2 files changed

+25
-6
lines changed

2 files changed

+25
-6
lines changed

pkg/daemon/controller.go

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ import (
1616
v1 "k8s.io/api/core/v1"
1717
k8serrors "k8s.io/apimachinery/pkg/api/errors"
1818
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
19+
"k8s.io/apimachinery/pkg/labels"
1920
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2021
"k8s.io/apimachinery/pkg/util/wait"
2122
"k8s.io/client-go/informers"
@@ -722,12 +723,29 @@ func (c *Controller) gcInterfaces() {
722723
continue
723724
}
724725

725-
if _, err := c.podsLister.Pods(podNamespace).Get(podName); err != nil {
726-
if k8serrors.IsNotFound(err) {
727-
klog.Infof("pod %s/%s not found, delete ovs interface %s", podNamespace, podName, iface)
728-
if err := ovs.CleanInterface(iface); err != nil {
729-
klog.Errorf("failed to clean ovs interface %s: %v", iface, err)
730-
}
726+
if _, err := c.podsLister.Pods(podNamespace).Get(podName); err != nil && k8serrors.IsNotFound(err) {
727+
// Pod not found by name. Check if this might be a KubeVirt VM.
728+
// For KubeVirt VMs, the pod_name in OVS external_ids is set to the VM name (not the launcher pod name).
729+
// The actual launcher pod has the label 'vm.kubevirt.io/name' with the VM name as value.
730+
// Try to find launcher pods by this label.
731+
selector := labels.SelectorFromSet(map[string]string{util.KubeVirtVMNameLabel: podName})
732+
launcherPods, listErr := c.podsLister.Pods(podNamespace).List(selector)
733+
if listErr != nil {
734+
klog.Errorf("failed to list launcher pods for vm %s/%s: %v", podNamespace, podName, listErr)
735+
continue
736+
}
737+
738+
// If we found launcher pod(s) for this VM, keep the interface
739+
if len(launcherPods) > 0 {
740+
klog.V(5).Infof("found %d launcher pod(s) for vm %s/%s, keeping ovs interface %s",
741+
len(launcherPods), podNamespace, podName, iface)
742+
continue
743+
}
744+
745+
// No pod and no launcher pod found - safe to delete
746+
klog.Infof("pod %s/%s not found, delete ovs interface %s", podNamespace, podName, iface)
747+
if err := ovs.CleanInterface(iface); err != nil {
748+
klog.Errorf("failed to clean ovs interface %s: %v", iface, err)
731749
}
732750
}
733751
}

pkg/util/const.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ const (
112112
VpcDNSNameLabel = "ovn.kubernetes.io/vpc-dns"
113113
QoSLabel = "ovn.kubernetes.io/qos"
114114
NodeNameLabel = "ovn.kubernetes.io/node-name"
115+
KubeVirtVMNameLabel = "vm.kubevirt.io/name"
115116
NetworkPolicyLogAnnotation = "ovn.kubernetes.io/enable_log"
116117
NetworkPolicyEnforcementAnnotation = "ovn.kubernetes.io/network_policy_enforcement"
117118
ACLActionsLogAnnotation = "ovn.kubernetes.io/log_acl_actions"

0 commit comments

Comments
 (0)