Skip to content

Commit ebdc3ad

Browse files
committed
SPLAT-2113: spike NLB with SGs when annotation is present
1 parent 425c1c5 commit ebdc3ad

File tree

2 files changed

+101
-30
lines changed

2 files changed

+101
-30
lines changed

pkg/providers/v1/aws.go

Lines changed: 59 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2255,6 +2255,22 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
22552255
instanceIDs = append(instanceIDs, string(id))
22562256
}
22572257

2258+
// TODO: get the list of SGs when it requires to add it (only if NLB was created with one)
2259+
// Check if SG annotation has been added and SG exists, then build the required permissions.
2260+
if _, present := annotations[ServiceAnnotationLoadBalancerSecurityGroups]; present {
2261+
securityGroups, _, err := c.buildELBSecurityGroupList(serviceName, loadBalancerName, annotations)
2262+
if err != nil {
2263+
return nil, err
2264+
}
2265+
if len(securityGroups) == 0 {
2266+
return nil, fmt.Errorf("NLB must be created with an Security Group to allow syncronization, please recrease the service with a security group")
2267+
}
2268+
permissions := buildSecuritySecurityGroupPermissions(apiService, sourceRanges)
2269+
if _, err = c.setSecurityGroupIngress(securityGroups[0], permissions); err != nil {
2270+
return nil, err
2271+
}
2272+
}
2273+
22582274
v2LoadBalancer, err := c.ensureLoadBalancerv2(
22592275
serviceName,
22602276
loadBalancerName,
@@ -2435,36 +2451,7 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
24352451
}
24362452

24372453
if setupSg {
2438-
ec2SourceRanges := []*ec2.IpRange{}
2439-
for _, sourceRange := range sourceRanges.StringSlice() {
2440-
ec2SourceRanges = append(ec2SourceRanges, &ec2.IpRange{CidrIp: aws.String(sourceRange)})
2441-
}
2442-
2443-
permissions := NewIPPermissionSet()
2444-
for _, port := range apiService.Spec.Ports {
2445-
portInt64 := int64(port.Port)
2446-
protocol := strings.ToLower(string(port.Protocol))
2447-
2448-
permission := &ec2.IpPermission{}
2449-
permission.FromPort = &portInt64
2450-
permission.ToPort = &portInt64
2451-
permission.IpRanges = ec2SourceRanges
2452-
permission.IpProtocol = &protocol
2453-
2454-
permissions.Insert(permission)
2455-
}
2456-
2457-
// Allow ICMP fragmentation packets, important for MTU discovery
2458-
{
2459-
permission := &ec2.IpPermission{
2460-
IpProtocol: aws.String("icmp"),
2461-
FromPort: aws.Int64(3),
2462-
ToPort: aws.Int64(4),
2463-
IpRanges: ec2SourceRanges,
2464-
}
2465-
2466-
permissions.Insert(permission)
2467-
}
2454+
permissions := buildSecuritySecurityGroupPermissions(apiService, sourceRanges)
24682455
_, err = c.setSecurityGroupIngress(securityGroupIDs[0], permissions)
24692456
if err != nil {
24702457
return nil, err
@@ -2573,6 +2560,41 @@ func (c *Cloud) EnsureLoadBalancer(ctx context.Context, clusterName string, apiS
25732560
return status, nil
25742561
}
25752562

2563+
func buildSecuritySecurityGroupPermissions(apiService *v1.Service, sourceRanges netutils.IPNetSet) IPPermissionSet {
2564+
ec2SourceRanges := []*ec2.IpRange{}
2565+
for _, sourceRange := range sourceRanges.StringSlice() {
2566+
ec2SourceRanges = append(ec2SourceRanges, &ec2.IpRange{CidrIp: aws.String(sourceRange)})
2567+
}
2568+
2569+
permissions := NewIPPermissionSet()
2570+
for _, port := range apiService.Spec.Ports {
2571+
portInt64 := int64(port.Port)
2572+
protocol := strings.ToLower(string(port.Protocol))
2573+
2574+
permission := &ec2.IpPermission{}
2575+
permission.FromPort = &portInt64
2576+
permission.ToPort = &portInt64
2577+
permission.IpRanges = ec2SourceRanges
2578+
permission.IpProtocol = &protocol
2579+
2580+
permissions.Insert(permission)
2581+
}
2582+
2583+
// Allow ICMP fragmentation packets, important for MTU discovery
2584+
{
2585+
permission := &ec2.IpPermission{
2586+
IpProtocol: aws.String("icmp"),
2587+
FromPort: aws.Int64(3),
2588+
ToPort: aws.Int64(4),
2589+
IpRanges: ec2SourceRanges,
2590+
}
2591+
2592+
permissions.Insert(permission)
2593+
}
2594+
2595+
return permissions
2596+
}
2597+
25762598
// GetLoadBalancer is an implementation of LoadBalancer.GetLoadBalancer
25772599
func (c *Cloud) GetLoadBalancer(ctx context.Context, clusterName string, service *v1.Service) (*v1.LoadBalancerStatus, bool, error) {
25782600
if isLBExternal(service.Annotations) {
@@ -2898,6 +2920,8 @@ func (c *Cloud) EnsureLoadBalancerDeleted(ctx context.Context, clusterName strin
28982920
}
28992921
}
29002922

2923+
// TODO add delete SG
2924+
29012925
return c.updateInstanceSecurityGroupsForNLB(loadBalancerName, nil, nil, nil, nil)
29022926
}
29032927

@@ -3068,6 +3092,11 @@ func (c *Cloud) UpdateLoadBalancer(ctx context.Context, clusterName string, serv
30683092
return fmt.Errorf("Load balancer not found")
30693093
}
30703094
_, err = c.EnsureLoadBalancer(ctx, clusterName, service, nodes)
3095+
if err != nil {
3096+
return err
3097+
}
3098+
3099+
// TODO ensure security groups when defined
30713100
return err
30723101
}
30733102
lb, err := c.describeLoadBalancer(loadBalancerName)

pkg/providers/v1/aws_loadbalancer.go

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,17 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa
177177
// TODO: What happens if we have more than one subnet per AZ?
178178
createRequest.SubnetMappings = createSubnetMappings(discoveredSubnetIDs, allocationIDs)
179179

180+
if sgList, present := annotations[ServiceAnnotationLoadBalancerSecurityGroups]; present {
181+
// assuming SGs already been verified (if exists or not)
182+
klog.Infof("Setting up NLB with Security Groups: %v", sgList)
183+
for _, sg := range strings.Split(sgList, ",") {
184+
createRequest.SecurityGroups = append(createRequest.SecurityGroups, aws.String(sg))
185+
}
186+
// TODO(mtulio): check SGs exists, otherwise return fail
187+
// TODO check if need to manage the backend rules
188+
// createRequest.SecurityGroups =
189+
}
190+
180191
for k, v := range tags {
181192
createRequest.Tags = append(createRequest.Tags, &elbv2.Tag{
182193
Key: aws.String(k), Value: aws.String(v),
@@ -381,6 +392,12 @@ func (c *Cloud) ensureLoadBalancerv2(namespacedName types.NamespacedName, loadBa
381392
return nil, err
382393
}
383394

395+
// TODO: reconcile Security Groups.
396+
// Security Groups reconciliation is supported only when LB has been created with a SG.
397+
// TODO#1: check Security Groups is enabled in the NLB
398+
// TODO#1.1: reconcile SG from LB annotation
399+
// TODO#1.2: reconcile extra SG from LB annotation
400+
384401
// Subnets cannot be modified on NLBs
385402
if dirty {
386403
loadBalancers, err := c.elbv2.DescribeLoadBalancers(
@@ -819,6 +836,31 @@ func (c *Cloud) updateInstanceSecurityGroupsForNLB(lbName string, instances map[
819836
}
820837
}
821838

839+
// This block of code is responsible for updating the security group rules for instances
840+
// associated with a Network Load Balancer (NLB) in AWS. It ensures that the security group
841+
// rules allow traffic from specified client CIDRs and health check ports, as well as
842+
// handling MTU discovery rules for the NLB.
843+
//
844+
// Key steps in the process:
845+
// 1. Initialize sets for client ports, health check ports, and determine the client protocol
846+
// (TCP or UDP) based on the provided port mappings.
847+
// 2. Iterate through the port mappings to populate the client ports and health check ports.
848+
// If a custom health check port is specified, it is parsed and validated.
849+
// 3. Construct annotations for client and health check rules, which are used to identify
850+
// the rules in the security group.
851+
// 4. For each security group associated with the cluster:
852+
// - If the security group is desired (i.e., associated with an instance in the cluster):
853+
// - Add rules for health check traffic if the health check rules are not a subset of
854+
// the client rules.
855+
// - Add rules for client traffic.
856+
// - If the security group is not desired, remove any existing rules for health check
857+
// and client traffic.
858+
// - Update MTU discovery rules if necessary.
859+
// 5. The `updateInstanceSecurityGroupForNLBTraffic` function is used to manage the specific
860+
// permissions for traffic, ensuring that the security group rules match the desired state.
861+
//
862+
// This ensures that the security group rules are correctly configured to allow traffic
863+
// to and from the NLB, while also cleaning up any unnecessary rules.
822864
{
823865
clientPorts := sets.Int64{}
824866
clientProtocol := "tcp"

0 commit comments

Comments
 (0)