Skip to content

Commit 72a6520

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: Damir Nugmanov <damir_nug@mail.ru> Signed-off-by: dnugmanov <damir_nug@mail.ru>
1 parent 1633e46 commit 72a6520

File tree

2 files changed

+24
-6
lines changed

2 files changed

+24
-6
lines changed

pkg/daemon/controller.go

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import (
1515
"github.com/scylladb/go-set/strset"
1616
v1 "k8s.io/api/core/v1"
1717
k8serrors "k8s.io/apimachinery/pkg/api/errors"
18+
"k8s.io/apimachinery/pkg/labels"
1819
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1920
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
2021
"k8s.io/apimachinery/pkg/util/wait"
@@ -722,12 +723,28 @@ 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+
}
736+
737+
// If we found launcher pod(s) for this VM, keep the interface
738+
if len(launcherPods) > 0 {
739+
klog.V(5).Infof("found %d launcher pod(s) for vm %s/%s, keeping ovs interface %s",
740+
len(launcherPods), podNamespace, podName, iface)
741+
continue
742+
}
743+
744+
// No pod and no launcher pod found - safe to delete
745+
klog.Infof("pod %s/%s not found, delete ovs interface %s", podNamespace, podName, iface)
746+
if err := ovs.CleanInterface(iface); err != nil {
747+
klog.Errorf("failed to clean ovs interface %s: %v", iface, err)
731748
}
732749
}
733750
}

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)