1
16
17 package network
18
19 import (
20 "context"
21 "fmt"
22 "strconv"
23 "time"
24
25 v1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/util/wait"
28 "k8s.io/client-go/util/workqueue"
29 "k8s.io/kubernetes/test/e2e/feature"
30 "k8s.io/kubernetes/test/e2e/framework"
31 e2enode "k8s.io/kubernetes/test/e2e/framework/node"
32 "k8s.io/kubernetes/test/e2e/network/common"
33 testutils "k8s.io/kubernetes/test/utils"
34 admissionapi "k8s.io/pod-security-admission/api"
35
36 "github.com/onsi/ginkgo/v2"
37 )
38
39 const (
40 parallelCreateServiceWorkers = 1
41 maxServicesPerCluster = 10000
42 maxServicesPerNamespace = 5000
43 checkServicePercent = 0.05
44 )
45
46 var _ = common.SIGDescribe(feature.PerformanceDNS, framework.WithSerial(), func() {
47 f := framework.NewDefaultFramework("performancedns")
48 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
49
50 ginkgo.BeforeEach(func(ctx context.Context) {
51 framework.ExpectNoError(e2enode.WaitForAllNodesSchedulable(ctx, f.ClientSet, f.Timeouts.NodeSchedulable))
52 e2enode.WaitForTotalHealthy(ctx, f.ClientSet, time.Minute)
53
54 err := framework.CheckTestingNSDeletedExcept(ctx, f.ClientSet, f.Namespace.Name)
55 framework.ExpectNoError(err)
56 })
57
58
59 ginkgo.It("Should answer DNS query for maximum number of services per cluster", func(ctx context.Context) {
60
61 numNs := (maxServicesPerCluster + maxServicesPerNamespace - 1) / maxServicesPerNamespace
62
63 var namespaces []string
64 for i := 0; i < numNs; i++ {
65 ns, _ := f.CreateNamespace(ctx, f.BaseName, nil)
66 namespaces = append(namespaces, ns.Name)
67 f.AddNamespacesToDelete(ns)
68 }
69
70 services := generateServicesInNamespaces(namespaces, maxServicesPerCluster)
71 createService := func(i int) {
72 defer ginkgo.GinkgoRecover()
73 framework.ExpectNoError(testutils.CreateServiceWithRetries(f.ClientSet, services[i].Namespace, services[i]))
74 }
75 framework.Logf("Creating %v test services", maxServicesPerCluster)
76 workqueue.ParallelizeUntil(ctx, parallelCreateServiceWorkers, len(services), createService)
77 dnsTest := dnsTestCommon{
78 f: f,
79 c: f.ClientSet,
80 ns: f.Namespace.Name,
81 }
82 dnsTest.createUtilPodLabel(ctx, "e2e-dns-scale-records")
83 ginkgo.DeferCleanup(dnsTest.deleteUtilPod)
84 framework.Logf("Querying %v%% of service records", checkServicePercent*100)
85 for i := 0; i < len(services); i++ {
86 if i%(1/checkServicePercent) != 0 {
87 continue
88 }
89 s := services[i]
90 svc, err := f.ClientSet.CoreV1().Services(s.Namespace).Get(ctx, s.Name, metav1.GetOptions{})
91 framework.ExpectNoError(err)
92 qname := fmt.Sprintf("%v.%v.svc.%v", s.Name, s.Namespace, framework.TestContext.ClusterDNSDomain)
93 framework.Logf("Querying %v expecting %v", qname, svc.Spec.ClusterIP)
94 dnsTest.checkDNSRecordFrom(
95 qname,
96 func(actual []string) bool {
97 return len(actual) == 1 && actual[0] == svc.Spec.ClusterIP
98 },
99 "cluster-dns",
100 wait.ForeverTestTimeout,
101 )
102 }
103 })
104 })
105
106 func generateServicesInNamespaces(namespaces []string, num int) []*v1.Service {
107 services := make([]*v1.Service, num)
108 for i := 0; i < num; i++ {
109 services[i] = &v1.Service{
110 ObjectMeta: metav1.ObjectMeta{
111 Name: "svc-" + strconv.Itoa(i),
112 Namespace: namespaces[i%len(namespaces)],
113 },
114 Spec: v1.ServiceSpec{
115 Ports: []v1.ServicePort{{
116 Port: 80,
117 }},
118 },
119 }
120 }
121 return services
122 }
123
View as plain text