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

Adding support of UDN usage #156

Merged
merged 3 commits into from
Nov 23, 2024
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
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 @@ -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 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 @@ -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().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
Loading