Skip to content

Commit

Permalink
Adding support of UDN usage (#156)
Browse files Browse the repository at this point in the history
* Adding support of UDN usage

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

* updating the README.md with the latest features

* Using a dedicated struct to extract NetworkData from the annotations
  • Loading branch information
capolrik authored Nov 23, 2024
1 parent bb7c578 commit 0d99424
Show file tree
Hide file tree
Showing 4 changed files with 109 additions and 3 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,19 @@ Flags:
--clean Clean-up resources created by k8s-netperf (default true)
--json Instead of human-readable output, return JSON to stdout
--local Run network performance tests with Server-Pods/Client-Pods on the same Node
--vm Launch Virtual Machines instead of pods for client/servers
--across Place the client and server across availability zones
--all Run all tests scenarios - hostNet and podNetwork (if possible)
--debug Enable debug log
--udn Create and use a UDN called 'udn-l2-primary' as a primary network.
--prom string Prometheus URL
--uuid string User provided UUID
--search string OpenSearch URL, if you have auth, pass in the format of https://user:pass@url:port
--index string OpenSearch Index to save the results to, defaults to k8s-netperf
--metrics Show all system metrics retrieved from prom
--tcp-tolerance float Allowed %diff from hostNetwork to podNetwork, anything above tolerance will result in k8s-netperf exiting 1. (default 10)
--version k8s-netperf version
--csv Archive results, cluster and benchmark metrics in CSV files (default true)
-h, --help help for k8s-netperf


Expand Down
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 bool
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 udn {
s.Udn = true
// Create a dynamic client
dynClient, err := dynamic.NewForConfig(rconfig)
if err != nil {
log.Error(err)
}
s.DClient = dynClient
err = k8s.DeployL2Udn(dynClient)
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 @@ -381,6 +399,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 @@ -391,6 +410,11 @@ func executeWorkload(nc config.Config,
} else {
serverIP = s.NetperfService.Spec.ClusterIP
}
} else if s.Udn {
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 @@ -488,6 +512,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().BoolVar(&udn, "udn", false, "Create and use a UDN called 'udn-l2-primary' as primary network.")
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 bool
ServerNodeInfo metrics.NodeInfo
ClientNodeInfo metrics.NodeInfo
Client apiv1.PodList
Expand Down
76 changes: 76 additions & 0 deletions pkg/k8s/kubernetes.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@ package k8s

import (
"context"
"encoding/json"
"fmt"
"net"
"strings"

"github.com/cloud-bulldozer/k8s-netperf/pkg/config"
Expand All @@ -12,9 +14,12 @@ import (
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 @@ -44,6 +49,13 @@ type ServiceParams struct {
DataPorts []int32
}

type PodNetworksData struct {
IPAddresses []string `json:"ip_addresses"`
MacAddress string `json:"mac_address"`
GatewayIPs []string `json:"gateway_ips"`
Role string `json:"role"`
}

const sa string = "netperf"
const namespace string = "netperf"

Expand Down Expand Up @@ -72,6 +84,7 @@ const clientAcrossRole = "client-across"
const hostNetServerRole = "host-server"
const hostNetClientRole = "host-client"
const k8sNetperfImage = "quay.io/cloud-bulldozer/k8s-netperf:latest"
const udnName = "udn-l2-primary"

// BuildInfra will create the infra for the SUT
func BuildInfra(client *kubernetes.Clientset) error {
Expand Down Expand Up @@ -124,6 +137,40 @@ func BuildInfra(client *kubernetes.Clientset) error {
return nil
}

// Create a User Defined Network for the tests
func DeployL2Udn(dynamicClient *dynamic.DynamicClient) error {
log.Infof("Deploying L2 Primary UDN in the NS : %s", namespace)
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 {
return 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 +496,35 @@ 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 root map[string]json.RawMessage
err := json.Unmarshal([]byte(podNetworksJson), &root)
if err != nil {
fmt.Println("Error unmarshalling JSON:", err)
return "", err
}
//
var udnData PodNetworksData
err = json.Unmarshal(root["netperf/"+udnName], &udnData)
if err != nil {
return "", err
}
// Extract the IPv4 address
var ipv4 net.IP
for _, ip := range udnData.IPAddresses {
if strings.Contains(ip, ".") { // Check if it's an IPv4 address
ipv4, _, err = net.ParseCIDR(ip)
if err != nil {
return "", err
}
}
}
return ipv4.String(), 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 0d99424

Please sign in to comment.