@@ -40,10 +40,12 @@ import (
4040)
4141
4242const (
43- annotationLBType = "service.beta.kubernetes.io/aws-load-balancer-type"
44- annotationLBInternal = "service.beta.kubernetes.io/aws-load-balancer-internal"
45- annotationLBTargetNodeLabels = "service.beta.kubernetes.io/aws-load-balancer-target-node-labels"
46- annotationLBTargetGroupAttributes = "service.beta.kubernetes.io/aws-load-balancer-target-group-attributes"
43+ annotationLBType = "service.beta.kubernetes.io/aws-load-balancer-type"
44+ annotationLBInternal = "service.beta.kubernetes.io/aws-load-balancer-internal"
45+ annotationLBTargetNodeLabels = "service.beta.kubernetes.io/aws-load-balancer-target-node-labels"
46+ annotationLBTargetGroupAttributes = "service.beta.kubernetes.io/aws-load-balancer-target-group-attributes"
47+ annotationLBIPAddressType = "service.beta.kubernetes.io/aws-load-balancer-ip-address-type"
48+ annotationLBTargetGroupIPAddressType = "service.beta.kubernetes.io/aws-load-balancer-target-group-ip-address-type"
4749)
4850
4951var (
@@ -246,6 +248,79 @@ var _ = Describe("[cloud-provider-aws-e2e] loadbalancer", func() {
246248 }
247249 },
248250 },
251+ // Dual stack NLB with IPv6 target group test.
252+ // This test validates that a Network Load Balancer can be created with dual-stack support
253+ // (IPv4 and IPv6) and that target groups can be configured to use IPv6.
254+ {
255+ name : "NLB dual stack with IPv6 target group" ,
256+ resourceSuffix : "ds-nlb-ipv6-tg" ,
257+ extraAnnotations : map [string ]string {
258+ annotationLBType : "nlb" ,
259+ annotationLBIPAddressType : "dualstack" ,
260+ annotationLBTargetGroupIPAddressType : "ipv6" ,
261+ },
262+ listenerCount : 1 ,
263+ hookPreTest : func (e2e * e2eTestConfig ) {
264+ framework .Logf ("running hook pre-test: verify dual stack load balancer and IPv6 target group are configured correctly" )
265+
266+ if e2e .svc .Status .LoadBalancer .Ingress [0 ].Hostname == "" && e2e .svc .Status .LoadBalancer .Ingress [0 ].IP == "" {
267+ framework .Failf ("LoadBalancer ingress is empty (no hostname or IP) for service %s/%s" , e2e .svc .Namespace , e2e .svc .Name )
268+ }
269+
270+ hostAddr := e2eservice .GetIngressPoint (& e2e .svc .Status .LoadBalancer .Ingress [0 ])
271+ framework .Logf ("Load balancer's ingress address: %s" , hostAddr )
272+
273+ if hostAddr == "" {
274+ framework .Failf ("Unable to get LoadBalancer ingress address for service %s/%s" , e2e .svc .Namespace , e2e .svc .Name )
275+ }
276+
277+ elbClient , err := getAWSClientLoadBalancer (e2e .ctx )
278+ framework .ExpectNoError (err , "failed to create AWS ELB client" )
279+
280+ // Find the load balancer by DNS name
281+ foundLB , err := getAWSLoadBalancerFromDNSName (e2e .ctx , elbClient , hostAddr )
282+ framework .ExpectNoError (err , "failed to find load balancer with DNS name %s" , hostAddr )
283+ if foundLB == nil {
284+ framework .Failf ("Found load balancer is nil for DNS name %s" , hostAddr )
285+ }
286+
287+ lbARN := aws .ToString (foundLB .LoadBalancerArn )
288+ if lbARN == "" {
289+ framework .Failf ("Load balancer ARN is empty for DNS name %s" , hostAddr )
290+ }
291+ framework .Logf ("Found load balancer: %s with ARN: %s" , aws .ToString (foundLB .LoadBalancerName ), lbARN )
292+
293+ // Verify load balancer IP address type is dualstack
294+ framework .Logf ("=== Verifying Load Balancer IP Address Type ===" )
295+ lbIPAddressType := foundLB .IpAddressType
296+ framework .Logf ("Load balancer IP address type: %s" , lbIPAddressType )
297+ if lbIPAddressType != elbv2types .IpAddressTypeDualstack {
298+ framework .Failf ("Load balancer IP address type mismatch: expected %s, got %s" , elbv2types .IpAddressTypeDualstack , lbIPAddressType )
299+ }
300+ framework .Logf ("✓ Load balancer IP address type is correctly set to dualstack" )
301+
302+ // Lookup target groups from load balancer ARN
303+ targetGroups , err := elbClient .DescribeTargetGroups (e2e .ctx , & elbv2.DescribeTargetGroupsInput {
304+ LoadBalancerArn : aws .String (lbARN ),
305+ })
306+ framework .ExpectNoError (err , "failed to describe target groups" )
307+ gomega .Expect (len (targetGroups .TargetGroups )).To (gomega .BeNumerically (">" , 0 ))
308+
309+ // Verify target group IP address type is IPv6
310+ framework .Logf ("=== Verifying Target Group IP Address Type ===" )
311+ for _ , tg := range targetGroups .TargetGroups {
312+ tgName := aws .ToString (tg .TargetGroupName )
313+ tgIPAddressType := tg .IpAddressType
314+ framework .Logf ("Target group: %s, IP address type: %s" , tgName , tgIPAddressType )
315+
316+ if tgIPAddressType != elbv2types .TargetGroupIpAddressTypeEnumIpv6 {
317+ framework .Failf ("Target group IP address type mismatch for %s: expected %s, got %s" ,
318+ tgName , elbv2types .TargetGroupIpAddressTypeEnumIpv6 , tgIPAddressType )
319+ }
320+ framework .Logf ("✓ Target group %s IP address type is correctly set to ipv6" , tgName )
321+ }
322+ },
323+ },
249324 }
250325
251326 serviceNameBase := "lbconfig-test"
0 commit comments