Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(core): hide target pod during migration via cilium label #609

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -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"
8 changes: 8 additions & 0 deletions images/virt-artifact/patches/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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).
Loading