Skip to content

Commit

Permalink
Adding support of UDN usage
Browse files Browse the repository at this point in the history
Using the UDN ip from the Server pod annotations. Service and IPv6 are not supported
Using --udn option create a UserDefinedNetwork object on the netperf ns
  • Loading branch information
capolrik committed Nov 4, 2024
1 parent 3771765 commit 9b0192f
Show file tree
Hide file tree
Showing 3 changed files with 89 additions and 3 deletions.
31 changes: 28 additions & 3 deletions cmd/k8s-netperf/k8s-netperf.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ var (
netperf bool
iperf3 bool
uperf bool
udn string
acrossAZ bool
full bool
vm bool
Expand Down Expand Up @@ -151,19 +152,36 @@ var rootCmd = &cobra.Command{
os.Exit(1)
}

if vm {
s.VM = true
if len(udn) > 1 {
s.Udn = udn
// Create a dynamic client
dynClient, err := dynamic.NewForConfig(rconfig)
if err != nil {
log.Error(err)
}
s.DClient = dynClient
err = k8s.DeployL2Udn(dynClient, udn)
if err != nil {
log.Error(err)
os.Exit(1)
}
}

if vm {
s.VM = true
// Create a dynamic client
if s.DClient == nil {
dynClient, err := dynamic.NewForConfig(rconfig)
if err != nil {
log.Error(err)
}
s.DClient = dynClient
}
kclient, err := kubevirtv1.NewForConfig(rconfig)
if err != nil {
log.Error(err)
}
s.KClient = kclient
s.DClient = dynClient
}

// Build the SUT (Deployments)
Expand Down Expand Up @@ -374,6 +392,7 @@ func executeWorkload(nc config.Config,
hostNet bool,
driverName string, virt bool) result.Data {
serverIP := ""
var err error
Client := s.Client
var driver drivers.Driver
if nc.Service {
Expand All @@ -384,6 +403,11 @@ func executeWorkload(nc config.Config,
} else {
serverIP = s.NetperfService.Spec.ClusterIP
}
} else if len(s.Udn) > 1 {
serverIP, err = k8s.ExtractUdnIp(s)
if err != nil {
log.Fatal(err)
}
} else {
if hostNet {
serverIP = s.ServerHost.Items[0].Status.PodIP
Expand Down Expand Up @@ -481,6 +505,7 @@ func main() {
rootCmd.Flags().BoolVar(&acrossAZ, "across", false, "Place the client and server across availability zones")
rootCmd.Flags().BoolVar(&full, "all", false, "Run all tests scenarios - hostNet and podNetwork (if possible)")
rootCmd.Flags().BoolVar(&debug, "debug", false, "Enable debug log")
rootCmd.Flags().StringVar(&udn, "udn", "", "Create and use a UDN using this name if provided.")
rootCmd.Flags().StringVar(&promURL, "prom", "", "Prometheus URL")
rootCmd.Flags().StringVar(&id, "uuid", "", "User provided UUID")
rootCmd.Flags().StringVar(&searchURL, "search", "", "OpenSearch URL, if you have auth, pass in the format of https://user:pass@url:port")
Expand Down
1 change: 1 addition & 0 deletions pkg/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ type PerfScenarios struct {
Configs []Config
VM bool
VMHost string
Udn string
ServerNodeInfo metrics.NodeInfo
ClientNodeInfo metrics.NodeInfo
Client apiv1.PodList
Expand Down
60 changes: 60 additions & 0 deletions pkg/k8s/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,21 @@ import (
"fmt"
"strings"

"encoding/json"

"github.com/cloud-bulldozer/k8s-netperf/pkg/config"
log "github.com/cloud-bulldozer/k8s-netperf/pkg/logging"
"github.com/cloud-bulldozer/k8s-netperf/pkg/metrics"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
v1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/labels"
"k8s.io/apimachinery/pkg/runtime/schema"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
"k8s.io/utils/pointer"
)
Expand Down Expand Up @@ -124,6 +129,39 @@ func BuildInfra(client *kubernetes.Clientset) error {
return nil
}

// Create a User Defined Network for the tests
func DeployL2Udn(dynamicClient *dynamic.DynamicClient, udnName string) error {
udn := &unstructured.Unstructured{
Object: map[string]interface{}{
"apiVersion": "k8s.ovn.org/v1",
"kind": "UserDefinedNetwork",
"metadata": map[string]interface{}{
"name": udnName,
"namespace": "netperf",
},
"spec": map[string]interface{}{
"topology": "Layer2",
"layer2": map[string]interface{}{
"role": "Primary",
"subnets": []string{"10.0.0.0/24", "2001:db8::/60"},
},
},
},
}

// Specify the GVR for UDN
gvr := schema.GroupVersionResource{
Group: "k8s.ovn.org",
Version: "v1",
Resource: "userdefinednetworks",
}
_, err := dynamicClient.Resource(gvr).Namespace(namespace).Create(context.TODO(), udn, metav1.CreateOptions{})
if err != nil {
log.Fatalf("Failed to create UDN: %v", err)
}
return nil
}

// BuildSUT Build the k8s env to run network performance tests
func BuildSUT(client *kubernetes.Clientset, s *config.PerfScenarios) error {
var netperfDataPorts []int32
Expand Down Expand Up @@ -449,6 +487,28 @@ func BuildSUT(client *kubernetes.Clientset, s *config.PerfScenarios) error {
return nil
}

// Extract the UDN Ip address of a pod from the annotations - Support only ipv4
func ExtractUdnIp(s config.PerfScenarios) (string, error) {
podNetworksJson := s.Server.Items[0].Annotations["k8s.ovn.org/pod-networks"]
var podNetworks map[string]interface{}
err := json.Unmarshal([]byte(podNetworksJson), &podNetworks)
if err != nil {
return "", err
}
UdnJson := podNetworks[namespace+"/"+s.Udn].(map[string]interface{})
UdnIpAddreses := UdnJson["ip_addresses"].([]interface{})
// Extract the IPv4 address
var ipv4 string
for _, ip := range UdnIpAddreses {
ipStr := ip.(string)
if strings.Contains(ipStr, ".") { // Check if it's an IPv4 address
ipv4 = strings.Split(ipStr, "/")[0] // Extract the IP address part before the subnet
break
}
}
return ipv4, nil
}

// 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)
Expand Down

0 comments on commit 9b0192f

Please sign in to comment.