1
2
3
4
19
20 package ipvs
21
22 import (
23 "fmt"
24 "reflect"
25 "testing"
26
27 netutils "k8s.io/utils/net"
28
29 utilipvs "k8s.io/kubernetes/pkg/proxy/ipvs/util"
30 utilipvstest "k8s.io/kubernetes/pkg/proxy/ipvs/util/testing"
31 )
32
33 func Test_GracefulDeleteRS(t *testing.T) {
34 tests := []struct {
35 name string
36 vs *utilipvs.VirtualServer
37 rs *utilipvs.RealServer
38 existingIPVS *utilipvstest.FakeIPVS
39 expectedIPVS *utilipvstest.FakeIPVS
40 err error
41 }{
42 {
43 name: "graceful delete, no connections results in deleting the real server immediatetly",
44 vs: &utilipvs.VirtualServer{
45 Address: netutils.ParseIPSloppy("1.1.1.1"),
46 Protocol: "tcp",
47 Port: uint16(80),
48 },
49 rs: &utilipvs.RealServer{
50 Address: netutils.ParseIPSloppy("10.0.0.1"),
51 Port: uint16(80),
52 Weight: 100,
53 ActiveConn: 0,
54 InactiveConn: 0,
55 },
56 existingIPVS: &utilipvstest.FakeIPVS{
57 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
58 {
59 IP: "1.1.1.1",
60 Port: 80,
61 Protocol: "tcp",
62 }: {
63 Address: netutils.ParseIPSloppy("1.1.1.1"),
64 Protocol: "tcp",
65 Port: uint16(80),
66 },
67 },
68 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
69 {
70 IP: "1.1.1.1",
71 Port: 80,
72 Protocol: "tcp",
73 }: {
74 {
75 Address: netutils.ParseIPSloppy("10.0.0.1"),
76 Port: uint16(80),
77 Weight: 100,
78 ActiveConn: 0,
79 InactiveConn: 0,
80 },
81 },
82 },
83 },
84 expectedIPVS: &utilipvstest.FakeIPVS{
85 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
86 {
87 IP: "1.1.1.1",
88 Port: 80,
89 Protocol: "tcp",
90 }: {
91 Address: netutils.ParseIPSloppy("1.1.1.1"),
92 Protocol: "tcp",
93 Port: uint16(80),
94 },
95 },
96 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
97 {
98 IP: "1.1.1.1",
99 Port: 80,
100 Protocol: "tcp",
101 }: {},
102 },
103 },
104 err: nil,
105 },
106 {
107 name: "graceful delete, real server has active connections, weight should be 0 but don't delete",
108 vs: &utilipvs.VirtualServer{
109 Address: netutils.ParseIPSloppy("1.1.1.1"),
110 Protocol: "tcp",
111 Port: uint16(80),
112 },
113 rs: &utilipvs.RealServer{
114 Address: netutils.ParseIPSloppy("10.0.0.1"),
115 Port: uint16(80),
116 Weight: 100,
117 ActiveConn: 10,
118 InactiveConn: 0,
119 },
120 existingIPVS: &utilipvstest.FakeIPVS{
121 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
122 {
123 IP: "1.1.1.1",
124 Port: 80,
125 Protocol: "tcp",
126 }: {
127 Address: netutils.ParseIPSloppy("1.1.1.1"),
128 Protocol: "tcp",
129 Port: uint16(80),
130 },
131 },
132 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
133 {
134 IP: "1.1.1.1",
135 Port: 80,
136 Protocol: "tcp",
137 }: {
138 {
139 Address: netutils.ParseIPSloppy("10.0.0.1"),
140 Port: uint16(80),
141 Weight: 100,
142 ActiveConn: 10,
143 InactiveConn: 0,
144 },
145 },
146 },
147 },
148 expectedIPVS: &utilipvstest.FakeIPVS{
149 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
150 {
151 IP: "1.1.1.1",
152 Port: 80,
153 Protocol: "tcp",
154 }: {
155 Address: netutils.ParseIPSloppy("1.1.1.1"),
156 Protocol: "tcp",
157 Port: uint16(80),
158 },
159 },
160 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
161 {
162 IP: "1.1.1.1",
163 Port: 80,
164 Protocol: "tcp",
165 }: {
166 {
167 Address: netutils.ParseIPSloppy("10.0.0.1"),
168 Port: uint16(80),
169 Weight: 0,
170 ActiveConn: 10,
171 InactiveConn: 0,
172 },
173 },
174 },
175 },
176 err: nil,
177 },
178 {
179 name: "graceful delete, real server has in-active connections, weight should be 0 but don't delete",
180 vs: &utilipvs.VirtualServer{
181 Address: netutils.ParseIPSloppy("1.1.1.1"),
182 Protocol: "tcp",
183 Port: uint16(80),
184 },
185 rs: &utilipvs.RealServer{
186 Address: netutils.ParseIPSloppy("10.0.0.1"),
187 Port: uint16(80),
188 Weight: 100,
189 ActiveConn: 0,
190 InactiveConn: 10,
191 },
192 existingIPVS: &utilipvstest.FakeIPVS{
193 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
194 {
195 IP: "1.1.1.1",
196 Port: 80,
197 Protocol: "tcp",
198 }: {
199 Address: netutils.ParseIPSloppy("1.1.1.1"),
200 Protocol: "tcp",
201 Port: uint16(80),
202 },
203 },
204 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
205 {
206 IP: "1.1.1.1",
207 Port: 80,
208 Protocol: "tcp",
209 }: {
210 {
211 Address: netutils.ParseIPSloppy("10.0.0.1"),
212 Port: uint16(80),
213 Weight: 100,
214 ActiveConn: 0,
215 InactiveConn: 10,
216 },
217 },
218 },
219 },
220 expectedIPVS: &utilipvstest.FakeIPVS{
221 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
222 {
223 IP: "1.1.1.1",
224 Port: 80,
225 Protocol: "tcp",
226 }: {
227 Address: netutils.ParseIPSloppy("1.1.1.1"),
228 Protocol: "tcp",
229 Port: uint16(80),
230 },
231 },
232 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
233 {
234 IP: "1.1.1.1",
235 Port: 80,
236 Protocol: "tcp",
237 }: {
238 {
239 Address: netutils.ParseIPSloppy("10.0.0.1"),
240 Port: uint16(80),
241 Weight: 0,
242 ActiveConn: 0,
243 InactiveConn: 10,
244 },
245 },
246 },
247 },
248 err: nil,
249 },
250 {
251 name: "graceful delete, real server has connections, but udp connections are deleted immediately",
252 vs: &utilipvs.VirtualServer{
253 Address: netutils.ParseIPSloppy("1.1.1.1"),
254 Protocol: "udp",
255 Port: uint16(80),
256 },
257 rs: &utilipvs.RealServer{
258 Address: netutils.ParseIPSloppy("10.0.0.1"),
259 Port: uint16(80),
260 Weight: 100,
261 ActiveConn: 10,
262 InactiveConn: 10,
263 },
264 existingIPVS: &utilipvstest.FakeIPVS{
265 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
266 {
267 IP: "1.1.1.1",
268 Port: 80,
269 Protocol: "udp",
270 }: {
271 Address: netutils.ParseIPSloppy("1.1.1.1"),
272 Protocol: "udp",
273 Port: uint16(80),
274 },
275 },
276 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
277 {
278 IP: "1.1.1.1",
279 Port: 80,
280 Protocol: "udp",
281 }: {
282 {
283 Address: netutils.ParseIPSloppy("10.0.0.1"),
284 Port: uint16(80),
285 Weight: 100,
286 ActiveConn: 10,
287 InactiveConn: 10,
288 },
289 },
290 },
291 },
292 expectedIPVS: &utilipvstest.FakeIPVS{
293 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
294 {
295 IP: "1.1.1.1",
296 Port: 80,
297 Protocol: "udp",
298 }: {
299 Address: netutils.ParseIPSloppy("1.1.1.1"),
300 Protocol: "udp",
301 Port: uint16(80),
302 },
303 },
304 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
305 {
306 IP: "1.1.1.1",
307 Port: 80,
308 Protocol: "udp",
309 }: {},
310 },
311 },
312 err: nil,
313 },
314 {
315 name: "graceful delete, real server mismatch should be no-op",
316 vs: &utilipvs.VirtualServer{
317 Address: netutils.ParseIPSloppy("1.1.1.1"),
318 Protocol: "tcp",
319 Port: uint16(80),
320 },
321 rs: &utilipvs.RealServer{
322 Address: netutils.ParseIPSloppy("10.0.0.1"),
323 Port: uint16(81),
324 Weight: 100,
325 ActiveConn: 0,
326 InactiveConn: 10,
327 },
328 existingIPVS: &utilipvstest.FakeIPVS{
329 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
330 {
331 IP: "1.1.1.1",
332 Port: 80,
333 Protocol: "tcp",
334 }: {
335 Address: netutils.ParseIPSloppy("1.1.1.1"),
336 Protocol: "tcp",
337 Port: uint16(80),
338 },
339 },
340 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
341 {
342 IP: "1.1.1.1",
343 Port: 80,
344 Protocol: "tcp",
345 }: {
346 {
347 Address: netutils.ParseIPSloppy("10.0.0.1"),
348 Port: uint16(80),
349 Weight: 100,
350 ActiveConn: 0,
351 InactiveConn: 10,
352 },
353 },
354 },
355 },
356 expectedIPVS: &utilipvstest.FakeIPVS{
357 Services: map[utilipvstest.ServiceKey]*utilipvs.VirtualServer{
358 {
359 IP: "1.1.1.1",
360 Port: 80,
361 Protocol: "tcp",
362 }: {
363 Address: netutils.ParseIPSloppy("1.1.1.1"),
364 Protocol: "tcp",
365 Port: uint16(80),
366 },
367 },
368 Destinations: map[utilipvstest.ServiceKey][]*utilipvs.RealServer{
369 {
370 IP: "1.1.1.1",
371 Port: 80,
372 Protocol: "tcp",
373 }: {
374 {
375 Address: netutils.ParseIPSloppy("10.0.0.1"),
376 Port: uint16(80),
377 Weight: 100,
378 ActiveConn: 0,
379 InactiveConn: 10,
380 },
381 },
382 },
383 },
384 err: nil,
385 },
386 }
387
388 for _, test := range tests {
389 t.Run(test.name, func(t *testing.T) {
390 ipvs := test.existingIPVS
391 gracefulTerminationManager := NewGracefulTerminationManager(ipvs)
392
393 err := gracefulTerminationManager.GracefulDeleteRS(test.vs, test.rs)
394 if err != test.err {
395 t.Logf("actual err: %v", err)
396 t.Logf("expected err: %v", test.err)
397 t.Errorf("unexpected error")
398 }
399
400 if !reflect.DeepEqual(ipvs, test.expectedIPVS) {
401 t.Logf("actual: %+v", ipvs)
402 t.Logf("expected : %+v", test.expectedIPVS)
403 t.Errorf("unexpected IPVS servers")
404 }
405 })
406 }
407 }
408
409 func Test_RaceTerminateRSList(t *testing.T) {
410 ipvs := utilipvstest.NewFake()
411 gracefulTerminationManager := NewGracefulTerminationManager(ipvs)
412
413
414 go func() {
415 for i := 1; i <= 10; i++ {
416 for j := 1; j <= 100; j++ {
417 item := makeListItem(i, j)
418 gracefulTerminationManager.rsList.add(item)
419 }
420 }
421 }()
422
423
424 for gracefulTerminationManager.rsList.len() < 20 {
425 }
426
427
428 fakeHandler := func(rsToDelete *listItem) (bool, error) {
429 return true, nil
430 }
431 if !gracefulTerminationManager.rsList.flushList(fakeHandler) {
432 t.Error("failed to flush entries")
433 }
434 }
435
436 func makeListItem(i, j int) *listItem {
437 vs := fmt.Sprintf("%d.%d.%d.%d", 1, 1, i, i)
438 rs := fmt.Sprintf("%d.%d.%d.%d", 1, 1, i, j)
439 return &listItem{
440 VirtualServer: &utilipvs.VirtualServer{
441 Address: netutils.ParseIPSloppy(vs),
442 Protocol: "tcp",
443 Port: uint16(80),
444 },
445 RealServer: &utilipvs.RealServer{
446 Address: netutils.ParseIPSloppy(rs),
447 Port: uint16(80),
448 },
449 }
450 }
451
View as plain text