@@ -9,13 +9,11 @@ import (
99 "sync"
1010 "time"
1111
12- "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
13- "k8s.io/utils/ptr"
14-
1512 "github.com/Azure/azure-sdk-for-go/sdk/azcore"
1613 "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
1714 "github.com/Azure/azure-sdk-for-go/sdk/azcore/cloud"
1815 "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
16+ "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
1917 "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
2018 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/compute/armcompute"
2119 "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/network/armnetwork/v6"
@@ -26,6 +24,7 @@ import (
2624 corev1 "k8s.io/api/core/v1"
2725 "k8s.io/klog/v2"
2826 utilnet "k8s.io/utils/net"
27+ "k8s.io/utils/ptr"
2928)
3029
3130const (
@@ -51,6 +50,7 @@ type Azure struct {
5150 nodeMapLock sync.Mutex
5251 nodeLockMap map [string ]* sync.Mutex
5352 azureWorkloadIdentityEnabled bool
53+ lbBackendPoolSynced bool
5454}
5555
5656type azureCredentialsConfig struct {
@@ -302,6 +302,60 @@ func (a *Azure) GetNodeEgressIPConfiguration(node *corev1.Node, cloudPrivateIPCo
302302 return []* NodeEgressIPConfiguration {config }, nil
303303}
304304
305+ // The consensus is to not add egress IP to public load balancer
306+ // backend pool regardless of the presence of an OutBoundRule.
307+ // During upgrade this function removes any egress IP added to
308+ // public load balancer backend pool previously.
309+ func (a * Azure ) SyncLBBackend (ip net.IP , node * corev1.Node ) error {
310+ if a .lbBackendPoolSynced {
311+ // nothing to do. Return immediately if LB backend has already synced
312+ return nil
313+ }
314+ ipc := ip .String ()
315+ klog .Infof ("Acquiring node lock for modifying load balancer backend pool, node: %s, ip: %s" , node .Name , ipc )
316+ nodeLock := a .getNodeLock (node .Name )
317+ nodeLock .Lock ()
318+ defer nodeLock .Unlock ()
319+ instance , err := a .getInstance (node )
320+ if err != nil {
321+ return err
322+ }
323+ networkInterfaces , err := a .getNetworkInterfaces (instance )
324+ if err != nil {
325+ return err
326+ }
327+ if networkInterfaces [0 ].Properties == nil {
328+ return fmt .Errorf ("nil network interface properties" )
329+ }
330+ // Perform the operation against the first interface listed, which will be
331+ // the primary interface (if it's defined as such) or the first one returned
332+ // following the order Azure specifies.
333+ networkInterface := networkInterfaces [0 ]
334+ var loadBalanceerBackendPoolModified bool
335+ // omit Egress IP from LB backend pool
336+ ipConfigurations := networkInterface .Properties .IPConfigurations
337+ for _ , ipCfg := range ipConfigurations {
338+ if ptr .Deref (ipCfg .Properties .PrivateIPAddress , "" ) == ipc &&
339+ ipCfg .Properties .LoadBalancerBackendAddressPools != nil {
340+ ipCfg .Properties .LoadBalancerBackendAddressPools = nil
341+ loadBalanceerBackendPoolModified = true
342+ }
343+ }
344+ if loadBalanceerBackendPoolModified {
345+ networkInterface .Properties .IPConfigurations = ipConfigurations
346+ poller , err := a .createOrUpdate (networkInterface )
347+ if err != nil {
348+ return err
349+ }
350+ if err = a .waitForCompletion (poller ); err != nil {
351+ return err
352+ }
353+ a .lbBackendPoolSynced = true
354+ return nil
355+ }
356+ return nil
357+ }
358+
305359func (a * Azure ) createOrUpdate (networkInterface armnetwork.Interface ) (* runtime.Poller [armnetwork.InterfacesClientCreateOrUpdateResponse ], error ) {
306360 ctx , cancel := context .WithTimeout (a .ctx , defaultAzureOperationTimeout )
307361 defer cancel ()
0 commit comments