1
16
17 package network
18
19 import (
20 "context"
21 "fmt"
22 "strconv"
23 "strings"
24
25 v1 "k8s.io/api/core/v1"
26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
27 "k8s.io/apimachinery/pkg/util/sets"
28 utilwait "k8s.io/apimachinery/pkg/util/wait"
29 "k8s.io/kubernetes/pkg/cluster/ports"
30 "k8s.io/kubernetes/test/e2e/feature"
31 "k8s.io/kubernetes/test/e2e/framework"
32 e2enetwork "k8s.io/kubernetes/test/e2e/framework/network"
33 e2enode "k8s.io/kubernetes/test/e2e/framework/node"
34 e2epod "k8s.io/kubernetes/test/e2e/framework/pod"
35 e2eskipper "k8s.io/kubernetes/test/e2e/framework/skipper"
36 e2essh "k8s.io/kubernetes/test/e2e/framework/ssh"
37 "k8s.io/kubernetes/test/e2e/network/common"
38 "k8s.io/kubernetes/test/e2e/storage/utils"
39 admissionapi "k8s.io/pod-security-admission/api"
40
41 "github.com/onsi/ginkgo/v2"
42 )
43
44
45
46
47
48 func checkConnectivityToHost(ctx context.Context, f *framework.Framework, nodeName, podName, host string, port, timeout int) error {
49 command := []string{
50 "nc",
51 "-vz",
52 "-w", strconv.Itoa(timeout),
53 host,
54 strconv.Itoa(port),
55 }
56
57 pod := e2epod.NewAgnhostPod(f.Namespace.Name, podName, nil, nil, nil)
58 pod.Spec.Containers[0].Command = command
59 pod.Spec.Containers[0].Args = nil
60 nodeSelection := e2epod.NodeSelection{Name: nodeName}
61 e2epod.SetNodeSelection(&pod.Spec, nodeSelection)
62 pod.Spec.RestartPolicy = v1.RestartPolicyNever
63
64 podClient := f.ClientSet.CoreV1().Pods(f.Namespace.Name)
65 _, err := podClient.Create(ctx, pod, metav1.CreateOptions{})
66 if err != nil {
67 return err
68 }
69 err = e2epod.WaitForPodSuccessInNamespace(ctx, f.ClientSet, podName, f.Namespace.Name)
70
71 if err != nil {
72 logs, logErr := e2epod.GetPodLogs(ctx, f.ClientSet, f.Namespace.Name, pod.Name, pod.Spec.Containers[0].Name)
73 if logErr != nil {
74 framework.Logf("Warning: Failed to get logs from pod %q: %v", pod.Name, logErr)
75 } else {
76 framework.Logf("pod %s/%s logs:\n%s", f.Namespace.Name, pod.Name, logs)
77 }
78 }
79
80 return err
81 }
82
83 var _ = common.SIGDescribe("Networking", func() {
84 var svcname = "nettest"
85 f := framework.NewDefaultFramework(svcname)
86 f.NamespacePodSecurityLevel = admissionapi.LevelPrivileged
87
88 f.It("should provide Internet connection for containers", feature.NetworkingIPv4, func(ctx context.Context) {
89 ginkgo.By("Running container which tries to connect to 8.8.8.8")
90 framework.ExpectNoError(
91 checkConnectivityToHost(ctx, f, "", "connectivity-test", "8.8.8.8", 53, 30))
92 })
93
94 f.It("should provide Internet connection for containers", feature.NetworkingIPv6, "[Experimental][LinuxOnly]", func(ctx context.Context) {
95
96 e2eskipper.SkipIfNodeOSDistroIs("windows")
97 ginkgo.By("Running container which tries to connect to 2001:4860:4860::8888")
98 framework.ExpectNoError(
99 checkConnectivityToHost(ctx, f, "", "connectivity-test", "2001:4860:4860::8888", 53, 30))
100 })
101
102 f.It("should provider Internet connection for containers using DNS", feature.NetworkingDNS, func(ctx context.Context) {
103 ginkgo.By("Running container which tries to connect to google.com")
104 framework.ExpectNoError(
105 checkConnectivityToHost(ctx, f, "", "connectivity-test", "google.com", 80, 30))
106 })
107
108
109 ginkgo.It("should provide unchanging, static URL paths for kubernetes api services", func(ctx context.Context) {
110 tests := []struct {
111 path string
112 }{
113 {path: "/healthz"},
114 {path: "/api"},
115 {path: "/apis"},
116 {path: "/metrics"},
117 {path: "/openapi/v2"},
118 {path: "/version"},
119
120 }
121 if !framework.ProviderIs("gke", "skeleton") {
122 tests = append(tests, struct{ path string }{path: "/logs"})
123 }
124 for _, test := range tests {
125 ginkgo.By(fmt.Sprintf("testing: %s", test.path))
126 data, err := f.ClientSet.CoreV1().RESTClient().Get().
127 AbsPath(test.path).
128 DoRaw(ctx)
129 if err != nil {
130 framework.Failf("ginkgo.Failed: %v\nBody: %s", err, string(data))
131 }
132 }
133 })
134
135 ginkgo.It("should check kube-proxy urls", func(ctx context.Context) {
136
137
138 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork)
139
140 ginkgo.By("checking kube-proxy URLs")
141 config.GetSelfURL(ctx, ports.ProxyHealthzPort, "/healthz", "200 OK")
142
143 config.GetSelfURL(ctx, ports.ProxyHealthzPort, "/healthz", "lastUpdated")
144
145 config.GetSelfURLStatusCode(ctx, ports.ProxyStatusPort, "/proxyMode", "200")
146 })
147
148 ginkgo.Describe("Granular Checks: Services", func() {
149
150 ginkgo.It("should function for pod-Service: http", func(ctx context.Context) {
151 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
152 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
153 err := config.DialFromTestContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
154 if err != nil {
155 framework.Failf("failed dialing endpoint, %v", err)
156 }
157 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (nodeIP)", config.TestContainerPod.Name, config.NodeIP, config.NodeHTTPPort))
158
159 err = config.DialFromTestContainer(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
160 if err != nil {
161 framework.Failf("failed dialing endpoint, %v", err)
162 }
163 })
164
165 ginkgo.It("should function for pod-Service: udp", func(ctx context.Context) {
166 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
167 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
168 err := config.DialFromTestContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
169 if err != nil {
170 framework.Failf("failed dialing endpoint, %v", err)
171 }
172
173 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (nodeIP)", config.TestContainerPod.Name, config.NodeIP, config.NodeUDPPort))
174 err = config.DialFromTestContainer(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
175 if err != nil {
176 framework.Failf("failed dialing endpoint, %v", err)
177 }
178 })
179
180 f.It("should function for pod-Service: sctp", feature.SCTPConnectivity, func(ctx context.Context) {
181 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.EnableSCTP)
182 ginkgo.By(fmt.Sprintf("dialing(sctp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterSCTPPort))
183 err := config.DialFromTestContainer(ctx, "sctp", config.ClusterIP, e2enetwork.ClusterSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
184 if err != nil {
185 framework.Failf("failed dialing endpoint, %v", err)
186 }
187 ginkgo.By(fmt.Sprintf("dialing(sctp) %v --> %v:%v (nodeIP)", config.TestContainerPod.Name, config.NodeIP, config.NodeSCTPPort))
188 err = config.DialFromTestContainer(ctx, "sctp", config.NodeIP, config.NodeSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
189 if err != nil {
190 framework.Failf("failed dialing endpoint, %v", err)
191 }
192 })
193
194 ginkgo.It("should function for node-Service: http", func(ctx context.Context) {
195 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork)
196 ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterHTTPPort))
197 err := config.DialFromNode(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
198 if err != nil {
199 framework.Failf("failed dialing endpoint, %v", err)
200 }
201 ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeHTTPPort))
202 err = config.DialFromNode(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
203 if err != nil {
204 framework.Failf("failed dialing endpoint, %v", err)
205 }
206 })
207
208 ginkgo.It("should function for node-Service: udp", func(ctx context.Context) {
209 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork)
210 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterUDPPort))
211 err := config.DialFromNode(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
212 if err != nil {
213 framework.Failf("failed dialing endpoint, %v", err)
214 }
215 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeUDPPort))
216 err = config.DialFromNode(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
217 if err != nil {
218 framework.Failf("failed dialing endpoint, %v", err)
219 }
220 })
221
222 f.It("should function for node-Service: sctp", feature.SCTPConnectivity, func(ctx context.Context) {
223 ginkgo.Skip("Skipping SCTP node to service test until DialFromNode supports SCTP #96482")
224 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.EnableSCTP)
225 ginkgo.By(fmt.Sprintf("dialing(sctp) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterSCTPPort))
226 err := config.DialFromNode(ctx, "sctp", config.ClusterIP, e2enetwork.ClusterSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
227 if err != nil {
228 framework.Failf("failed dialing endpoint, %v", err)
229 }
230 ginkgo.By(fmt.Sprintf("dialing(sctp) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeSCTPPort))
231 err = config.DialFromNode(ctx, "sctp", config.NodeIP, config.NodeSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
232 if err != nil {
233 framework.Failf("failed dialing endpoint, %v", err)
234 }
235 })
236
237 ginkgo.It("should function for endpoint-Service: http", func(ctx context.Context) {
238 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
239 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
240 err := config.DialFromEndpointContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
241 if err != nil {
242 framework.Failf("failed dialing endpoint, %v", err)
243 }
244 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, config.NodeHTTPPort))
245 err = config.DialFromEndpointContainer(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
246 if err != nil {
247 framework.Failf("failed dialing endpoint, %v", err)
248 }
249 })
250
251 ginkgo.It("should function for endpoint-Service: udp", func(ctx context.Context) {
252 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
253 ginkgo.By(fmt.Sprintf("dialing(udp) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
254 err := config.DialFromEndpointContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
255 if err != nil {
256 framework.Failf("failed dialing endpoint, %v", err)
257 }
258
259 ginkgo.By(fmt.Sprintf("dialing(udp) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, config.NodeUDPPort))
260 err = config.DialFromEndpointContainer(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
261 if err != nil {
262 framework.Failf("failed dialing endpoint, %v", err)
263 }
264 })
265
266 f.It("should function for endpoint-Service: sctp", feature.SCTPConnectivity, func(ctx context.Context) {
267 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.EnableSCTP)
268 ginkgo.By(fmt.Sprintf("dialing(sctp) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterSCTPPort))
269 err := config.DialFromEndpointContainer(ctx, "sctp", config.ClusterIP, e2enetwork.ClusterSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
270 if err != nil {
271 framework.Failf("failed dialing endpoint, %v", err)
272 }
273
274 ginkgo.By(fmt.Sprintf("dialing(sctp) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, config.NodeSCTPPort))
275 err = config.DialFromEndpointContainer(ctx, "sctp", config.NodeIP, config.NodeSCTPPort, config.MaxTries, 0, config.EndpointHostnames())
276 if err != nil {
277 framework.Failf("failed dialing endpoint, %v", err)
278 }
279 })
280
281
282
283 ginkgo.It("should function for multiple endpoint-Services with same selector", func(ctx context.Context) {
284 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
285 ginkgo.By("creating a second service with same selector")
286 svc2, httpPort := createSecondNodePortService(ctx, f, config)
287
288
289 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (config.clusterIP)", config.EndpointPods[0].Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
290 err := config.DialFromEndpointContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
291 if err != nil {
292 framework.Failf("failed dialing endpoint, %v", err)
293 }
294 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, config.NodeHTTPPort))
295 err = config.DialFromEndpointContainer(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
296 if err != nil {
297 framework.Failf("failed dialing endpoint, %v", err)
298 }
299
300 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (svc2.clusterIP)", config.EndpointPods[0].Name, svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
301 err = config.DialFromEndpointContainer(ctx, "http", svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
302 if err != nil {
303 framework.Failf("failed dialing endpoint, %v", err)
304 }
305
306 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, httpPort))
307 err = config.DialFromEndpointContainer(ctx, "http", config.NodeIP, httpPort, config.MaxTries, 0, config.EndpointHostnames())
308 if err != nil {
309 framework.Failf("failed dialing endpoint, %v", err)
310 }
311
312 ginkgo.By("deleting the original node port service")
313 config.DeleteNodePortService(ctx)
314
315
316 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (svc2.clusterIP)", config.EndpointPods[0].Name, svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
317 err = config.DialFromEndpointContainer(ctx, "http", svc2.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
318 if err != nil {
319 framework.Failf("failed dialing endpoint, %v", err)
320 }
321 ginkgo.By(fmt.Sprintf("dialing(http) %v (endpoint) --> %v:%v (nodeIP)", config.EndpointPods[0].Name, config.NodeIP, httpPort))
322 err = config.DialFromEndpointContainer(ctx, "http", config.NodeIP, httpPort, config.MaxTries, 0, config.EndpointHostnames())
323 if err != nil {
324 framework.Failf("failed dialing endpoint, %v", err)
325 }
326 })
327
328 ginkgo.It("should update endpoints: http", func(ctx context.Context) {
329 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
330 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
331 err := config.DialFromTestContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
332 if err != nil {
333 framework.Failf("failed dialing endpoint (initial), %v", err)
334 }
335 ginkgo.By("Deleting a pod which, will be replaced with a new endpoint")
336 config.DeleteNetProxyPod(ctx)
337
338 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP) (endpoint recovery)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
339 err = config.DialFromTestContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, config.MaxTries, config.EndpointHostnames())
340 if err != nil {
341 framework.Failf("failed dialing endpoint (recovery), %v", err)
342 }
343 })
344
345 ginkgo.It("should update endpoints: udp", func(ctx context.Context) {
346 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
347 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
348 err := config.DialFromTestContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
349 if err != nil {
350 framework.Failf("failed dialing endpoint (initial), %v", err)
351 }
352 ginkgo.By("Deleting a pod which, will be replaced with a new endpoint")
353 config.DeleteNetProxyPod(ctx)
354
355 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP) (endpoint recovery)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
356 err = config.DialFromTestContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, config.MaxTries, config.EndpointHostnames())
357 if err != nil {
358 framework.Failf("failed dialing endpoint (recovery), %v", err)
359 }
360 })
361
362
363 f.It("should update nodePort: http", f.WithSlow(), func(ctx context.Context) {
364 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork)
365 ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (ctx, nodeIP) and getting ALL host endpoints", config.NodeIP, config.NodeIP, config.NodeHTTPPort))
366 err := config.DialFromNode(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
367 if err != nil {
368 framework.Failf("Error dialing http from node: %v", err)
369 }
370 ginkgo.By("Deleting the node port access point")
371 config.DeleteNodePortService(ctx)
372
373 ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (nodeIP) and getting ZERO host endpoints", config.NodeIP, config.NodeIP, config.NodeHTTPPort))
374
375
376
377 err = config.DialFromNode(ctx, "http", config.NodeIP, config.NodeHTTPPort, 10, 10, sets.NewString())
378 if err != nil {
379 framework.Failf("Failure validating that node port service STOPPED removed properly: %v", err)
380 }
381 })
382
383
384 ginkgo.It("should support basic nodePort: udp functionality", func(ctx context.Context) {
385 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork)
386 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP) and getting ALL host endpoints", config.NodeIP, config.NodeIP, config.NodeUDPPort))
387 err := config.DialFromNode(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
388 if err != nil {
389 framework.Failf("Failure validating that nodePort service WAS forwarding properly: %v", err)
390 }
391 })
392
393
394 f.It("should update nodePort: udp", f.WithSlow(), func(ctx context.Context) {
395 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork)
396 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP) and getting ALL host endpoints", config.NodeIP, config.NodeIP, config.NodeUDPPort))
397 err := config.DialFromNode(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
398 if err != nil {
399 framework.Failf("Failure validating that nodePort service WAS forwarding properly: %v", err)
400 }
401
402 ginkgo.By("Deleting the node port access point")
403 config.DeleteNodePortService(ctx)
404
405 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP) and getting ZERO host endpoints", config.NodeIP, config.NodeIP, config.NodeUDPPort))
406
407
408
409 err = config.DialFromNode(ctx, "udp", config.NodeIP, config.NodeUDPPort, 10, 10, sets.NewString())
410 if err != nil {
411 framework.Failf("Failure validating that node port service STOPPED removed properly: %v", err)
412 }
413 })
414
415
416 ginkgo.It("should function for client IP based session affinity: http [LinuxOnly]", func(ctx context.Context) {
417 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
418 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v", config.TestContainerPod.Name, config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterHTTPPort))
419
420
421 eps, err := config.GetEndpointsFromTestContainer(ctx, "http", config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterHTTPPort, e2enetwork.SessionAffinityChecks)
422 if err != nil {
423 framework.Failf("ginkgo.Failed to get endpoints from test container, error: %v", err)
424 }
425 if len(eps) == 0 {
426 framework.Failf("Unexpected no endpoints return")
427 }
428 if len(eps) > 1 {
429 framework.Failf("Unexpected endpoints return: %v, expect 1 endpoints", eps)
430 }
431 })
432
433
434 ginkgo.It("should function for client IP based session affinity: udp [LinuxOnly]", func(ctx context.Context) {
435 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
436 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v", config.TestContainerPod.Name, config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterUDPPort))
437
438
439 eps, err := config.GetEndpointsFromTestContainer(ctx, "udp", config.SessionAffinityService.Spec.ClusterIP, e2enetwork.ClusterUDPPort, e2enetwork.SessionAffinityChecks)
440 if err != nil {
441 framework.Failf("ginkgo.Failed to get endpoints from test container, error: %v", err)
442 }
443 if len(eps) == 0 {
444 framework.Failf("Unexpected no endpoints return")
445 }
446 if len(eps) > 1 {
447 framework.Failf("Unexpected endpoints return: %v, expect 1 endpoints", eps)
448 }
449 })
450
451 ginkgo.It("should be able to handle large requests: http", func(ctx context.Context) {
452 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
453 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
454 message := strings.Repeat("42", 1000)
455 err := config.DialEchoFromTestContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, message)
456 if err != nil {
457 framework.Failf("failed dialing endpoint, %v", err)
458 }
459 })
460
461 ginkgo.It("should be able to handle large requests: udp", func(ctx context.Context) {
462 config := e2enetwork.NewNetworkingTestConfig(ctx, f)
463 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
464 message := "n" + strings.Repeat("o", 1999)
465 err := config.DialEchoFromTestContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, message)
466 if err != nil {
467 framework.Failf("failed dialing endpoint, %v", err)
468 }
469 })
470
471
472
473
474 ginkgo.It("should function for service endpoints using hostNetwork", func(ctx context.Context) {
475 config := e2enetwork.NewNetworkingTestConfig(ctx, f, e2enetwork.UseHostNetwork, e2enetwork.EndpointsUseHostNetwork)
476
477 ginkgo.By("pod-Service(hostNetwork): http")
478
479 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
480 err := config.DialFromTestContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
481 if err != nil {
482 framework.Failf("failed dialing endpoint, %v", err)
483 }
484 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (nodeIP)", config.TestContainerPod.Name, config.NodeIP, config.NodeHTTPPort))
485 err = config.DialFromTestContainer(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
486 if err != nil {
487 framework.Failf("failed dialing endpoint, %v", err)
488 }
489
490 ginkgo.By("pod-Service(hostNetwork): udp")
491
492 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
493 err = config.DialFromTestContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
494 if err != nil {
495 framework.Failf("failed dialing endpoint, %v", err)
496 }
497
498 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (nodeIP)", config.TestContainerPod.Name, config.NodeIP, config.NodeUDPPort))
499 err = config.DialFromTestContainer(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
500 if err != nil {
501 framework.Failf("failed dialing endpoint, %v", err)
502 }
503
504 ginkgo.By("node-Service(hostNetwork): http")
505
506 ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterHTTPPort))
507 err = config.DialFromNode(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
508 if err != nil {
509 framework.Failf("failed dialing endpoint, %v", err)
510 }
511 ginkgo.By(fmt.Sprintf("dialing(http) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeHTTPPort))
512 err = config.DialFromNode(ctx, "http", config.NodeIP, config.NodeHTTPPort, config.MaxTries, 0, config.EndpointHostnames())
513 if err != nil {
514 framework.Failf("failed dialing endpoint, %v", err)
515 }
516 ginkgo.By("node-Service(hostNetwork): udp")
517
518 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (config.clusterIP)", config.NodeIP, config.ClusterIP, e2enetwork.ClusterUDPPort))
519 err = config.DialFromNode(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, config.EndpointHostnames())
520 if err != nil {
521 framework.Failf("failed dialing endpoint, %v", err)
522 }
523 ginkgo.By(fmt.Sprintf("dialing(udp) %v (node) --> %v:%v (nodeIP)", config.NodeIP, config.NodeIP, config.NodeUDPPort))
524 err = config.DialFromNode(ctx, "udp", config.NodeIP, config.NodeUDPPort, config.MaxTries, 0, config.EndpointHostnames())
525 if err != nil {
526 framework.Failf("failed dialing endpoint, %v", err)
527 }
528
529 ginkgo.By("handle large requests: http(hostNetwork)")
530
531 ginkgo.By(fmt.Sprintf("dialing(http) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterHTTPPort))
532 message := strings.Repeat("42", 1000)
533 err = config.DialEchoFromTestContainer(ctx, "http", config.ClusterIP, e2enetwork.ClusterHTTPPort, config.MaxTries, 0, message)
534 if err != nil {
535 framework.Failf("failed dialing endpoint, %v", err)
536 }
537
538 ginkgo.By("handle large requests: udp(hostNetwork)")
539
540 ginkgo.By(fmt.Sprintf("dialing(udp) %v --> %v:%v (config.clusterIP)", config.TestContainerPod.Name, config.ClusterIP, e2enetwork.ClusterUDPPort))
541 message = "n" + strings.Repeat("o", 1999)
542 err = config.DialEchoFromTestContainer(ctx, "udp", config.ClusterIP, e2enetwork.ClusterUDPPort, config.MaxTries, 0, message)
543 if err != nil {
544 framework.Failf("failed dialing endpoint, %v", err)
545 }
546
547 })
548
549 })
550
551 f.It("should recreate its iptables rules if they are deleted", f.WithDisruptive(), func(ctx context.Context) {
552 e2eskipper.SkipUnlessProviderIs(framework.ProvidersWithSSH...)
553 e2eskipper.SkipUnlessSSHKeyPresent()
554
555 hosts, err := e2essh.NodeSSHHosts(ctx, f.ClientSet)
556 framework.ExpectNoError(err, "failed to find external/internal IPs for every node")
557 if len(hosts) == 0 {
558 framework.Failf("No ssh-able nodes")
559 }
560 host := hosts[0]
561
562 ns := f.Namespace.Name
563 numPods, servicePort := 3, defaultServeHostnameServicePort
564 svc := "iptables-flush-test"
565
566 ginkgo.DeferCleanup(StopServeHostnameService, f.ClientSet, ns, svc)
567 podNames, svcIP, err := StartServeHostnameService(ctx, f.ClientSet, getServeHostnameService(svc), ns, numPods)
568 framework.ExpectNoError(err, "failed to create replication controller with service: %s in the namespace: %s", svc, ns)
569
570
571
572
573
574
575 ginkgo.By("dumping iptables rules on node " + host)
576 result, err := e2essh.SSH(ctx, "sudo iptables-save", host, framework.TestContext.Provider)
577 e2essh.LogResult(result)
578 if err != nil || result.Code != 0 {
579 framework.Failf("couldn't dump iptable rules: %v", err)
580 }
581
582
583
584
585 var deleteRuleCmds, deleteChainCmds []string
586 table := ""
587 for _, line := range strings.Split(result.Stdout, "\n") {
588 if strings.HasPrefix(line, "*") {
589 table = line[1:]
590 } else if table == "" {
591 continue
592 }
593
594
595 if !strings.HasPrefix(line, "-A KUBE-") && strings.Contains(line, "-j KUBE-") {
596 deleteRuleCmds = append(deleteRuleCmds, fmt.Sprintf("sudo iptables -t %s -D %s || true", table, line[3:]))
597 }
598
599 if strings.HasPrefix(line, ":KUBE-") {
600 chain := strings.Split(line, " ")[0][1:]
601 deleteRuleCmds = append(deleteRuleCmds, fmt.Sprintf("sudo iptables -t %s -F %s || true", table, chain))
602 deleteChainCmds = append(deleteChainCmds, fmt.Sprintf("sudo iptables -t %s -X %s || true", table, chain))
603 }
604 }
605 cmd := strings.Join(append(deleteRuleCmds, deleteChainCmds...), "\n")
606
607 ginkgo.By("deleting all KUBE-* iptables chains")
608 result, err = e2essh.SSH(ctx, cmd, host, framework.TestContext.Provider)
609 if err != nil || result.Code != 0 {
610 e2essh.LogResult(result)
611 framework.Failf("couldn't delete iptable rules: %v", err)
612 }
613
614 ginkgo.By("verifying that kube-proxy rules are eventually recreated")
615 framework.ExpectNoError(verifyServeHostnameServiceUp(ctx, f.ClientSet, ns, podNames, svcIP, servicePort))
616
617 ginkgo.By("verifying that kubelet rules are eventually recreated")
618 err = utilwait.PollImmediate(framework.Poll, framework.RestartNodeReadyAgainTimeout, func() (bool, error) {
619 result, err = e2essh.SSH(ctx, "sudo iptables-save -t mangle", host, framework.TestContext.Provider)
620 if err != nil || result.Code != 0 {
621 e2essh.LogResult(result)
622 return false, err
623 }
624
625 if strings.Contains(result.Stdout, "\n:KUBE-IPTABLES-HINT") {
626 return true, nil
627 }
628 return false, nil
629 })
630 if err != nil {
631 e2essh.LogResult(result)
632 }
633 framework.ExpectNoError(err, "kubelet did not recreate its iptables rules")
634 })
635
636
637
638 f.It("should allow creating a Pod with an SCTP HostPort [LinuxOnly]", f.WithSerial(), func(ctx context.Context) {
639 node, err := e2enode.GetRandomReadySchedulableNode(ctx, f.ClientSet)
640 framework.ExpectNoError(err)
641 hostExec := utils.NewHostExec(f)
642 ginkgo.DeferCleanup(hostExec.Cleanup)
643
644 ginkgo.By("getting the state of the sctp module on the selected node")
645 nodes := &v1.NodeList{}
646 nodes.Items = append(nodes.Items, *node)
647 sctpLoadedAtStart := CheckSCTPModuleLoadedOnNodes(ctx, f, nodes)
648
649 ginkgo.By("creating a pod with hostport on the selected node")
650 podName := "hostport"
651 ports := []v1.ContainerPort{{Protocol: v1.ProtocolSCTP, ContainerPort: 5060, HostPort: 5060}}
652 podSpec := e2epod.NewAgnhostPod(f.Namespace.Name, podName, nil, nil, ports)
653 nodeSelection := e2epod.NodeSelection{Name: node.Name}
654 e2epod.SetNodeSelection(&podSpec.Spec, nodeSelection)
655
656 ginkgo.By(fmt.Sprintf("Launching the pod on node %v", node.Name))
657 e2epod.NewPodClient(f).CreateSync(ctx, podSpec)
658 ginkgo.DeferCleanup(func(ctx context.Context) {
659 err := f.ClientSet.CoreV1().Pods(f.Namespace.Name).Delete(ctx, podName, metav1.DeleteOptions{})
660 framework.ExpectNoError(err, "failed to delete pod: %s in namespace: %s", podName, f.Namespace.Name)
661 })
662 ginkgo.By("validating sctp module is still not loaded")
663 sctpLoadedAtEnd := CheckSCTPModuleLoadedOnNodes(ctx, f, nodes)
664 if !sctpLoadedAtStart && sctpLoadedAtEnd {
665 framework.Failf("The state of the sctp module has changed due to the test case")
666 }
667 })
668 })
669
View as plain text