k8s.io/kubernetes@v1.29.3/test/integration/ipamperf/ipam_test.go (about) 1 /* 2 Copyright 2018 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 ipamperf 18 19 import ( 20 "context" 21 "encoding/json" 22 "fmt" 23 "net" 24 "os" 25 "testing" 26 "time" 27 28 "k8s.io/klog/v2" 29 "k8s.io/klog/v2/ktesting" 30 netutils "k8s.io/utils/net" 31 32 "k8s.io/client-go/informers" 33 clientset "k8s.io/client-go/kubernetes" 34 restclient "k8s.io/client-go/rest" 35 "k8s.io/kubernetes/cmd/kube-apiserver/app/options" 36 "k8s.io/kubernetes/pkg/controller/nodeipam" 37 "k8s.io/kubernetes/pkg/controller/nodeipam/ipam" 38 "k8s.io/kubernetes/test/integration/framework" 39 "k8s.io/kubernetes/test/integration/util" 40 ) 41 42 func setupAllocator(ctx context.Context, kubeConfig *restclient.Config, config *Config, clusterCIDR, serviceCIDR *net.IPNet, subnetMaskSize int) (*clientset.Clientset, util.ShutdownFunc, error) { 43 controllerStopChan := make(chan struct{}) 44 shutdownFunc := func() { 45 close(controllerStopChan) 46 } 47 48 clientConfig := restclient.CopyConfig(kubeConfig) 49 clientConfig.QPS = float32(config.KubeQPS) 50 clientConfig.Burst = config.KubeQPS 51 clientSet := clientset.NewForConfigOrDie(clientConfig) 52 53 sharedInformer := informers.NewSharedInformerFactory(clientSet, 1*time.Hour) 54 ipamController, err := nodeipam.NewNodeIpamController( 55 ctx, 56 sharedInformer.Core().V1().Nodes(), 57 config.Cloud, clientSet, []*net.IPNet{clusterCIDR}, serviceCIDR, nil, 58 []int{subnetMaskSize}, config.AllocatorType, 59 ) 60 if err != nil { 61 return nil, shutdownFunc, err 62 } 63 go ipamController.Run(ctx) 64 sharedInformer.Start(controllerStopChan) 65 66 return clientSet, shutdownFunc, nil 67 } 68 69 func runTest(t *testing.T, kubeConfig *restclient.Config, config *Config, clusterCIDR, serviceCIDR *net.IPNet, subnetMaskSize int) (*Results, error) { 70 t.Helper() 71 klog.Infof("Running test %s", t.Name()) 72 73 nodeClientConfig := restclient.CopyConfig(kubeConfig) 74 nodeClientConfig.QPS = float32(config.CreateQPS) 75 nodeClientConfig.Burst = config.CreateQPS 76 nodeClient := clientset.NewForConfigOrDie(nodeClientConfig) 77 78 defer deleteNodes(nodeClient) // cleanup nodes on after controller shutdown 79 _, ctx := ktesting.NewTestContext(t) 80 clientSet, shutdownFunc, err := setupAllocator(ctx, kubeConfig, config, clusterCIDR, serviceCIDR, subnetMaskSize) 81 if err != nil { 82 t.Fatalf("Error starting IPAM allocator: %v", err) 83 } 84 defer shutdownFunc() 85 86 o := NewObserver(clientSet, config.NumNodes) 87 if err := o.StartObserving(); err != nil { 88 t.Fatalf("Could not start test observer: %v", err) 89 } 90 91 if err := createNodes(nodeClient, config); err != nil { 92 t.Fatalf("Could not create nodes: %v", err) 93 } 94 95 results := o.Results(t.Name(), config) 96 klog.Infof("Results: %s", results) 97 if !results.Succeeded { 98 t.Errorf("%s: Not allocations succeeded", t.Name()) 99 } 100 return results, nil 101 } 102 103 func logResults(allResults []*Results) { 104 jStr, err := json.MarshalIndent(allResults, "", " ") 105 if err != nil { 106 klog.Errorf("Error formatting results: %v", err) 107 return 108 } 109 if resultsLogFile != "" { 110 klog.Infof("Logging results to %s", resultsLogFile) 111 if err := os.WriteFile(resultsLogFile, jStr, os.FileMode(0644)); err != nil { 112 klog.Errorf("Error logging results to %s: %v", resultsLogFile, err) 113 } 114 } 115 klog.Infof("AllResults:\n%s", string(jStr)) 116 } 117 118 func TestPerformance(t *testing.T) { 119 // TODO (#93112) skip test until appropriate timeout established 120 if testing.Short() || true { 121 // TODO (#61854) find why flakiness is caused by etcd connectivity before enabling always 122 t.Skip("Skipping because we want to run short tests") 123 } 124 125 _, ctx := ktesting.NewTestContext(t) 126 ctx, cancel := context.WithCancel(ctx) 127 defer cancel() 128 129 _, kubeConfig, tearDownFn := framework.StartTestServer(ctx, t, framework.TestServerSetup{ 130 ModifyServerRunOptions: func(opts *options.ServerRunOptions) { 131 // Disable ServiceAccount admission plugin as we don't have serviceaccount controller running. 132 opts.Admission.GenericAdmission.DisablePlugins = []string{"ServiceAccount", "TaintNodesByCondition"} 133 }, 134 }) 135 defer tearDownFn() 136 137 _, clusterCIDR, _ := netutils.ParseCIDRSloppy("10.96.0.0/11") // allows up to 8K nodes 138 _, serviceCIDR, _ := netutils.ParseCIDRSloppy("10.94.0.0/24") // does not matter for test - pick upto 250 services 139 subnetMaskSize := 24 140 141 var ( 142 allResults []*Results 143 tests []*Config 144 ) 145 146 if isCustom { 147 tests = append(tests, customConfig) 148 } else { 149 for _, numNodes := range []int{10, 100} { 150 for _, alloc := range []ipam.CIDRAllocatorType{ipam.RangeAllocatorType, ipam.CloudAllocatorType, ipam.IPAMFromClusterAllocatorType, ipam.IPAMFromCloudAllocatorType} { 151 tests = append(tests, &Config{AllocatorType: alloc, NumNodes: numNodes, CreateQPS: numNodes, KubeQPS: 10, CloudQPS: 10}) 152 } 153 } 154 } 155 156 for _, test := range tests { 157 testName := fmt.Sprintf("%s-KubeQPS%d-Nodes%d", test.AllocatorType, test.KubeQPS, test.NumNodes) 158 t.Run(testName, func(t *testing.T) { 159 allocateCIDR := false 160 if test.AllocatorType == ipam.IPAMFromCloudAllocatorType || test.AllocatorType == ipam.CloudAllocatorType { 161 allocateCIDR = true 162 } 163 bil := newBaseInstanceList(allocateCIDR, clusterCIDR, subnetMaskSize) 164 cloud, err := util.NewMockGCECloud(bil.newMockCloud()) 165 if err != nil { 166 t.Fatalf("Unable to create mock cloud: %v", err) 167 } 168 test.Cloud = cloud 169 if results, err := runTest(t, kubeConfig, test, clusterCIDR, serviceCIDR, subnetMaskSize); err == nil { 170 allResults = append(allResults, results) 171 } 172 }) 173 } 174 175 logResults(allResults) 176 }