Skip to content

Commit

Permalink
UDP Support over IPv6 via Dualstack NLBs using SourceNAT configuratio…
Browse files Browse the repository at this point in the history
…ns (#3926)

* UDP Support over IPv6 via Dualstack NLBs using SourceNAT configurations

* updated go version

* fixed tests

* removed duplicate assertion
  • Loading branch information
shethyogita83 authored Oct 31, 2024
1 parent 2d8cbe7 commit 73b1f0e
Show file tree
Hide file tree
Showing 11 changed files with 844 additions and 42 deletions.
37 changes: 37 additions & 0 deletions docs/guide/service/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@
| [service.beta.kubernetes.io/aws-load-balancer-inbound-sg-rules-on-private-link-traffic](#update-security-settings) | string | |
| [service.beta.kubernetes.io/aws-load-balancer-listener-attributes.${Protocol}-${Port}](#listener-attributes) | stringMap | |
| [service.beta.kubernetes.io/aws-load-balancer-multi-cluster-target-group](#multi-cluster-target-group) | boolean | false | If specified, the controller will only operate on targets that exist within the cluster, ignoring targets from other sources. |
| [service.beta.kubernetes.io/aws-load-balancer-enable-prefix-for-ipv6-source-nat](#enable-prefix-for-ipv6-source-nat) | string | off | Optional annotation. dualstack lb only. Allowed values - on and off |
| [service.beta.kubernetes.io/aws-load-balancer-source-nat-ipv6-prefixes](#source-nat-ipv6-prefixes) | stringList | | Optional annotation. dualstack lb only. This annotation is only applicable when user has to set the service.beta.kubernetes.io/aws-load-balancer-enable-prefix-for-ipv6-source-nat to "on". Length must match the number of subnets |

## Traffic Routing
Traffic Routing can be controlled with following annotations:
Expand Down Expand Up @@ -199,6 +201,41 @@ Traffic Listening can be controlled with following annotations:
service.beta.kubernetes.io/aws-load-balancer-ip-address-type: ipv4
```

## Support UDP-based services over IPv6
You can configure dualstack NLB to support UDP-based services over IPv6 via the following annotations:

- <a name="enable-prefix-for-ipv6-source-nat">service.beta.kubernetes.io/aws-load-balancer-enable-prefix-for-ipv6-source-nat</a> specifies whether Prefix for IPv6 source NAT is enabled or not. UDP-based support can be enabled for dualstack NLBs only if Prefix for IPv6 source NAT is enabled.

!!!note ""
- Applicable to Network Load Balancers using dualstack IP address type.
- This configuration is optional, and you can use it to enable UDP support over IPv6.
- Allowed values are either “on” or “off”
- Once the source prefix for source NATing is enabled, it cannot be disabled if load balancer has a UDP listener attached.
- Steps to disable the aws-load-balancer-enable-prefix-for-ipv6-source-nat after it is enabled and UDP listeners already attached.
- You will have to first remove the UDP listeners and apply the manifest.
- Update the manifest to set source NATing to "off" and then apply the manifest again.

!!!example
- Enable prefix for IPv6 Source NAT
```
service.beta.kubernetes.io/aws-load-balancer-enable-prefix-for-ipv6-source-nat: "on"
```

- <a name="source-nat-ipv6-prefixes">service.beta.kubernetes.io/aws-load-balancer-source-nat-ipv6-prefixes</a> specifies a list of IPv6 prefixes that should be used for IPv6 source NATing.

!!!note ""
- Applicable to Network Load Balancers using dualstack IP address type.
- This annotation can be specified only if service.beta.kubernetes.io/aws-load-balancer-enable-prefix-for-ipv6-source-nat annotation is set to “on”.
- This configuration is optional and it can be used to specify custom IPv6 prefixes for IPv6 source NATing to support UDP based services routing in Network Load Balancers using dualstack IP address type.
- If service.beta.kubernetes.io/aws-load-balancer-enable-prefix-for-ipv6-source-nat annotation is set to “on”, and you don’t specify this annotation, then IPv6 prefix/CIDR for source NATing will be auto-assigned to each subnet.
- If you are specifying this annotation, you must specify the same number of items in the list as the load balancer subnets annotation and following the same order. Each item in the list can have value of either “auto_assigned” or a valid IPv6 prefix/CIDR with prefix length of 80 and it should be in range of the corresponding subnet CIDR.
- Once the source NAT IPv6 prefixes are set, the IPv6 prefixes cannot be updated if the load balancer has a UDP listener attached.

!!!example
```
service.beta.kubernetes.io/aws-load-balancer-source-nat-ipv6-prefixes: 1025:0223:0009:6487:0001::/80, auto_assigned, 1025:0223:0010:6487:0001::/80
```

## Resource attributes
NLB resource attributes can be controlled via the following annotations:

Expand Down
13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
@@ -1,21 +1,22 @@
module sigs.k8s.io/aws-load-balancer-controller

go 1.22.7
go 1.22.8

require (
github.com/aws/aws-sdk-go-v2 v1.30.5
github.com/aws/aws-sdk-go v1.55.5
github.com/aws/aws-sdk-go-v2 v1.32.3
github.com/aws/aws-sdk-go-v2/config v1.27.27
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11
github.com/aws/aws-sdk-go-v2/service/acm v1.28.4
github.com/aws/aws-sdk-go-v2/service/appmesh v1.27.7
github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.36.0
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.41.0
github.com/aws/aws-sdk-go-v2/service/resourcegroupstaggingapi v1.23.3
github.com/aws/aws-sdk-go-v2/service/servicediscovery v1.31.7
github.com/aws/aws-sdk-go-v2/service/shield v1.27.3
github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3
github.com/aws/aws-sdk-go-v2/service/wafv2 v1.51.4
github.com/aws/smithy-go v1.21.0
github.com/aws/smithy-go v1.22.0
github.com/evanphx/json-patch v5.7.0+incompatible
github.com/gavv/httpexpect/v2 v2.9.0
github.com/go-logr/logr v1.4.1
Expand Down Expand Up @@ -56,8 +57,8 @@ require (
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 // indirect
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 // indirect
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 // indirect
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 // indirect
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 // indirect
Expand Down
22 changes: 12 additions & 10 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,20 @@ github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5 h1:0CwZNZbxp69SHPd
github.com/armon/go-socks5 v0.0.0-20160902184237-e75332964ef5/go.mod h1:wHh0iHkYZB8zMSxRWpUBQtwG5a7fFgvEO+odwuTv2gs=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535 h1:4daAzAu0S6Vi7/lbWECcX0j45yZReDZ56BQsrVBOEEY=
github.com/asaskevich/govalidator v0.0.0-20200428143746-21a406dcc535/go.mod h1:oGkLhpf+kjZl6xBf758TQhh5XrAeiJv/7FRz/2spLIg=
github.com/aws/aws-sdk-go-v2 v1.30.5 h1:mWSRTwQAb0aLE17dSzztCVJWI9+cRMgqebndjwDyK0g=
github.com/aws/aws-sdk-go-v2 v1.30.5/go.mod h1:CT+ZPWXbYrci8chcARI3OmI/qgd+f6WtuLOoaIA8PR0=
github.com/aws/aws-sdk-go v1.55.5 h1:KKUZBfBoyqy5d3swXyiC7Q76ic40rYcbqH7qjh59kzU=
github.com/aws/aws-sdk-go v1.55.5/go.mod h1:eRwEWoyTWFMVYVQzKMNHWP5/RV4xIUGMQfXQHfHkpNU=
github.com/aws/aws-sdk-go-v2 v1.32.3 h1:T0dRlFBKcdaUPGNtkBSwHZxrtis8CQU17UpNBZYd0wk=
github.com/aws/aws-sdk-go-v2 v1.32.3/go.mod h1:2SK5n0a2karNTv5tbP1SjsX0uhttou00v/HpXKM1ZUo=
github.com/aws/aws-sdk-go-v2/config v1.27.27 h1:HdqgGt1OAP0HkEDDShEl0oSYa9ZZBSOmKpdpsDMdO90=
github.com/aws/aws-sdk-go-v2/config v1.27.27/go.mod h1:MVYamCg76dFNINkZFu4n4RjDixhVr51HLj4ErWzrVwg=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27 h1:2raNba6gr2IfA0eqqiP2XiQ0UVOpGPgDSi0I9iAP+UI=
github.com/aws/aws-sdk-go-v2/credentials v1.17.27/go.mod h1:gniiwbGahQByxan6YjQUMcW4Aov6bLC3m+evgcoN4r4=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11 h1:KreluoV8FZDEtI6Co2xuNk/UqI9iwMrOx/87PBNIKqw=
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.11/go.mod h1:SeSUYBLsMYFoRvHE0Tjvn7kbxaUhl75CJi1sbfhMxkU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17 h1:pI7Bzt0BJtYA0N/JEC6B8fJ4RBrEMi1LBrkMdFYNSnQ=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.17/go.mod h1:Dh5zzJYMtxfIjYW+/evjQ8uj2OyR/ve2KROHGHlSFqE=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17 h1:Mqr/V5gvrhA2gvgnF42Zh5iMiQNcOYthFYwCyrnuWlc=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.17/go.mod h1:aLJpZlCmjE+V+KtN1q1uyZkfnUWpQGpbsn89XPKyzfU=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22 h1:Jw50LwEkVjuVzE1NzkhNKkBf9cRN7MtE1F/b2cOKTUM=
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.22/go.mod h1:Y/SmAyPcOTmpeVaWSzSKiILfXTVJwrGmYZhcRbhWuEY=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22 h1:981MHwBaRZM7+9QSR6XamDzF/o7ouUGxFzr+nVSIhrs=
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.22/go.mod h1:1RA1+aBEfn+CAB/Mh0MB6LsdCYCnjZm7tKXtnk499ZQ=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU=
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY=
github.com/aws/aws-sdk-go-v2/service/acm v1.28.4 h1:wiW1Y6/1lysA0eJZRq0I53YYKuV9MNAzL15z2eZRlEE=
Expand All @@ -56,8 +58,8 @@ github.com/aws/aws-sdk-go-v2/service/appmesh v1.27.7 h1:q44a6kysAfej9zZwRnraOg9s
github.com/aws/aws-sdk-go-v2/service/appmesh v1.27.7/go.mod h1:ZYSmrgAMp0rTCHH+SGsoxZo+PPbgsDqBzewTp3tSJ60=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0 h1:ta62lid9JkIpKZtZZXSj6rP2AqY5x1qYGq53ffxqD9Q=
github.com/aws/aws-sdk-go-v2/service/ec2 v1.173.0/go.mod h1:o6QDjdVKpP5EF0dp/VlvqckzuSDATr1rLdHt3A5m0YY=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.36.0 h1:3t8g6wmPA9hr69qzDraI1umO2An7jKNe75dBsxbI30E=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.36.0/go.mod h1:jk+iid9R4MN7UVDwSTK/ZDDO8WNhxnO2WVzfYOMLh+4=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.41.0 h1:W+xNfPS8dQ8YoszdkHqTDYIgCrWJvyUU/ZgdJ0frCRE=
github.com/aws/aws-sdk-go-v2/service/elasticloadbalancingv2 v1.41.0/go.mod h1:6WuvTcPjB9gff93p/2LNBg09d8xK99jpVO6+fRSCKEU=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3 h1:dT3MqvGhSoaIhRseqw2I0yH81l7wiR2vjs57O51EAm8=
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.3/go.mod h1:GlAeCkHwugxdHaueRr4nhPuY+WW+gR8UjlcqzPr1SPI=
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.17 h1:HGErhhrxZlQ044RiM+WdoZxp0p+EGM62y3L6pwA4olE=
Expand All @@ -78,8 +80,8 @@ github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3 h1:7dr6En0/6KRFoz8VmnYk
github.com/aws/aws-sdk-go-v2/service/wafregional v1.23.3/go.mod h1:24TtlRsv4LKAE3VnRJQhpatr8cpX0yj8NSzg8/lxOCw=
github.com/aws/aws-sdk-go-v2/service/wafv2 v1.51.4 h1:1khBA5uryBRJoCb4G2iR5RT06BkfPEjjDCHAiRb8P3Q=
github.com/aws/aws-sdk-go-v2/service/wafv2 v1.51.4/go.mod h1:QpFImaPGKNwa+MiZ+oo6LbV1PVQBapc0CnrAMRScoxM=
github.com/aws/smithy-go v1.21.0 h1:H7L8dtDRk0P1Qm6y0ji7MCYMQObJ5R9CRpyPhRUkLYA=
github.com/aws/smithy-go v1.21.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/aws/smithy-go v1.22.0 h1:uunKnWlcoL3zO7q+gG2Pk53joueEOsnNB28QdMsmiMM=
github.com/aws/smithy-go v1.22.0/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
Expand Down
2 changes: 2 additions & 0 deletions pkg/annotations/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,4 +99,6 @@ const (
SvcLBSuffixSecurityGroupPrefixLists = "aws-load-balancer-security-group-prefix-lists"
SvcLBSuffixlsAttsAnnotationPrefix = "aws-load-balancer-listener-attributes"
SvcLBSuffixMultiClusterTargetGroup = "aws-load-balancer-multi-cluster-target-group"
ScvLBSuffixEnablePrefixForIpv6SourceNat = "aws-load-balancer-enable-prefix-for-ipv6-source-nat"
ScvLBSuffixSourceNatIpv6Prefixes = "aws-load-balancer-source-nat-ipv6-prefixes"
)
35 changes: 28 additions & 7 deletions pkg/deploy/elbv2/load_balancer_manager.go
Original file line number Diff line number Diff line change
Expand Up @@ -154,20 +154,36 @@ func (m *defaultLoadBalancerManager) updateSDKLoadBalancerWithIPAddressType(ctx

func (m *defaultLoadBalancerManager) updateSDKLoadBalancerWithSubnetMappings(ctx context.Context, resLB *elbv2model.LoadBalancer, sdkLB LoadBalancerWithTags) error {
desiredSubnets := sets.NewString()
desiredSubnetsSourceNATPrefixes := sets.NewString()
currentSubnetsSourceNATPrefixes := sets.NewString()
for _, mapping := range resLB.Spec.SubnetMappings {
desiredSubnets.Insert(mapping.SubnetID)
if mapping.SourceNatIpv6Prefix != nil {
desiredSubnetsSourceNATPrefixes.Insert(awssdk.ToString(mapping.SourceNatIpv6Prefix))
}
}
currentSubnets := sets.NewString()
for _, az := range sdkLB.LoadBalancer.AvailabilityZones {
currentSubnets.Insert(awssdk.ToString(az.SubnetId))
if len(az.SourceNatIpv6Prefixes) != 0 {
currentSubnetsSourceNATPrefixes.Insert(az.SourceNatIpv6Prefixes[0])
}
}
if desiredSubnets.Equal(currentSubnets) {
sdkLBEnablePrefixForIpv6SourceNatValue := string(elbv2model.EnablePrefixForIpv6SourceNatOff)
resLBEnablePrefixForIpv6SourceNatValue := string(elbv2model.EnablePrefixForIpv6SourceNatOff)

sdkLBEnablePrefixForIpv6SourceNatValue = string(sdkLB.LoadBalancer.EnablePrefixForIpv6SourceNat)

resLBEnablePrefixForIpv6SourceNatValue = string(resLB.Spec.EnablePrefixForIpv6SourceNat)

if desiredSubnets.Equal(currentSubnets) && desiredSubnetsSourceNATPrefixes.Equal(currentSubnetsSourceNATPrefixes) && sdkLBEnablePrefixForIpv6SourceNatValue == resLBEnablePrefixForIpv6SourceNatValue {
return nil
}

req := &elbv2sdk.SetSubnetsInput{
LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
SubnetMappings: buildSDKSubnetMappings(resLB.Spec.SubnetMappings),
LoadBalancerArn: sdkLB.LoadBalancer.LoadBalancerArn,
SubnetMappings: buildSDKSubnetMappings(resLB.Spec.SubnetMappings),
EnablePrefixForIpv6SourceNat: elbv2types.EnablePrefixForIpv6SourceNatEnum(resLBEnablePrefixForIpv6SourceNatValue),
}
changeDesc := fmt.Sprintf("%v => %v", currentSubnets.List(), desiredSubnets.List())
m.logger.Info("modifying loadBalancer subnetMappings",
Expand Down Expand Up @@ -261,6 +277,10 @@ func buildSDKCreateLoadBalancerInput(lbSpec elbv2model.LoadBalancerSpec) (*elbv2
sdkObj.SecurityGroups = sdkSecurityGroups
}

if lbSpec.EnablePrefixForIpv6SourceNat != "" {
sdkObj.EnablePrefixForIpv6SourceNat = elbv2types.EnablePrefixForIpv6SourceNatEnum(lbSpec.EnablePrefixForIpv6SourceNat)
}

sdkObj.CustomerOwnedIpv4Pool = lbSpec.CustomerOwnedIPv4Pool
return sdkObj, nil
}
Expand Down Expand Up @@ -294,10 +314,11 @@ func buildSDKSecurityGroups(modelSecurityGroups []coremodel.StringToken) ([]stri

func buildSDKSubnetMapping(modelSubnetMapping elbv2model.SubnetMapping) elbv2types.SubnetMapping {
return elbv2types.SubnetMapping{
AllocationId: modelSubnetMapping.AllocationID,
PrivateIPv4Address: modelSubnetMapping.PrivateIPv4Address,
IPv6Address: modelSubnetMapping.IPv6Address,
SubnetId: awssdk.String(modelSubnetMapping.SubnetID),
AllocationId: modelSubnetMapping.AllocationID,
PrivateIPv4Address: modelSubnetMapping.PrivateIPv4Address,
IPv6Address: modelSubnetMapping.IPv6Address,
SubnetId: awssdk.String(modelSubnetMapping.SubnetID),
SourceNatIpv6Prefix: modelSubnetMapping.SourceNatIpv6Prefix,
}
}

Expand Down
Loading

0 comments on commit 73b1f0e

Please sign in to comment.