diff --git a/images/virt-artifact/patches/030-hide-target-pod-during-migration-via-cilium-label.patch b/images/virt-artifact/patches/030-hide-target-pod-during-migration-via-cilium-label.patch new file mode 100644 index 000000000..8865d2c67 --- /dev/null +++ b/images/virt-artifact/patches/030-hide-target-pod-during-migration-via-cilium-label.patch @@ -0,0 +1,80 @@ +diff --git a/pkg/virt-controller/watch/migration.go b/pkg/virt-controller/watch/migration.go +index 28d6636b36..26780d2810 100644 +--- a/pkg/virt-controller/watch/migration.go ++++ b/pkg/virt-controller/watch/migration.go +@@ -713,6 +713,8 @@ func (c *MigrationController) createTargetPod(migration *virtv1.VirtualMachineIn + } + } + ++ templatePod.Labels[virtv1.HiddenMigrationPodLabel] = "" ++ + key := controller.MigrationKey(migration) + c.podExpectations.ExpectCreations(key, 1) + pod, err := c.clientset.CoreV1().Pods(vmi.GetNamespace()).Create(context.Background(), templatePod, v1.CreateOptions{}) +@@ -1249,6 +1251,18 @@ func (c *MigrationController) sync(key string, migration *virtv1.VirtualMachineI + + if migrationFinalizedOnVMI := vmi.Status.MigrationState != nil && vmi.Status.MigrationState.MigrationUID == migration.UID && + vmi.Status.MigrationState.EndTimestamp != nil; migrationFinalizedOnVMI { ++ if vmi.Status.MigrationState.Completed { ++ vmiConditionManager := controller.NewVirtualMachineInstanceConditionManager() ++ ++ if !vmiConditionManager.HasCondition(vmi, virtv1.VirtualMachineInstanceVCPUChange) && ++ !vmiConditionManager.HasConditionWithStatus(vmi, virtv1.VirtualMachineInstanceMemoryChange, k8sv1.ConditionTrue) { ++ err := enableNetworkAccessibility(pod, c.clientset) ++ if err != nil { ++ log.Log.Reason(err).Error("Failed to enable target pod accessibility via network, please report a bug") ++ } ++ } ++ } ++ + return nil + } + +@@ -1370,6 +1384,34 @@ func (c *MigrationController) sync(key string, migration *virtv1.VirtualMachineI + return nil + } + ++func enableNetworkAccessibility(pod *k8sv1.Pod, virtClient kubecli.KubevirtClient) error { ++ if pod == nil { ++ return errors.New("got nil pod to enable network accessibility") ++ } ++ ++ // 1. Do nothing if its accessibility is already enabled. ++ if _, exists := pod.Labels[virtv1.HiddenMigrationPodLabel]; !exists { ++ return nil ++ } ++ ++ // 2. Remove special label from the pod to make it accessible via network. ++ patchSet := patch.New( ++ patch.WithTest(fmt.Sprintf("/metadata/labels/%s", patch.EscapeJSONPointer(virtv1.HiddenMigrationPodLabel)), ""), ++ patch.WithRemove(fmt.Sprintf("/metadata/labels/%s", patch.EscapeJSONPointer(virtv1.HiddenMigrationPodLabel))), ++ ) ++ patchBytes, err := patchSet.GeneratePayload() ++ if err != nil { ++ return fmt.Errorf("generate patch: %w", err) ++ } ++ ++ _, err = virtClient.CoreV1().Pods(pod.Namespace).Patch(context.Background(), pod.Name, types.JSONPatchType, patchBytes, v1.PatchOptions{}) ++ if err != nil { ++ return fmt.Errorf("apply patch to remove pod label %s: %w", virtv1.HiddenMigrationPodLabel, err) ++ } ++ ++ return nil ++} ++ + func (c *MigrationController) setupVMIRuntimeUser(vmi *virtv1.VirtualMachineInstance) *patch.PatchSet { + patchSet := patch.New() + if !c.clusterConfig.RootEnabled() { +diff --git a/staging/src/kubevirt.io/api/core/v1/types.go b/staging/src/kubevirt.io/api/core/v1/types.go +index 66c9374784..8e75551630 100644 +--- a/staging/src/kubevirt.io/api/core/v1/types.go ++++ b/staging/src/kubevirt.io/api/core/v1/types.go +@@ -875,6 +875,8 @@ const ( + // Machine Instance migration job. Needed because with CRDs we can't use field + // selectors. Used on VirtualMachineInstance. + MigrationTargetNodeNameLabel string = "kubevirt.io/migrationTargetNodeName" ++ // A special label allows to control access to the pod network. When a pod has this special label, network packets cannot reach it. ++ HiddenMigrationPodLabel string = "network.deckhouse.io/hidden-pod" + // This annotation indicates that a migration is the result of an + // automated evacuation + EvacuationMigrationAnnotation string = "kubevirt.io/evacuationMigration" diff --git a/images/virt-artifact/patches/README.md b/images/virt-artifact/patches/README.md index a5052fbd2..7272c6362 100644 --- a/images/virt-artifact/patches/README.md +++ b/images/virt-artifact/patches/README.md @@ -126,3 +126,11 @@ Kubevirt uses flags to detect firmware combinations in converter. EFIConfiguration, so we can't set needed files directly. But there is combination for SEV: OVFM_CODE.cc.fd + OVMF_VARS.fd that works for Linux, because OVFM_CODE.cc.fd is actually a symlink to OVFM_CODE.fd. So, we set true for the second flag to force OVFM_CODE.cc.fd + OVMF_VARS.fd for non-Windows virtual machines._ + +#### `030-hide-target-pod-during-migration-via-cilium-label.patch` + +During the VM migration process, two pods with the same address are created and packets are randomly delivered to them. +To force delivery of packages to only one VM pod, the special label `network.deckhouse.io/hidden-pod` for target pod were added. +When the migration completes, the label is removed and the target pod becomes accessible via network. + +d8-cni-cilium ensures that once the label is removed from the target pod, only the target pod remains accessible over the network (while the source pod does not).