Skip to content

Commit 0d99424

Browse files
authored
Adding support of UDN usage (#156)
* 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
1 parent bb7c578 commit 0d99424

File tree

4 files changed

+109
-3
lines changed

4 files changed

+109
-3
lines changed

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,15 +70,19 @@ Flags:
7070
--clean Clean-up resources created by k8s-netperf (default true)
7171
--json Instead of human-readable output, return JSON to stdout
7272
--local Run network performance tests with Server-Pods/Client-Pods on the same Node
73+
--vm Launch Virtual Machines instead of pods for client/servers
7374
--across Place the client and server across availability zones
7475
--all Run all tests scenarios - hostNet and podNetwork (if possible)
7576
--debug Enable debug log
77+
--udn Create and use a UDN called 'udn-l2-primary' as a primary network.
7678
--prom string Prometheus URL
7779
--uuid string User provided UUID
7880
--search string OpenSearch URL, if you have auth, pass in the format of https://user:pass@url:port
81+
--index string OpenSearch Index to save the results to, defaults to k8s-netperf
7982
--metrics Show all system metrics retrieved from prom
8083
--tcp-tolerance float Allowed %diff from hostNetwork to podNetwork, anything above tolerance will result in k8s-netperf exiting 1. (default 10)
8184
--version k8s-netperf version
85+
--csv Archive results, cluster and benchmark metrics in CSV files (default true)
8286
-h, --help help for k8s-netperf
8387

8488

cmd/k8s-netperf/k8s-netperf.go

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@ var (
3939
netperf bool
4040
iperf3 bool
4141
uperf bool
42+
udn bool
4243
acrossAZ bool
4344
full bool
4445
vm bool
@@ -151,19 +152,36 @@ var rootCmd = &cobra.Command{
151152
os.Exit(1)
152153
}
153154

154-
if vm {
155-
s.VM = true
155+
if udn {
156+
s.Udn = true
156157
// Create a dynamic client
157158
dynClient, err := dynamic.NewForConfig(rconfig)
158159
if err != nil {
159160
log.Error(err)
160161
}
162+
s.DClient = dynClient
163+
err = k8s.DeployL2Udn(dynClient)
164+
if err != nil {
165+
log.Error(err)
166+
os.Exit(1)
167+
}
168+
}
169+
170+
if vm {
171+
s.VM = true
172+
// Create a dynamic client
173+
if s.DClient == nil {
174+
dynClient, err := dynamic.NewForConfig(rconfig)
175+
if err != nil {
176+
log.Error(err)
177+
}
178+
s.DClient = dynClient
179+
}
161180
kclient, err := kubevirtv1.NewForConfig(rconfig)
162181
if err != nil {
163182
log.Error(err)
164183
}
165184
s.KClient = kclient
166-
s.DClient = dynClient
167185
}
168186

169187
// Build the SUT (Deployments)
@@ -381,6 +399,7 @@ func executeWorkload(nc config.Config,
381399
hostNet bool,
382400
driverName string, virt bool) result.Data {
383401
serverIP := ""
402+
var err error
384403
Client := s.Client
385404
var driver drivers.Driver
386405
if nc.Service {
@@ -391,6 +410,11 @@ func executeWorkload(nc config.Config,
391410
} else {
392411
serverIP = s.NetperfService.Spec.ClusterIP
393412
}
413+
} else if s.Udn {
414+
serverIP, err = k8s.ExtractUdnIp(s)
415+
if err != nil {
416+
log.Fatal(err)
417+
}
394418
} else {
395419
if hostNet {
396420
serverIP = s.ServerHost.Items[0].Status.PodIP
@@ -488,6 +512,7 @@ func main() {
488512
rootCmd.Flags().BoolVar(&acrossAZ, "across", false, "Place the client and server across availability zones")
489513
rootCmd.Flags().BoolVar(&full, "all", false, "Run all tests scenarios - hostNet and podNetwork (if possible)")
490514
rootCmd.Flags().BoolVar(&debug, "debug", false, "Enable debug log")
515+
rootCmd.Flags().BoolVar(&udn, "udn", false, "Create and use a UDN called 'udn-l2-primary' as primary network.")
491516
rootCmd.Flags().StringVar(&promURL, "prom", "", "Prometheus URL")
492517
rootCmd.Flags().StringVar(&id, "uuid", "", "User provided UUID")
493518
rootCmd.Flags().StringVar(&searchURL, "search", "", "OpenSearch URL, if you have auth, pass in the format of https://user:pass@url:port")

pkg/config/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ type PerfScenarios struct {
3838
Configs []Config
3939
VM bool
4040
VMHost string
41+
Udn bool
4142
ServerNodeInfo metrics.NodeInfo
4243
ClientNodeInfo metrics.NodeInfo
4344
Client apiv1.PodList

pkg/k8s/kubernetes.go

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@ package k8s
22

33
import (
44
"context"
5+
"encoding/json"
56
"fmt"
7+
"net"
68
"strings"
79

810
"github.com/cloud-bulldozer/k8s-netperf/pkg/config"
@@ -12,9 +14,12 @@ import (
1214
corev1 "k8s.io/api/core/v1"
1315
v1 "k8s.io/api/rbac/v1"
1416
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
17+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
1518
"k8s.io/apimachinery/pkg/labels"
19+
"k8s.io/apimachinery/pkg/runtime/schema"
1620
"k8s.io/apimachinery/pkg/util/intstr"
1721
"k8s.io/apimachinery/pkg/watch"
22+
"k8s.io/client-go/dynamic"
1823
"k8s.io/client-go/kubernetes"
1924
"k8s.io/utils/pointer"
2025
)
@@ -44,6 +49,13 @@ type ServiceParams struct {
4449
DataPorts []int32
4550
}
4651

52+
type PodNetworksData struct {
53+
IPAddresses []string `json:"ip_addresses"`
54+
MacAddress string `json:"mac_address"`
55+
GatewayIPs []string `json:"gateway_ips"`
56+
Role string `json:"role"`
57+
}
58+
4759
const sa string = "netperf"
4860
const namespace string = "netperf"
4961

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

7689
// BuildInfra will create the infra for the SUT
7790
func BuildInfra(client *kubernetes.Clientset) error {
@@ -124,6 +137,40 @@ func BuildInfra(client *kubernetes.Clientset) error {
124137
return nil
125138
}
126139

140+
// Create a User Defined Network for the tests
141+
func DeployL2Udn(dynamicClient *dynamic.DynamicClient) error {
142+
log.Infof("Deploying L2 Primary UDN in the NS : %s", namespace)
143+
udn := &unstructured.Unstructured{
144+
Object: map[string]interface{}{
145+
"apiVersion": "k8s.ovn.org/v1",
146+
"kind": "UserDefinedNetwork",
147+
"metadata": map[string]interface{}{
148+
"name": udnName,
149+
"namespace": "netperf",
150+
},
151+
"spec": map[string]interface{}{
152+
"topology": "Layer2",
153+
"layer2": map[string]interface{}{
154+
"role": "Primary",
155+
"subnets": []string{"10.0.0.0/24", "2001:db8::/60"},
156+
},
157+
},
158+
},
159+
}
160+
161+
// Specify the GVR for UDN
162+
gvr := schema.GroupVersionResource{
163+
Group: "k8s.ovn.org",
164+
Version: "v1",
165+
Resource: "userdefinednetworks",
166+
}
167+
_, err := dynamicClient.Resource(gvr).Namespace(namespace).Create(context.TODO(), udn, metav1.CreateOptions{})
168+
if err != nil {
169+
return err
170+
}
171+
return nil
172+
}
173+
127174
// BuildSUT Build the k8s env to run network performance tests
128175
func BuildSUT(client *kubernetes.Clientset, s *config.PerfScenarios) error {
129176
var netperfDataPorts []int32
@@ -449,6 +496,35 @@ func BuildSUT(client *kubernetes.Clientset, s *config.PerfScenarios) error {
449496
return nil
450497
}
451498

499+
// Extract the UDN Ip address of a pod from the annotations - Support only ipv4
500+
func ExtractUdnIp(s config.PerfScenarios) (string, error) {
501+
podNetworksJson := s.Server.Items[0].Annotations["k8s.ovn.org/pod-networks"]
502+
//
503+
var root map[string]json.RawMessage
504+
err := json.Unmarshal([]byte(podNetworksJson), &root)
505+
if err != nil {
506+
fmt.Println("Error unmarshalling JSON:", err)
507+
return "", err
508+
}
509+
//
510+
var udnData PodNetworksData
511+
err = json.Unmarshal(root["netperf/"+udnName], &udnData)
512+
if err != nil {
513+
return "", err
514+
}
515+
// Extract the IPv4 address
516+
var ipv4 net.IP
517+
for _, ip := range udnData.IPAddresses {
518+
if strings.Contains(ip, ".") { // Check if it's an IPv4 address
519+
ipv4, _, err = net.ParseCIDR(ip)
520+
if err != nil {
521+
return "", err
522+
}
523+
}
524+
}
525+
return ipv4.String(), nil
526+
}
527+
452528
// launchServerVM will create the ServerVM with the specific node and pod affinity.
453529
func launchServerVM(perf *config.PerfScenarios, name string, podAff *corev1.PodAntiAffinity, nodeAff *corev1.NodeAffinity) error {
454530
_, err := CreateVMServer(perf.KClient, serverRole, serverRole, *podAff, *nodeAff)

0 commit comments

Comments
 (0)