From 38345a348fa46cae692a1c68291c88366063f7c1 Mon Sep 17 00:00:00 2001 From: Charles CAPORALI Date: Fri, 6 Dec 2024 16:10:05 +0100 Subject: [PATCH] Adding support of UDN l2 primary using VMs Needed to be run on 4.18 and above, uses the l2bridge binding method --- pkg/k8s/kubernetes.go | 16 +++++++++++---- pkg/k8s/kubevirt.go | 47 +++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/pkg/k8s/kubernetes.go b/pkg/k8s/kubernetes.go index 047943a..24d7acb 100644 --- a/pkg/k8s/kubernetes.go +++ b/pkg/k8s/kubernetes.go @@ -6,6 +6,7 @@ import ( "fmt" "net" "strings" + "time" "github.com/cloud-bulldozer/k8s-netperf/pkg/config" log "github.com/cloud-bulldozer/k8s-netperf/pkg/logging" @@ -151,8 +152,9 @@ func DeployL2Udn(dynamicClient *dynamic.DynamicClient) error { "spec": map[string]interface{}{ "topology": "Layer2", "layer2": map[string]interface{}{ - "role": "Primary", - "subnets": []string{"10.0.0.0/24", "2001:db8::/60"}, + "role": "Primary", + "subnets": []string{"10.0.0.0/24"}, + "ipamLifecycle": "Persistent", }, }, }, @@ -557,7 +559,7 @@ func ExtractUdnIp(s config.PerfScenarios) (string, error) { // launchServerVM will create the ServerVM with the specific node and pod affinity. func launchServerVM(perf *config.PerfScenarios, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity) error { - _, err := CreateVMServer(perf.KClient, serverRole, serverRole, *podAff, *nodeAff, perf.Bridge) + _, err := CreateVMServer(perf.KClient, serverRole, serverRole, *podAff, *nodeAff, perf.Bridge, perf.Udn) if err != nil { return err } @@ -565,6 +567,9 @@ func launchServerVM(perf *config.PerfScenarios, name string, podAff *corev1.PodA if err != nil { return err } + log.Infof("⏰ Waiting 120s for the Server VMI to be ready...") + //wait for the VMI to be ready + time.Sleep(120 * time.Second) if strings.Contains(name, "host") { perf.ServerHost, err = GetPods(perf.ClientSet, fmt.Sprintf("app=%s", serverRole)) if err != nil { @@ -582,7 +587,7 @@ func launchServerVM(perf *config.PerfScenarios, name string, podAff *corev1.PodA // launchClientVM will create the ClientVM with the specific node and pod affinity. func launchClientVM(perf *config.PerfScenarios, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity) error { - host, err := CreateVMClient(perf.KClient, perf.ClientSet, perf.DClient, name, podAff, nodeAff, perf.Bridge) + host, err := CreateVMClient(perf.KClient, perf.ClientSet, perf.DClient, name, podAff, nodeAff, perf.Bridge, perf.Udn) if err != nil { return err } @@ -591,6 +596,9 @@ func launchClientVM(perf *config.PerfScenarios, name string, podAff *corev1.PodA if err != nil { return err } + log.Infof("⏰ Waiting 200s for the client VMI to be ready...") + //wait for the VMI to be ready + time.Sleep(200 * time.Second) if strings.Contains(name, "host") { perf.ClientHost, err = GetPods(perf.ClientSet, fmt.Sprintf("app=%s", name)) if err != nil { diff --git a/pkg/k8s/kubevirt.go b/pkg/k8s/kubevirt.go index f96addf..e8613e2 100644 --- a/pkg/k8s/kubevirt.go +++ b/pkg/k8s/kubevirt.go @@ -158,7 +158,7 @@ func exposeService(client *kubernetes.Clientset, dynamicClient *dynamic.DynamicC // CreateVMClient takes in the affinity rules and deploys the VMI func CreateVMClient(kclient *kubevirtv1.KubevirtV1Client, client *kubernetes.Clientset, - dyn *dynamic.DynamicClient, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity, bridge bool) (string, error) { + dyn *dynamic.DynamicClient, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity, bridge bool, udn bool) (string, error) { label := map[string]string{ "app": name, "role": name, @@ -232,6 +232,27 @@ runcmd: ethernets: eth1: addresses: [ 10.10.10.12/24 ]` + } else if udn { + interfaces = []v1.Interface{ + { + Name: "primary-l2-net", + Binding: &v1.PluginBinding{ + Name: "l2bridge", + }, + }, + } + networks = []v1.Network{ + { + Name: "primary-l2-net", + NetworkSource: v1.NetworkSource{ + Pod: &v1.PodNetwork{}, + }, + }, + } + netData = `version: 2 +ethernets: + eth0: + dhcp4: true` } _, err = CreateVMI(kclient, name, label, b64.StdEncoding.EncodeToString([]byte(data)), *podAff, *nodeAff, interfaces, networks, b64.StdEncoding.EncodeToString([]byte(netData))) if err != nil { @@ -250,7 +271,7 @@ ethernets: // CreateVMServer will take the pod and node affinity and deploy the VMI func CreateVMServer(client *kubevirtv1.KubevirtV1Client, name string, role string, podAff corev1.PodAntiAffinity, - nodeAff corev1.NodeAffinity, bridge bool) (*v1.VirtualMachineInstance, error) { + nodeAff corev1.NodeAffinity, bridge bool, udn bool) (*v1.VirtualMachineInstance, error) { label := map[string]string{ "app": name, "role": role, @@ -275,6 +296,7 @@ ssh_deletekeys: false password: fedora chpasswd: { expire: False } runcmd: + - export HOME=/home/fedora - dnf install -y --nodocs uperf iperf3 git ethtool - dnf install -y --nodocs automake gcc bc lksctp-tools-devel texinfo --enablerepo=* - git clone https://github.com/HewlettPackard/netperf.git @@ -325,6 +347,27 @@ runcmd: ethernets: eth1: addresses: [ 10.10.10.14/24 ]` + } else if udn { + interfaces = []v1.Interface{ + { + Name: "primary-l2-net", + Binding: &v1.PluginBinding{ + Name: "l2bridge", + }, + }, + } + networks = []v1.Network{ + { + Name: "primary-l2-net", + NetworkSource: v1.NetworkSource{ + Pod: &v1.PodNetwork{}, + }, + }, + } + netData = `version: 2 +ethernets: + eth0: + dhcp4: true` } return CreateVMI(client, name, label, b64.StdEncoding.EncodeToString([]byte(data)), podAff, nodeAff, interfaces, networks, b64.StdEncoding.EncodeToString([]byte(netData))) }