Skip to content

Commit 57b79e5

Browse files
committed
Remove any Egress IP from Azure public LB backend
The consensus is to not add egress IP to public load balancer backend pool regardless of the presence of an OutBoundRule. During upgrade this PR let cobtroller removes any egress IP added to public load balancer backend pool previously. Signed-off-by: Arnab Ghosh <[email protected]>
1 parent 4dde249 commit 57b79e5

File tree

7 files changed

+90
-7
lines changed

7 files changed

+90
-7
lines changed

pkg/cloudprovider/aws.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,6 +224,11 @@ func (a *AWS) GetNodeEgressIPConfiguration(node *corev1.Node, cloudPrivateIPConf
224224
return []*NodeEgressIPConfiguration{config}, nil
225225
}
226226

227+
func (a *AWS) SyncLBBackend(_ net.IP, _ *corev1.Node) error {
228+
// We dont add Egress IP to AWS public LB backend; nothing to do
229+
return nil
230+
}
231+
227232
// Unfortunately the AWS API (WaitUntilInstanceRunning) only handles equality
228233
// assertion: so on delete we can't specify and assert that the IP which is
229234
// being removed is completely removed, we are forced to do the inverse, i.e:

pkg/cloudprovider/azure.go

Lines changed: 57 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -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"
@@ -27,6 +25,7 @@ import (
2725
corev1 "k8s.io/api/core/v1"
2826
"k8s.io/klog/v2"
2927
utilnet "k8s.io/utils/net"
28+
"k8s.io/utils/ptr"
3029
)
3130

3231
const (
@@ -52,6 +51,7 @@ type Azure struct {
5251
nodeMapLock sync.Mutex
5352
nodeLockMap map[string]*sync.Mutex
5453
azureWorkloadIdentityEnabled bool
54+
lbBackendPoolSynced bool
5555
}
5656

5757
type 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+
305359
func (a *Azure) createOrUpdate(networkInterface armnetwork.Interface) (*runtime.Poller[armnetwork.InterfacesClientCreateOrUpdateResponse], error) {
306360
ctx, cancel := context.WithTimeout(a.ctx, defaultAzureOperationTimeout)
307361
defer cancel()

pkg/cloudprovider/cloudprovider.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,15 +4,15 @@ import (
44
"context"
55
"errors"
66
"fmt"
7-
apifeatures "github.com/openshift/api/features"
8-
configv1 "github.com/openshift/api/config/v1"
9-
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
107
"net"
118
"os"
129
"path/filepath"
1310
"sync"
1411

1512
v1 "github.com/openshift/api/cloudnetwork/v1"
13+
configv1 "github.com/openshift/api/config/v1"
14+
apifeatures "github.com/openshift/api/features"
15+
"github.com/openshift/library-go/pkg/operator/configobserver/featuregates"
1616
corev1 "k8s.io/api/core/v1"
1717
)
1818

@@ -60,6 +60,10 @@ type CloudProviderIntf interface {
6060
// instance and IP family (AWS), also: the interface is either keyed by name
6161
// (GCP) or ID (Azure, AWS).
6262
GetNodeEgressIPConfiguration(node *corev1.Node, cloudPrivateIPConfigs []*v1.CloudPrivateIPConfig) ([]*NodeEgressIPConfiguration, error)
63+
64+
// SyncLBBackend removes any egress IP which is already added to backend pool of
65+
// a public load balancer. This is mostly Azure specific and may be removed later.
66+
SyncLBBackend(ip net.IP, node *corev1.Node) error
6367
}
6468

6569
// CloudProviderWithMoveIntf is additional interface that can be added to cloud

pkg/cloudprovider/cloudprovider_fake.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,7 @@ func (f *FakeCloudProvider) GetNodeEgressIPConfiguration(node *corev1.Node, clou
6969
}
7070
return nil, nil
7171
}
72+
73+
func (a *FakeCloudProvider) SyncLBBackend(_ net.IP, _ *corev1.Node) error {
74+
return nil
75+
}

pkg/cloudprovider/gcp.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,11 @@ func (g *GCP) GetNodeEgressIPConfiguration(node *corev1.Node, cloudPrivateIPConf
189189
return nil, nil
190190
}
191191

192+
func (a *GCP) SyncLBBackend(_ net.IP, _ *corev1.Node) error {
193+
// We dont add Egress IP to GCP public LB backend; nothing to do
194+
return nil
195+
}
196+
192197
// The GCP zone operations API call. All GCP infrastructure modifications are
193198
// assigned a unique operation ID and are queued in a global/zone operations
194199
// queue. In the case of assignments of private IP addresses to instances, the

pkg/cloudprovider/openstack.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -545,6 +545,11 @@ func (o *OpenStack) GetNodeEgressIPConfiguration(node *corev1.Node, cloudPrivate
545545
return nil, fmt.Errorf("no suitable interface configurations found")
546546
}
547547

548+
func (a *OpenStack) SyncLBBackend(_ net.IP, _ *corev1.Node) error {
549+
// We dont add Egress IP to OpenStack public LB backend; nothing to do
550+
return nil
551+
}
552+
548553
// getNeutronPortNodeEgressIPConfiguration renders the NeutronPortNodeEgressIPConfiguration for a given port.
549554
// The interface is keyed by a neutron UUID.
550555
// If multiple IPv4 repectively multiple IPv6 subnets are attached to the same port, throw an error.

pkg/controller/cloudprivateipconfig/cloudprivateipconfig_controller.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,8 +180,14 @@ func (c *CloudPrivateIPConfigController) SyncHandler(key string) error {
180180

181181
nodeNameToAdd, nodeNameToDel := c.computeOp(cloudPrivateIPConfig)
182182
switch {
183-
// Dequeue on NOOP, there's nothing to do
184183
case nodeNameToAdd == "" && nodeNameToDel == "":
184+
node, err := c.nodesLister.Get(cloudPrivateIPConfig.Spec.Node)
185+
if err != nil {
186+
return err
187+
}
188+
if err := c.cloudProviderClient.SyncLBBackend(ip, node); err != nil {
189+
return fmt.Errorf("error while syncing egress IP %q added to LB backend pool", key)
190+
}
185191
return nil
186192
case nodeNameToAdd != "" && nodeNameToDel != "":
187193
klog.Infof("CloudPrivateIPConfig: %q will be moved from node %q to node %q", key, nodeNameToDel, nodeNameToAdd)

0 commit comments

Comments
 (0)