Skip to content

Commit 0fbbc5d

Browse files
kishorjTimothy-Dougherty
authored andcommitted
Add support for specifying source ranges for NLB (kubernetes-sigs#1492)
* add support for specifying source ranges for NLB * address comments
1 parent a655ec3 commit 0fbbc5d

File tree

3 files changed

+314
-16
lines changed

3 files changed

+314
-16
lines changed

pkg/annotations/constants.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ const (
4242

4343
// NLB annotation suffixes
4444
// prefixes service.beta.kubernetes.io, service.kubernetes.io
45+
SvcLBSuffixSourceRanges = "load-balancer-source-ranges"
4546
SvcLBSuffixLoadBalancerType = "aws-load-balancer-type"
4647
SvcLBSuffixInternal = "aws-load-balancer-internal"
4748
SvcLBSuffixProxyProtocol = "aws-load-balancer-proxy-protocol"

pkg/service/nlb/builder.go

Lines changed: 51 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -486,41 +486,76 @@ func (t *defaultModelBuildTask) buildTargetGroupBinding(ctx context.Context, tar
486486
})
487487
}
488488

489-
func (t *defaultModelBuildTask) buildTargetGroupBindingNetworking(_ context.Context, tgPort intstr.IntOrString, hcPort intstr.IntOrString,
490-
tgProtocol corev1.Protocol, ec2Subnets []*ec2.Subnet) *elbv2model.TargetGroupBindingNetworking {
491-
var from []elbv2model.NetworkingPeer
492-
networkingProtocol := elbv2api.NetworkingProtocolTCP
493-
if tgProtocol == corev1.ProtocolUDP {
494-
networkingProtocol = elbv2api.NetworkingProtocolUDP
489+
func (t *defaultModelBuildTask) buildPeersFromSourceRanges(_ context.Context) []elbv2model.NetworkingPeer {
490+
var sourceRanges []string
491+
var peers []elbv2model.NetworkingPeer
492+
for _, cidr := range t.service.Spec.LoadBalancerSourceRanges {
493+
sourceRanges = append(sourceRanges, cidr)
495494
}
495+
if len(sourceRanges) == 0 {
496+
t.annotationParser.ParseStringSliceAnnotation(annotations.SvcLBSuffixSourceRanges, &sourceRanges, t.service.Annotations)
497+
}
498+
if len(sourceRanges) == 0 {
499+
sourceRanges = append(sourceRanges, "0.0.0.0/0")
500+
}
501+
for _, cidr := range sourceRanges {
502+
peers = append(peers, elbv2model.NetworkingPeer{
503+
IPBlock: &elbv2api.IPBlock{
504+
CIDR: cidr,
505+
},
506+
})
507+
}
508+
return peers
509+
}
510+
511+
func (t *defaultModelBuildTask) buildTargetGroupBindingNetworking(ctx context.Context, tgPort intstr.IntOrString, hcPort intstr.IntOrString,
512+
tgProtocol corev1.Protocol, ec2Subnets []*ec2.Subnet) *elbv2model.TargetGroupBindingNetworking {
513+
var fromVPC []elbv2model.NetworkingPeer
496514
for _, subnet := range ec2Subnets {
497-
from = append(from, elbv2model.NetworkingPeer{
515+
fromVPC = append(fromVPC, elbv2model.NetworkingPeer{
498516
IPBlock: &elbv2api.IPBlock{
499517
CIDR: aws.StringValue(subnet.CidrBlock),
500518
},
501519
})
502520
}
503-
ports := []elbv2api.NetworkingPort{
521+
networkingProtocol := elbv2api.NetworkingProtocolTCP
522+
if tgProtocol == corev1.ProtocolUDP {
523+
networkingProtocol = elbv2api.NetworkingProtocolUDP
524+
}
525+
trafficPorts := []elbv2api.NetworkingPort{
504526
{
505527
Port: &tgPort,
506528
Protocol: &networkingProtocol,
507529
},
508530
}
509-
if hcPort.String() != healthCheckPortTrafficPort && hcPort.IntValue() != tgPort.IntValue() {
510-
networkingProtocolTCP := elbv2api.NetworkingProtocolTCP
511-
ports = append(ports, elbv2api.NetworkingPort{
512-
Port: &hcPort,
513-
Protocol: &networkingProtocolTCP,
514-
})
531+
trafficSource := fromVPC
532+
if networkingProtocol == elbv2api.NetworkingProtocolUDP {
533+
trafficSource = t.buildPeersFromSourceRanges(ctx)
515534
}
516535
tgbNetworking := &elbv2model.TargetGroupBindingNetworking{
517536
Ingress: []elbv2model.NetworkingIngressRule{
518537
{
519-
From: from,
520-
Ports: ports,
538+
From: trafficSource,
539+
Ports: trafficPorts,
521540
},
522541
},
523542
}
543+
if tgProtocol == corev1.ProtocolUDP || (hcPort.String() != healthCheckPortTrafficPort && hcPort.IntValue() != tgPort.IntValue()) {
544+
var healthCheckPorts []elbv2api.NetworkingPort
545+
networkingProtocolTCP := elbv2api.NetworkingProtocolTCP
546+
networkingHealthCheckPort := hcPort
547+
if hcPort.String() == healthCheckPortTrafficPort {
548+
networkingHealthCheckPort = tgPort
549+
}
550+
healthCheckPorts = append(healthCheckPorts, elbv2api.NetworkingPort{
551+
Port: &networkingHealthCheckPort,
552+
Protocol: &networkingProtocolTCP,
553+
})
554+
tgbNetworking.Ingress = append(tgbNetworking.Ingress, elbv2model.NetworkingIngressRule{
555+
From: fromVPC,
556+
Ports: healthCheckPorts,
557+
})
558+
}
524559
return tgbNetworking
525560
}
526561

pkg/service/nlb/builder_test.go

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@ import (
44
"context"
55
"errors"
66
"github.com/aws/aws-sdk-go/aws"
7+
"github.com/aws/aws-sdk-go/service/ec2"
78
"github.com/stretchr/testify/assert"
89
corev1 "k8s.io/api/core/v1"
910
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1011
"k8s.io/apimachinery/pkg/util/intstr"
12+
elbv2api "sigs.k8s.io/aws-load-balancer-controller/apis/elbv2/v1beta1"
1113
"sigs.k8s.io/aws-load-balancer-controller/pkg/annotations"
1214
"sigs.k8s.io/aws-load-balancer-controller/pkg/deploy"
1315
"sigs.k8s.io/aws-load-balancer-controller/pkg/model/elbv2"
@@ -374,7 +376,23 @@ func Test_defaultModelBuilderTask_buildNLB(t *testing.T) {
374376
{
375377
"protocol":"TCP",
376378
"port":80
379+
}
380+
]
381+
},
382+
{
383+
"from":[
384+
{
385+
"ipBlock":{
386+
"cidr":"172.20.32.0/19"
387+
}
377388
},
389+
{
390+
"ipBlock":{
391+
"cidr":"172.20.64.0/19"
392+
}
393+
}
394+
],
395+
"ports":[
378396
{
379397
"protocol":"TCP",
380398
"port":8888
@@ -678,7 +696,28 @@ func Test_defaultModelBuilderTask_buildNLB(t *testing.T) {
678696
{
679697
"protocol":"TCP",
680698
"port":8883
699+
}
700+
]
701+
},
702+
{
703+
"from":[
704+
{
705+
"ipBlock":{
706+
"cidr":"10.1.1.1/32"
707+
}
681708
},
709+
{
710+
"ipBlock":{
711+
"cidr":"10.1.1.2/32"
712+
}
713+
},
714+
{
715+
"ipBlock":{
716+
"cidr":"10.1.1.3/32"
717+
}
718+
}
719+
],
720+
"ports":[
682721
{
683722
"protocol":"TCP",
684723
"port":80
@@ -1118,3 +1157,226 @@ func Test_defaultModelBuilderTask_buildSubnetMappings(t *testing.T) {
11181157
})
11191158
}
11201159
}
1160+
1161+
func Test_defaultModelBuilderTask_buildTargetGroupBindingNetworking(t *testing.T) {
1162+
networkingProtocolTCP := elbv2api.NetworkingProtocolTCP
1163+
networkingProtocolUDP := elbv2api.NetworkingProtocolUDP
1164+
port80 := intstr.FromInt(80)
1165+
port808 := intstr.FromInt(808)
1166+
trafficPort := intstr.FromString("traffic-port")
1167+
1168+
tests := []struct {
1169+
name string
1170+
svc *corev1.Service
1171+
tgPort intstr.IntOrString
1172+
hcPort intstr.IntOrString
1173+
subnets []*ec2.Subnet
1174+
tgProtocol corev1.Protocol
1175+
want *elbv2.TargetGroupBindingNetworking
1176+
}{
1177+
{
1178+
name: "udp-service with source ranges",
1179+
svc: &corev1.Service{
1180+
Spec: corev1.ServiceSpec{
1181+
LoadBalancerSourceRanges: []string{"10.0.0.0/16", "1.2.3.4/24"},
1182+
},
1183+
},
1184+
tgPort: port80,
1185+
hcPort: trafficPort,
1186+
subnets: []*ec2.Subnet{{
1187+
CidrBlock: aws.String("172.16.0.0/19"),
1188+
SubnetId: aws.String("az-1"),
1189+
}},
1190+
tgProtocol: corev1.ProtocolUDP,
1191+
want: &elbv2.TargetGroupBindingNetworking{
1192+
Ingress: []elbv2.NetworkingIngressRule{
1193+
{
1194+
From: []elbv2.NetworkingPeer{
1195+
{
1196+
IPBlock: &elbv2api.IPBlock{
1197+
CIDR: "10.0.0.0/16",
1198+
},
1199+
},
1200+
{
1201+
IPBlock: &elbv2api.IPBlock{
1202+
CIDR: "1.2.3.4/24",
1203+
},
1204+
},
1205+
},
1206+
Ports: []elbv2api.NetworkingPort{
1207+
{
1208+
Protocol: &networkingProtocolUDP,
1209+
Port: &port80,
1210+
},
1211+
},
1212+
},
1213+
{
1214+
From: []elbv2.NetworkingPeer{
1215+
{
1216+
IPBlock: &elbv2api.IPBlock{
1217+
CIDR: "172.16.0.0/19",
1218+
},
1219+
},
1220+
},
1221+
Ports: []elbv2api.NetworkingPort{
1222+
{
1223+
Protocol: &networkingProtocolTCP,
1224+
Port: &port80,
1225+
},
1226+
},
1227+
},
1228+
},
1229+
},
1230+
},
1231+
{
1232+
name: "udp-service with source ranges annotation",
1233+
svc: &corev1.Service{
1234+
ObjectMeta: metav1.ObjectMeta{
1235+
Annotations: map[string]string{
1236+
"service.beta.kubernetes.io/load-balancer-source-ranges": "1.2.3.4/17, 5.6.7.8/18",
1237+
},
1238+
},
1239+
},
1240+
tgPort: port80,
1241+
hcPort: port808,
1242+
subnets: []*ec2.Subnet{{
1243+
CidrBlock: aws.String("172.16.0.0/19"),
1244+
SubnetId: aws.String("az-1"),
1245+
}},
1246+
tgProtocol: corev1.ProtocolUDP,
1247+
want: &elbv2.TargetGroupBindingNetworking{
1248+
Ingress: []elbv2.NetworkingIngressRule{
1249+
{
1250+
From: []elbv2.NetworkingPeer{
1251+
{
1252+
IPBlock: &elbv2api.IPBlock{
1253+
CIDR: "1.2.3.4/17",
1254+
},
1255+
},
1256+
{
1257+
IPBlock: &elbv2api.IPBlock{
1258+
CIDR: "5.6.7.8/18",
1259+
},
1260+
},
1261+
},
1262+
Ports: []elbv2api.NetworkingPort{
1263+
{
1264+
Protocol: &networkingProtocolUDP,
1265+
Port: &port80,
1266+
},
1267+
},
1268+
},
1269+
{
1270+
From: []elbv2.NetworkingPeer{
1271+
{
1272+
IPBlock: &elbv2api.IPBlock{
1273+
CIDR: "172.16.0.0/19",
1274+
},
1275+
},
1276+
},
1277+
Ports: []elbv2api.NetworkingPort{
1278+
{
1279+
Protocol: &networkingProtocolTCP,
1280+
Port: &port808,
1281+
},
1282+
},
1283+
},
1284+
},
1285+
},
1286+
},
1287+
{
1288+
name: "udp-service with no source ranges configuration",
1289+
svc: &corev1.Service{},
1290+
tgPort: port80,
1291+
hcPort: port808,
1292+
subnets: []*ec2.Subnet{{
1293+
CidrBlock: aws.String("172.16.0.0/19"),
1294+
SubnetId: aws.String("az-1"),
1295+
}},
1296+
tgProtocol: corev1.ProtocolUDP,
1297+
want: &elbv2.TargetGroupBindingNetworking{
1298+
Ingress: []elbv2.NetworkingIngressRule{
1299+
{
1300+
From: []elbv2.NetworkingPeer{
1301+
{
1302+
IPBlock: &elbv2api.IPBlock{
1303+
CIDR: "0.0.0.0/0",
1304+
},
1305+
},
1306+
},
1307+
Ports: []elbv2api.NetworkingPort{
1308+
{
1309+
Protocol: &networkingProtocolUDP,
1310+
Port: &port80,
1311+
},
1312+
},
1313+
},
1314+
{
1315+
From: []elbv2.NetworkingPeer{
1316+
{
1317+
IPBlock: &elbv2api.IPBlock{
1318+
CIDR: "172.16.0.0/19",
1319+
},
1320+
},
1321+
},
1322+
Ports: []elbv2api.NetworkingPort{
1323+
{
1324+
Protocol: &networkingProtocolTCP,
1325+
Port: &port808,
1326+
},
1327+
},
1328+
},
1329+
},
1330+
},
1331+
},
1332+
{
1333+
name: "tcp-service with traffic-port hc",
1334+
svc: &corev1.Service{},
1335+
tgPort: port80,
1336+
hcPort: trafficPort,
1337+
subnets: []*ec2.Subnet{
1338+
{
1339+
CidrBlock: aws.String("172.16.0.0/19"),
1340+
SubnetId: aws.String("sn-1"),
1341+
},
1342+
{
1343+
CidrBlock: aws.String("1.2.3.4/19"),
1344+
SubnetId: aws.String("sn-2"),
1345+
},
1346+
},
1347+
tgProtocol: corev1.ProtocolTCP,
1348+
want: &elbv2.TargetGroupBindingNetworking{
1349+
Ingress: []elbv2.NetworkingIngressRule{
1350+
{
1351+
From: []elbv2.NetworkingPeer{
1352+
{
1353+
IPBlock: &elbv2api.IPBlock{
1354+
CIDR: "172.16.0.0/19",
1355+
},
1356+
},
1357+
{
1358+
IPBlock: &elbv2api.IPBlock{
1359+
CIDR: "1.2.3.4/19",
1360+
},
1361+
},
1362+
},
1363+
Ports: []elbv2api.NetworkingPort{
1364+
{
1365+
Protocol: &networkingProtocolTCP,
1366+
Port: &port80,
1367+
},
1368+
},
1369+
},
1370+
},
1371+
},
1372+
},
1373+
}
1374+
for _, tt := range tests {
1375+
t.Run(tt.name, func(t *testing.T) {
1376+
parser := annotations.NewSuffixAnnotationParser("service.beta.kubernetes.io")
1377+
builder := &defaultModelBuildTask{service: tt.svc, annotationParser: parser}
1378+
got := builder.buildTargetGroupBindingNetworking(context.Background(), tt.tgPort, tt.hcPort, tt.tgProtocol, tt.subnets)
1379+
assert.Equal(t, tt.want, got)
1380+
})
1381+
}
1382+
}

0 commit comments

Comments
 (0)