k8s.io/perf-tests/clusterloader2@v0.0.0-20240304094227-64bdb12da87e/pkg/measurement/common/network-policy/network-policy-enforcement-latency.go (about)

     1  /*
     2  Copyright 2023 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package networkpolicy
    18  
    19  import (
    20  	"context"
    21  	"embed"
    22  	"fmt"
    23  	"strings"
    24  	"sync"
    25  	"time"
    26  
    27  	"golang.org/x/time/rate"
    28  	corev1 "k8s.io/api/core/v1"
    29  	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
    30  	clientset "k8s.io/client-go/kubernetes"
    31  	"k8s.io/klog/v2"
    32  	"k8s.io/perf-tests/clusterloader2/pkg/framework"
    33  	"k8s.io/perf-tests/clusterloader2/pkg/framework/client"
    34  	"k8s.io/perf-tests/clusterloader2/pkg/measurement"
    35  	measurementutil "k8s.io/perf-tests/clusterloader2/pkg/measurement/util"
    36  	"k8s.io/perf-tests/clusterloader2/pkg/util"
    37  )
    38  
    39  /*
    40  The measurement tests network policy enforcement latency for two cases:
    41  	1. Created network policies
    42  Deploy the test clients (setup and run) with "testType" flag set to
    43  "policy-creation" after creating the target pods.
    44  	2. Created pods that are affected by network policies
    45  Deploy the test clients (setup and run) with "testType" flag set to
    46  "pod-creation", before creating the target pods.
    47  Target pods are all pods that have the specified label:
    48  { net-pol-test: targetLabelValue }.
    49  The test is set up by this measurement, by creating the required resources,
    50  including the network policy enforcement latency test client pods that are
    51  measuring the latencies and generating metrics for them.
    52  https://github.com/kubernetes/perf-tests/tree/master/network/tools/network-policy-enforcement-latency
    53  */
    54  
    55  const (
    56  	networkPolicyEnforcementName = "NetworkPolicyEnforcement"
    57  	netPolicyTestNamespace       = "net-policy-test"
    58  	netPolicyTestClientName      = "np-test-client"
    59  	policyCreationTest           = "policy-creation"
    60  	podCreationTest              = "pod-creation"
    61  	// denyLabelValue is used for network policies to allow connections only to
    62  	// the pods with the specified label, effectively denying other connections,
    63  	// as long as there isn't another network policy allowing it for other labels.
    64  	denyLabelValue  = "deny-traffic"
    65  	allowPolicyName = "allow-egress-to-target"
    66  	denyPolicyName  = "deny-egress-to-target"
    67  
    68  	serviceAccountFilePath              = "manifests/serviceaccount.yaml"
    69  	clusterRoleFilePath                 = "manifests/clusterrole.yaml"
    70  	clusterRoleBindingFilePath          = "manifests/clusterrolebinding.yaml"
    71  	depTestClientPolicyCreationFilePath = "manifests/dep-test-client-policy-creation.yaml"
    72  	depTestClientPodCreationFilePath    = "manifests/dep-test-client-pod-creation.yaml"
    73  	policyEgressApiserverFilePath       = "manifests/policy-egress-allow-apiserver.yaml"
    74  	policyEgressTargetPodsFilePath      = "manifests/policy-egress-allow-target-pods.yaml"
    75  	policyLoadFilePath                  = "manifests/policy-load.yaml"
    76  
    77  	defaultPolicyTargetLoadBaseName = "small-deployment"
    78  	defaultPolicyLoadCount          = 1000
    79  	defaultPolicyLoadQPS            = 10
    80  )
    81  
    82  //go:embed manifests
    83  var manifestsFS embed.FS
    84  
    85  func init() {
    86  	klog.V(2).Infof("Registering %q", networkPolicyEnforcementName)
    87  	if err := measurement.Register(networkPolicyEnforcementName, createNetworkPolicyEnforcementMeasurement); err != nil {
    88  		klog.Fatalf("Cannot register %s: %v", networkPolicyEnforcementName, err)
    89  	}
    90  }
    91  
    92  func createNetworkPolicyEnforcementMeasurement() measurement.Measurement {
    93  	return &networkPolicyEnforcementMeasurement{}
    94  }
    95  
    96  type networkPolicyEnforcementMeasurement struct {
    97  	k8sClient clientset.Interface
    98  	framework *framework.Framework
    99  	// testClientNamespace is the namespace of the test client pods.
   100  	testClientNamespace string
   101  	// targetLabelValue is the value for the label selector of target pods to
   102  	// apply network policies on and measure the latency to become reachable.
   103  	targetLabelValue string
   104  	// targetNamespaces is a list of test namespace with "test-" prefix that are
   105  	// used to specify namespaces of target pods for all test clients.
   106  	targetNamespaces []string
   107  	// baseline test does not create network policies. It is only used for pod
   108  	// creation latency test, to compare pod creation reachability latency with
   109  	// and without network policies.
   110  	baseline bool
   111  	// testClientNodeSelectorValue is value key for the node label on which the
   112  	// test client pods should run.
   113  	testClientNodeSelectorValue string
   114  }
   115  
   116  // Execute - Available actions:
   117  // 1. setup - Loads all the required data to execute run command. Should be
   118  // called only once.
   119  // 2. run - Runs a test measurement for the specified test type.
   120  // 3. complete - Finishes and cleans up the specified test type.
   121  func (nps *networkPolicyEnforcementMeasurement) Execute(config *measurement.Config) ([]measurement.Summary, error) {
   122  	action, err := util.GetString(config.Params, "action")
   123  	if err != nil {
   124  		return nil, err
   125  	}
   126  
   127  	switch action {
   128  	case "setup":
   129  		return nil, nps.setup(config)
   130  	case "run":
   131  		return nil, nps.run(config)
   132  	case "complete":
   133  		return nil, nps.complete(config)
   134  	default:
   135  		return nil, fmt.Errorf("unknown action %v", action)
   136  	}
   137  }
   138  
   139  // setup initializes the measurement, creates a namespace, network policy egress
   140  // allow to the kube-apiserver and permissions for the network policy
   141  // enforcement test clients.
   142  func (nps *networkPolicyEnforcementMeasurement) setup(config *measurement.Config) error {
   143  	err := nps.initializeMeasurement(config)
   144  	if err != nil {
   145  		return fmt.Errorf("failed to initialize the measurement: %v", err)
   146  	}
   147  
   148  	if err := client.CreateNamespace(nps.k8sClient, nps.testClientNamespace); err != nil {
   149  		return fmt.Errorf("error while creating namespace: %v", err)
   150  	}
   151  
   152  	// Create network policies for non-baseline test.
   153  	if !nps.baseline {
   154  		if err = nps.createPolicyAllowAPIServer(); err != nil {
   155  			return err
   156  		}
   157  
   158  		// Create a policy that allows egress from pod creation test client pods to
   159  		// target pods.
   160  		podCreationAllowPolicyName := fmt.Sprintf("%s-pod-creation", allowPolicyName)
   161  		if err = nps.createPolicyToTargetPods(podCreationAllowPolicyName, "", podCreationTest, true); err != nil {
   162  			return err
   163  		}
   164  
   165  		// Create a policy that denies egress from policy creation test client pods
   166  		// to target pods.
   167  		policyCreationDenyPolicyName := fmt.Sprintf("%s-policy-creation", denyPolicyName)
   168  		if err = nps.createPolicyToTargetPods(policyCreationDenyPolicyName, "", policyCreationTest, false); err != nil {
   169  			return err
   170  		}
   171  	}
   172  
   173  	return nps.createPermissionResources()
   174  }
   175  
   176  func (nps *networkPolicyEnforcementMeasurement) initializeMeasurement(config *measurement.Config) error {
   177  	if nps.framework != nil {
   178  		return fmt.Errorf("the %q is already started. Cannot start again", networkPolicyEnforcementName)
   179  	}
   180  
   181  	var err error
   182  	if nps.targetLabelValue, err = util.GetString(config.Params, "targetLabelValue"); err != nil {
   183  		return err
   184  	}
   185  
   186  	if nps.testClientNamespace, err = util.GetStringOrDefault(config.Params, "testClientNamespace", netPolicyTestNamespace); err != nil {
   187  		return err
   188  	}
   189  
   190  	if nps.baseline, err = util.GetBoolOrDefault(config.Params, "baseline", false); err != nil {
   191  		return err
   192  	}
   193  
   194  	if nps.testClientNodeSelectorValue, err = util.GetString(config.Params, "testClientNodeSelectorValue"); err != nil {
   195  		return err
   196  	}
   197  
   198  	nps.framework = config.ClusterFramework
   199  	nps.k8sClient = config.ClusterFramework.GetClientSets().GetClient()
   200  
   201  	namespaceList, err := nps.k8sClient.CoreV1().Namespaces().List(context.TODO(), metav1.ListOptions{})
   202  	if err != nil {
   203  		return err
   204  	}
   205  
   206  	// Target namespaces are only those that have a predefined test prefix.
   207  	testNamespacePrefix := nps.framework.GetAutomanagedNamespacePrefix()
   208  	for _, ns := range namespaceList.Items {
   209  		if strings.HasPrefix(ns.GetName(), testNamespacePrefix) {
   210  			nps.targetNamespaces = append(nps.targetNamespaces, ns.GetName())
   211  		}
   212  	}
   213  
   214  	if len(nps.targetNamespaces) == 0 {
   215  		return fmt.Errorf("cannot initialize the %q, no namespaces with prefix %q exist", networkPolicyEnforcementName, testNamespacePrefix)
   216  	}
   217  
   218  	return nil
   219  }
   220  
   221  // createPermissionResources creates ServiceAccount, ClusterRole and
   222  // ClusterRoleBinding for the test client pods.
   223  func (nps *networkPolicyEnforcementMeasurement) createPermissionResources() error {
   224  	templateMap := map[string]interface{}{
   225  		"Name":      netPolicyTestClientName,
   226  		"Namespace": nps.testClientNamespace,
   227  	}
   228  
   229  	if err := nps.framework.ApplyTemplatedManifests(manifestsFS, serviceAccountFilePath, templateMap); err != nil {
   230  		return fmt.Errorf("error while creating serviceaccount: %v", err)
   231  	}
   232  
   233  	if err := nps.framework.ApplyTemplatedManifests(manifestsFS, clusterRoleFilePath, templateMap); err != nil {
   234  		return fmt.Errorf("error while creating clusterrole: %v", err)
   235  	}
   236  
   237  	if err := nps.framework.ApplyTemplatedManifests(manifestsFS, clusterRoleBindingFilePath, templateMap); err != nil {
   238  		return fmt.Errorf("error while creating clusterrolebinding: %v", err)
   239  	}
   240  
   241  	return nil
   242  }
   243  
   244  func (nps *networkPolicyEnforcementMeasurement) run(config *measurement.Config) error {
   245  	if nps.framework == nil {
   246  		return fmt.Errorf("the %q is not set up. Execute with the `setup` action before with the `run` action", networkPolicyEnforcementName)
   247  	}
   248  
   249  	targetPort, err := util.GetIntOrDefault(config.Params, "targetPort", 80)
   250  	if err != nil {
   251  		return err
   252  	}
   253  
   254  	maxTargets, err := util.GetIntOrDefault(config.Params, "maxTargets", 1000)
   255  	if err != nil {
   256  		return err
   257  	}
   258  
   259  	metricsPort, err := util.GetIntOrDefault(config.Params, "metricsPort", 9160)
   260  	if err != nil {
   261  		return err
   262  	}
   263  
   264  	testType, err := util.GetString(config.Params, "testType")
   265  	if err != nil {
   266  		return err
   267  	}
   268  
   269  	templateMap := map[string]interface{}{
   270  		"Namespace":                   nps.testClientNamespace,
   271  		"TestClientLabel":             netPolicyTestClientName,
   272  		"TargetLabelSelector":         fmt.Sprintf("net-pol-test = %s", nps.targetLabelValue),
   273  		"TargetPort":                  targetPort,
   274  		"MetricsPort":                 metricsPort,
   275  		"ServiceAccountName":          netPolicyTestClientName,
   276  		"MaxTargets":                  maxTargets,
   277  		"TestClientNodeSelectorValue": nps.testClientNodeSelectorValue,
   278  	}
   279  
   280  	switch testType {
   281  	case policyCreationTest:
   282  		err = nps.runPolicyCreationTest(templateMap, config)
   283  	case podCreationTest:
   284  		err = nps.runPodCreationTest(templateMap)
   285  	default:
   286  		err = fmt.Errorf("unknown testType is specified: %q", testType)
   287  	}
   288  
   289  	return err
   290  }
   291  
   292  func (nps *networkPolicyEnforcementMeasurement) runPodCreationTest(depTemplateMap map[string]interface{}) error {
   293  	klog.V(2).Infof("Starting network policy enforcement latency measurement for pod creation")
   294  	return nps.createTestClientDeployments(depTemplateMap, podCreationTest, depTestClientPodCreationFilePath)
   295  }
   296  
   297  func (nps *networkPolicyEnforcementMeasurement) runPolicyCreationTest(depTemplateMap map[string]interface{}, config *measurement.Config) error {
   298  	klog.V(2).Infof("Starting network policy enforcement latency measurement for policy creation")
   299  	if nps.baseline {
   300  		klog.Warningf("Baseline flag is specified, which is only used for pod creation test, and means that no network policies should be created. Skipping policy creation test")
   301  		return nil
   302  	}
   303  
   304  	if err := nps.createTestClientDeployments(depTemplateMap, policyCreationTest, depTestClientPolicyCreationFilePath); err != nil {
   305  		return err
   306  	}
   307  
   308  	const (
   309  		timeout      = 2 * time.Minute
   310  		waitInterval = 5 * time.Second
   311  	)
   312  	ctx, cancel := context.WithTimeout(context.TODO(), timeout)
   313  	defer cancel()
   314  
   315  	desiredPodCount := len(nps.targetNamespaces)
   316  	options := &measurementutil.WaitForPodOptions{
   317  		DesiredPodCount:     func() int { return desiredPodCount },
   318  		CallerName:          nps.String(),
   319  		WaitForPodsInterval: waitInterval,
   320  	}
   321  
   322  	objectSelector := &util.ObjectSelector{
   323  		Namespace:     nps.testClientNamespace,
   324  		LabelSelector: fmt.Sprintf("type = %s", policyCreationTest),
   325  	}
   326  
   327  	podStore, err := measurementutil.NewPodStore(nps.k8sClient, objectSelector)
   328  	if err != nil {
   329  		return err
   330  	}
   331  
   332  	klog.V(2).Infof("Waiting for policy creation test client pods to be running")
   333  	_, err = measurementutil.WaitForPods(ctx, podStore, options)
   334  	if err != nil {
   335  		klog.Warningf("Not all %d policy creation test client pods are running after %v", len(nps.targetNamespaces), timeout)
   336  	}
   337  
   338  	wg := sync.WaitGroup{}
   339  	wg.Add(1)
   340  	// Create load policies while allow policies are being created to take network
   341  	// policy churn into account.
   342  	go func() {
   343  		nps.createLoadPolicies(config)
   344  		wg.Done()
   345  	}()
   346  
   347  	nps.createAllowPoliciesForPolicyCreationLatency()
   348  	wg.Wait()
   349  
   350  	return nil
   351  }
   352  
   353  func (nps *networkPolicyEnforcementMeasurement) createPolicyAllowAPIServer() error {
   354  	policyName := "allow-egress-apiserver"
   355  	if policy, err := nps.k8sClient.NetworkingV1().NetworkPolicies(nps.testClientNamespace).Get(context.TODO(), policyName, metav1.GetOptions{}); err == nil && policy != nil {
   356  		klog.Warningf("Attempting to create %q network policy, but it already exists", policyName)
   357  		return nil
   358  	}
   359  
   360  	// Get kube-apiserver IP address to allow connections to it from the test
   361  	// client pods. It's needed since network policies are denying connections
   362  	// with all endpoints that are not in the specified Labels / CIDR range.
   363  	endpoints, err := nps.k8sClient.CoreV1().Endpoints(corev1.NamespaceDefault).Get(context.TODO(), "kubernetes", metav1.GetOptions{})
   364  	if err != nil {
   365  		return fmt.Errorf("failed to get kube-apiserver Endpoints object: %v", err)
   366  	}
   367  
   368  	if len(endpoints.Subsets) == 0 || len(endpoints.Subsets[0].Addresses) == 0 {
   369  		return fmt.Errorf("kube-apiserver Endpoints object does not have an IP address")
   370  	}
   371  
   372  	kubeAPIServerIP := endpoints.Subsets[0].Addresses[0].IP
   373  	templateMap := map[string]interface{}{
   374  		"Name":            policyName,
   375  		"Namespace":       nps.testClientNamespace,
   376  		"TestClientLabel": netPolicyTestClientName,
   377  		"kubeAPIServerIP": kubeAPIServerIP,
   378  	}
   379  
   380  	if err := nps.framework.ApplyTemplatedManifests(manifestsFS, policyEgressApiserverFilePath, templateMap); err != nil {
   381  		return fmt.Errorf("error while creating allow egress to apiserver network policy: %v", err)
   382  	}
   383  
   384  	return nil
   385  }
   386  
   387  func (nps *networkPolicyEnforcementMeasurement) createPolicyToTargetPods(policyName, targetNamespace, testType string, allowForTargetPods bool) error {
   388  	templateMap := map[string]interface{}{
   389  		"Name":           policyName,
   390  		"Namespace":      nps.testClientNamespace,
   391  		"TypeLabelValue": testType,
   392  	}
   393  
   394  	if allowForTargetPods {
   395  		templateMap["TargetLabelValue"] = nps.targetLabelValue
   396  	} else {
   397  		templateMap["TargetLabelValue"] = denyLabelValue
   398  	}
   399  
   400  	if len(targetNamespace) > 0 {
   401  		templateMap["OnlyTargetNamespace"] = true
   402  		templateMap["TargetNamespace"] = targetNamespace
   403  	} else {
   404  		templateMap["OnlyTargetNamespace"] = false
   405  	}
   406  
   407  	if err := nps.framework.ApplyTemplatedManifests(manifestsFS, policyEgressTargetPodsFilePath, templateMap); err != nil {
   408  		return fmt.Errorf("error while creating allow egress to pods network policy: %v", err)
   409  	}
   410  
   411  	return nil
   412  }
   413  
   414  func (nps *networkPolicyEnforcementMeasurement) createTestClientDeployments(templateMap map[string]interface{}, testType, deploymentFilePath string) error {
   415  	klog.V(2).Infof("Creating test client deployments for measurement %q", networkPolicyEnforcementName)
   416  	templateMap["TypeLabelValue"] = testType
   417  
   418  	// Create a test client deployment for each test namespace.
   419  	for i, ns := range nps.targetNamespaces {
   420  		templateMap["Name"] = fmt.Sprintf("%s-%s-%d", testType, netPolicyTestClientName, i)
   421  		templateMap["TargetNamespace"] = ns
   422  		templateMap["AllowPolicyName"] = fmt.Sprintf("%s-%d", allowPolicyName, i)
   423  
   424  		if err := nps.framework.ApplyTemplatedManifests(manifestsFS, deploymentFilePath, templateMap); err != nil {
   425  			return fmt.Errorf("error while creating test client deployment: %v", err)
   426  		}
   427  	}
   428  
   429  	return nil
   430  }
   431  
   432  func (nps *networkPolicyEnforcementMeasurement) createLoadPolicies(config *measurement.Config) {
   433  	policyLoadTargetBaseName, err := util.GetStringOrDefault(config.Params, "policyLoadTargetBaseName", defaultPolicyTargetLoadBaseName)
   434  	if err != nil {
   435  		klog.Errorf("Failed getting parameter policyLoadBaseName value, error: %v", err)
   436  		return
   437  	}
   438  
   439  	policyLoadCount, err := util.GetIntOrDefault(config.Params, "policyLoadCount", defaultPolicyLoadCount)
   440  	if err != nil {
   441  		klog.Errorf("Failed getting parameter policyLoadBaseName value, error: %v", err)
   442  		return
   443  	}
   444  
   445  	policyLoadQPS, err := util.GetIntOrDefault(config.Params, "policyLoadQPS", defaultPolicyLoadQPS)
   446  	if err != nil {
   447  		klog.Errorf("Failed getting parameter policyLoadQPS value, error: %v", err)
   448  		return
   449  	}
   450  
   451  	policiesPerNs := policyLoadCount / len(nps.targetNamespaces)
   452  	limiter := rate.NewLimiter(rate.Limit(policyLoadQPS), policyLoadQPS)
   453  
   454  	for nsIdx, ns := range nps.targetNamespaces {
   455  		octet := nsIdx % 256
   456  		baseCidr := fmt.Sprintf("10.0.%d.0/24", octet)
   457  
   458  		for depIdx := 0; depIdx < policiesPerNs; depIdx++ {
   459  			// This will be the same as "small-deployment-0".."small-deployment-50",
   460  			// that is used in the ClusterLoader2 load test.
   461  			// https://github.com/kubernetes/perf-tests/tree/master/clusterloader2/testing/load
   462  			podSelectorLabelValue := fmt.Sprintf("policy-load-%s-%d", policyLoadTargetBaseName, depIdx)
   463  			templateMapForTargetPods := map[string]interface{}{
   464  				"Name":                  fmt.Sprintf("%s-%d", podSelectorLabelValue, nsIdx),
   465  				"Namespace":             ns,
   466  				"PodSelectorLabelValue": podSelectorLabelValue,
   467  				"CIDR":                  baseCidr,
   468  			}
   469  
   470  			err := limiter.Wait(context.TODO())
   471  			if err != nil {
   472  				klog.Errorf("limiter.Wait() returned an error: %v", err)
   473  				return
   474  			}
   475  
   476  			if err := nps.framework.ApplyTemplatedManifests(manifestsFS, policyLoadFilePath, templateMapForTargetPods); err != nil {
   477  				klog.Errorf("Error while creating load network policy for label selector 'name=%s': %v", podSelectorLabelValue, err)
   478  			}
   479  		}
   480  	}
   481  }
   482  
   483  func (nps *networkPolicyEnforcementMeasurement) createAllowPoliciesForPolicyCreationLatency() {
   484  	klog.V(2).Infof("Creating allow network policies for measurement %q", networkPolicyEnforcementName)
   485  
   486  	for i, ns := range nps.targetNamespaces {
   487  		policyName := fmt.Sprintf("%s-%d", allowPolicyName, i)
   488  		err := nps.createPolicyToTargetPods(policyName, ns, policyCreationTest, true)
   489  		if err != nil {
   490  			klog.Errorf("Failed to create a network policy to allow traffic to namespace %q", ns)
   491  		}
   492  	}
   493  }
   494  
   495  // complete deletes test client deployments for the specified test mode.
   496  func (nps *networkPolicyEnforcementMeasurement) complete(config *measurement.Config) error {
   497  	testType, err := util.GetString(config.Params, "testType")
   498  	if err != nil {
   499  		return err
   500  	}
   501  
   502  	var typeLabelValue string
   503  	switch testType {
   504  	case policyCreationTest:
   505  		typeLabelValue = policyCreationTest
   506  	case podCreationTest:
   507  		typeLabelValue = podCreationTest
   508  	default:
   509  		return fmt.Errorf("unknown testType is specified: %q", testType)
   510  	}
   511  
   512  	listOpts := metav1.ListOptions{LabelSelector: fmt.Sprintf("type=%s", typeLabelValue)}
   513  	err = nps.k8sClient.AppsV1().Deployments(nps.testClientNamespace).DeleteCollection(context.TODO(), metav1.DeleteOptions{}, listOpts)
   514  	if err != nil {
   515  		return fmt.Errorf("failed to complete %q test, error: %v", typeLabelValue, err)
   516  	}
   517  
   518  	return nil
   519  }
   520  
   521  func (nps *networkPolicyEnforcementMeasurement) deleteClusterRoleAndBinding() error {
   522  	klog.V(2).Infof("Deleting ClusterRole and ClusterRoleBinding for measurement %q", networkPolicyEnforcementName)
   523  
   524  	if err := nps.k8sClient.RbacV1().ClusterRoles().Delete(context.TODO(), netPolicyTestClientName, metav1.DeleteOptions{}); err != nil {
   525  		return err
   526  	}
   527  
   528  	return nps.k8sClient.RbacV1().ClusterRoleBindings().Delete(context.TODO(), netPolicyTestClientName, metav1.DeleteOptions{})
   529  }
   530  
   531  func (nps *networkPolicyEnforcementMeasurement) cleanUp() error {
   532  	if nps.k8sClient == nil {
   533  		return fmt.Errorf("cleanup skipped - the measurement is not running")
   534  	}
   535  
   536  	if err := nps.deleteClusterRoleAndBinding(); err != nil {
   537  		return err
   538  	}
   539  
   540  	klog.V(2).Infof("Deleting namespace %q for measurement %q", nps.testClientNamespace, networkPolicyEnforcementName)
   541  	return nps.k8sClient.CoreV1().Namespaces().Delete(context.TODO(), nps.testClientNamespace, metav1.DeleteOptions{})
   542  }
   543  
   544  // String returns a string representation of the measurement.
   545  func (nps *networkPolicyEnforcementMeasurement) String() string {
   546  	return networkPolicyEnforcementName
   547  }
   548  
   549  // Dispose cleans up after the measurement.
   550  func (nps *networkPolicyEnforcementMeasurement) Dispose() {
   551  	if err := nps.cleanUp(); err != nil {
   552  		klog.Errorf("Failed to clean up, error: %v", err)
   553  	}
   554  }