@@ -262,9 +262,10 @@ type Proxier struct {
262
262
gracefuldeleteManager * GracefulTerminationManager
263
263
}
264
264
265
- // IPGetter helps get node network interface IP
265
+ // IPGetter helps get node network interface IP and IPs binded to the IPVS dummy interface
266
266
type IPGetter interface {
267
267
NodeIPs () ([]net.IP , error )
268
+ BindedIPs () (sets.String , error )
268
269
}
269
270
270
271
// realIPGetter is a real NodeIP handler, it implements IPGetter.
@@ -300,6 +301,11 @@ func (r *realIPGetter) NodeIPs() (ips []net.IP, err error) {
300
301
return ips , nil
301
302
}
302
303
304
+ // BindedIPs returns all addresses that are binded to the IPVS dummy interface kube-ipvs0
305
+ func (r * realIPGetter ) BindedIPs () (sets.String , error ) {
306
+ return r .nl .GetLocalAddresses (DefaultDummyDevice , "" )
307
+ }
308
+
303
309
// Proxier implements proxy.Provider
304
310
var _ proxy.Provider = & Proxier {}
305
311
@@ -1089,6 +1095,11 @@ func (proxier *Proxier) syncProxyRules() {
1089
1095
// activeBindAddrs represents ip address successfully bind to DefaultDummyDevice in this round of sync
1090
1096
activeBindAddrs := map [string ]bool {}
1091
1097
1098
+ bindedAddresses , err := proxier .ipGetter .BindedIPs ()
1099
+ if err != nil {
1100
+ klog .Errorf ("error listing addresses binded to dummy interface, error: %v" , err )
1101
+ }
1102
+
1092
1103
hasNodePort := false
1093
1104
for _ , svc := range proxier .serviceMap {
1094
1105
svcInfo , ok := svc .(* serviceInfo )
@@ -1197,7 +1208,7 @@ func (proxier *Proxier) syncProxyRules() {
1197
1208
serv .Timeout = uint32 (svcInfo .StickyMaxAgeSeconds ())
1198
1209
}
1199
1210
// We need to bind ClusterIP to dummy interface, so set `bindAddr` parameter to `true` in syncService()
1200
- if err := proxier .syncService (svcNameString , serv , true ); err == nil {
1211
+ if err := proxier .syncService (svcNameString , serv , true , bindedAddresses ); err == nil {
1201
1212
activeIPVSServices [serv .String ()] = true
1202
1213
activeBindAddrs [serv .Address .String ()] = true
1203
1214
// ExternalTrafficPolicy only works for NodePort and external LB traffic, does not affect ClusterIP
@@ -1278,7 +1289,7 @@ func (proxier *Proxier) syncProxyRules() {
1278
1289
serv .Flags |= utilipvs .FlagPersistent
1279
1290
serv .Timeout = uint32 (svcInfo .StickyMaxAgeSeconds ())
1280
1291
}
1281
- if err := proxier .syncService (svcNameString , serv , true ); err == nil {
1292
+ if err := proxier .syncService (svcNameString , serv , true , bindedAddresses ); err == nil {
1282
1293
activeIPVSServices [serv .String ()] = true
1283
1294
activeBindAddrs [serv .Address .String ()] = true
1284
1295
@@ -1384,7 +1395,7 @@ func (proxier *Proxier) syncProxyRules() {
1384
1395
serv .Flags |= utilipvs .FlagPersistent
1385
1396
serv .Timeout = uint32 (svcInfo .StickyMaxAgeSeconds ())
1386
1397
}
1387
- if err := proxier .syncService (svcNameString , serv , true ); err == nil {
1398
+ if err := proxier .syncService (svcNameString , serv , true , bindedAddresses ); err == nil {
1388
1399
activeIPVSServices [serv .String ()] = true
1389
1400
activeBindAddrs [serv .Address .String ()] = true
1390
1401
if err := proxier .syncEndpoint (svcName , svcInfo .OnlyNodeLocalEndpoints (), serv ); err != nil {
@@ -1541,7 +1552,7 @@ func (proxier *Proxier) syncProxyRules() {
1541
1552
serv .Timeout = uint32 (svcInfo .StickyMaxAgeSeconds ())
1542
1553
}
1543
1554
// There is no need to bind Node IP to dummy interface, so set parameter `bindAddr` to `false`.
1544
- if err := proxier .syncService (svcNameString , serv , false ); err == nil {
1555
+ if err := proxier .syncService (svcNameString , serv , false , bindedAddresses ); err == nil {
1545
1556
activeIPVSServices [serv .String ()] = true
1546
1557
if err := proxier .syncEndpoint (svcName , svcInfo .OnlyNodeLocalEndpoints (), serv ); err != nil {
1547
1558
klog .Errorf ("Failed to sync endpoint for service: %v, err: %v" , serv , err )
@@ -1922,7 +1933,7 @@ func (proxier *Proxier) deleteEndpointConnections(connectionMap []proxy.ServiceE
1922
1933
}
1923
1934
}
1924
1935
1925
- func (proxier * Proxier ) syncService (svcName string , vs * utilipvs.VirtualServer , bindAddr bool ) error {
1936
+ func (proxier * Proxier ) syncService (svcName string , vs * utilipvs.VirtualServer , bindAddr bool , bindedAddresses sets. String ) error {
1926
1937
appliedVirtualServer , _ := proxier .ipvs .GetVirtualServer (vs )
1927
1938
if appliedVirtualServer == nil || ! appliedVirtualServer .Equal (vs ) {
1928
1939
if appliedVirtualServer == nil {
@@ -1943,16 +1954,22 @@ func (proxier *Proxier) syncService(svcName string, vs *utilipvs.VirtualServer,
1943
1954
}
1944
1955
}
1945
1956
1946
- // bind service address to dummy interface even if service not changed,
1947
- // in case that service IP was removed by other processes
1957
+ // bind service address to dummy interface
1948
1958
if bindAddr {
1959
+ // always attempt to bind if bindedAddresses is nil,
1960
+ // otherwise check if it's already binded and return early
1961
+ if bindedAddresses != nil && bindedAddresses .Has (vs .Address .String ()) {
1962
+ return nil
1963
+ }
1964
+
1949
1965
klog .V (4 ).Infof ("Bind addr %s" , vs .Address .String ())
1950
1966
_ , err := proxier .netlinkHandle .EnsureAddressBind (vs .Address .String (), DefaultDummyDevice )
1951
1967
if err != nil {
1952
1968
klog .Errorf ("Failed to bind service address to dummy device %q: %v" , svcName , err )
1953
1969
return err
1954
1970
}
1955
1971
}
1972
+
1956
1973
return nil
1957
1974
}
1958
1975
0 commit comments