Skip to content

Commit e7cbdf6

Browse files
authored
Add support for target group IP address type configuration IPv4, IPv6 (#770)
Implement support for configuring target group IP address types (ipv4 or ipv6) in Network Load Balancer (NLB) and Application Load Balancer (ALB) configurations. Changes: - Add --target-group-ip-addr-type CLI flag to specify target group IP address type - Add targetGroupIPAddressType field to Adapter for storing the configuration - Update CloudFormation templates to include TargetGroupIPAddressTypeParameter This feature allows dual-stack NLB to be connected with IPv6 address type target groups. Signed-off-by: speruri <surya.srikar.peruri@zalando.de>
1 parent 2ae6096 commit e7cbdf6

File tree

50 files changed

+2198
-93
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

50 files changed

+2198
-93
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,9 +40,16 @@ This information is used to manage AWS resources for each ingress objects of the
4040
- Suppport for `ipv4` and `dualstack` ip address types for ALB and NLB
4141
- set default ip address type for both ALB and NLB using `--ip-addr-type=dualstack`
4242
- set specific ip address type for a particular ALB or NLB by using the annotation `alb.ingress.kubernetes.io/ip-address-type: dualstack` in the ingress of the resource
43+
- Support for `ipv4` and `ipv6` target group IP address types for ALB and NLB
44+
- set default target group IP address type using `--target-group-ip-address-type=ipv6`
45+
- IPv6 targets require dualstack load balancers (`--ip-addr-type=dualstack`)
4346

4447
## Upgrade
4548

49+
### <v0.19 to >=v0.19
50+
51+
Version `v0.19` adds support for IPv6 target group IP address type. When using IPv6 targets, ensure your load balancer is configured as dualstack (`--ip-addr-type=dualstack` or `alb.ingress.kubernetes.io/ip-address-type: dualstack`). IPv4-only load balancers cannot route to IPv6 targets and will fail with a clear error message.
52+
4653
### <v0.18.0 to >=v0.18.0
4754

4855
Version `v0.18.0` vendors-in https://github.com/mweagle/go-cloudformation library to enable addition of missing CloudFormation features.

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v0.18
1+
v0.19

aws/adapter.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ type Adapter struct {
6363
controllerID string
6464
sslPolicy string
6565
ipAddressType string
66+
targetGroupIPAddressType string
6667
albLogsS3Bucket string
6768
albLogsS3Prefix string
6869
nlbZoneAffinity string
@@ -118,6 +119,8 @@ const (
118119
DefaultSslPolicy = "ELBSecurityPolicy-2016-08"
119120
// DefaultIpAddressType sets IpAddressType to "ipv4", it is either ipv4 or dualstack
120121
DefaultIpAddressType = "ipv4"
122+
// DefaultTargetGroupIPAddressType sets TargetGroupIPAddressType to "ipv4", it is either ipv4 or ipv6
123+
DefaultTargetGroupIPAddressType = "ipv4"
121124
// DefaultAlbS3LogsBucket is a blank string, and must be set if enabled
122125
DefaultAlbS3LogsBucket = ""
123126
// DefaultAlbS3LogsPrefix is a blank string, and optionally set if desired
@@ -138,6 +141,7 @@ const (
138141
LoadBalancerTypeApplication = "application"
139142
LoadBalancerTypeNetwork = "network"
140143
IPAddressTypeIPV4 = "ipv4"
144+
IPAddressTypeIPV6 = "ipv6"
141145
IPAddressTypeDualstack = "dualstack"
142146

143147
TargetAccessModeAWSCNI = "AWSCNI"
@@ -263,6 +267,7 @@ func NewAdapter(ctx context.Context, clusterID, newControllerID, vpcID string, d
263267
controllerID: newControllerID,
264268
sslPolicy: DefaultSslPolicy,
265269
ipAddressType: DefaultIpAddressType,
270+
targetGroupIPAddressType: DefaultTargetGroupIPAddressType,
266271
albLogsS3Bucket: DefaultAlbS3LogsBucket,
267272
albLogsS3Prefix: DefaultAlbS3LogsPrefix,
268273
nlbCrossZone: DefaultNLBCrossZone,
@@ -442,6 +447,15 @@ func (a *Adapter) WithIpAddressType(ipAddressType string) *Adapter {
442447
return a
443448
}
444449

450+
// WithTargetGroupIPAddressType returns the receiver with ipv4 or ipv6 configuration for target groups, defaults to ipv4.
451+
func (a *Adapter) WithTargetGroupIPAddressType(ipAddressType string) *Adapter {
452+
switch ipAddressType {
453+
case IPAddressTypeIPV4, IPAddressTypeIPV6:
454+
a.targetGroupIPAddressType = ipAddressType
455+
}
456+
return a
457+
}
458+
445459
// WithAlbLogsS3Bucket returns the receiver adapter after changing the S3 bucket for logging
446460
func (a *Adapter) WithAlbLogsS3Bucket(bucket string) *Adapter {
447461
a.albLogsS3Bucket = bucket
@@ -784,6 +798,10 @@ func (a *Adapter) CreateStack(ctx context.Context, certificateARNs []string, sch
784798
return "", fmt.Errorf("invalid SSLPolicy '%s' defined", sslPolicy)
785799
}
786800

801+
if ipAddressType == IPAddressTypeIPV4 && a.targetGroupIPAddressType == IPAddressTypeIPV6 {
802+
return "", fmt.Errorf("cannot use %s target group with %s load balancer; use dualstack load balancer for IPv6 targets", a.targetGroupIPAddressType, ipAddressType)
803+
}
804+
787805
spec := &stackSpec{
788806
name: a.stackName(),
789807
scheme: scheme,
@@ -814,6 +832,7 @@ func (a *Adapter) CreateStack(ctx context.Context, certificateARNs []string, sch
814832
controllerID: a.controllerID,
815833
sslPolicy: sslPolicy,
816834
ipAddressType: ipAddressType,
835+
targetGroupIPAddressType: a.targetGroupIPAddressType,
817836
loadbalancerType: loadBalancerType,
818837
albLogsS3Bucket: a.albLogsS3Bucket,
819838
albLogsS3Prefix: a.albLogsS3Prefix,
@@ -841,6 +860,10 @@ func (a *Adapter) UpdateStack(ctx context.Context, stackName string, certificate
841860
return "", fmt.Errorf("invalid SSLPolicy '%s' defined", sslPolicy)
842861
}
843862

863+
if ipAddressType == IPAddressTypeIPV4 && a.targetGroupIPAddressType == IPAddressTypeIPV6 {
864+
return "", fmt.Errorf("invalid TargetGroupIPAddressType %q defined for IPAddressType %q", a.targetGroupIPAddressType, ipAddressType)
865+
}
866+
844867
spec := &stackSpec{
845868
name: stackName,
846869
scheme: scheme,
@@ -871,6 +894,7 @@ func (a *Adapter) UpdateStack(ctx context.Context, stackName string, certificate
871894
controllerID: a.controllerID,
872895
sslPolicy: sslPolicy,
873896
ipAddressType: ipAddressType,
897+
targetGroupIPAddressType: a.targetGroupIPAddressType,
874898
loadbalancerType: loadBalancerType,
875899
albLogsS3Bucket: a.albLogsS3Bucket,
876900
albLogsS3Prefix: a.albLogsS3Prefix,

aws/cf.go

Lines changed: 45 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -21,23 +21,24 @@ const (
2121

2222
// Stack is a simple wrapper around a CloudFormation Stack.
2323
type Stack struct {
24-
Name string
25-
status types.StackStatus
26-
statusReason string
27-
LoadBalancerARN string
28-
DNSName string
29-
Scheme string
30-
SecurityGroup string
31-
SSLPolicy string
32-
IpAddressType string
33-
LoadBalancerType string
34-
HTTP2 bool
35-
OwnerIngress string
36-
CWAlarmConfigHash string
37-
TargetGroupARNs []string
38-
WAFWebACLID string
39-
CertificateARNs map[string]time.Time
40-
tags map[string]string
24+
Name string
25+
status types.StackStatus
26+
statusReason string
27+
LoadBalancerARN string
28+
DNSName string
29+
Scheme string
30+
SecurityGroup string
31+
SSLPolicy string
32+
IpAddressType string
33+
LoadBalancerType string
34+
HTTP2 bool
35+
OwnerIngress string
36+
CWAlarmConfigHash string
37+
TargetGroupARNs []string
38+
WAFWebACLID string
39+
CertificateARNs map[string]time.Time
40+
tags map[string]string
41+
targetGroupIPAddressType string
4142
}
4243

4344
// IsComplete returns true if the stack status is a complete state.
@@ -151,6 +152,7 @@ const (
151152
parameterTargetGroupTargetPortParameter = "TargetGroupTargetPortParameter"
152153
parameterTargetGroupHTTPTargetPortParameter = "TargetGroupHTTPTargetPortParameter"
153154
parameterTargetGroupVPCIDParameter = "TargetGroupVPCIDParameter"
155+
parameterTargetGroupIPAddressTypeParameter = "TargetGroupIPAddressTypeParameter"
154156
parameterListenerSslPolicyParameter = "ListenerSslPolicyParameter"
155157
parameterIpAddressTypeParameter = "IpAddressType"
156158
parameterLoadBalancerTypeParameter = "Type"
@@ -183,6 +185,7 @@ type stackSpec struct {
183185
controllerID string
184186
sslPolicy string
185187
ipAddressType string
188+
targetGroupIPAddressType string
186189
loadbalancerType string
187190
albLogsS3Bucket string
188191
albLogsS3Prefix string
@@ -241,6 +244,7 @@ func createStack(ctx context.Context, svc CloudFormationAPI, spec *stackSpec) (s
241244
cfParam(parameterLoadBalancerSubnetsParameter, strings.Join(spec.subnets, ",")),
242245
cfParam(parameterTargetGroupVPCIDParameter, spec.vpcID),
243246
cfParam(parameterTargetGroupTargetPortParameter, fmt.Sprintf("%d", spec.targetPort)),
247+
cfParam(parameterTargetGroupIPAddressTypeParameter, spec.targetGroupIPAddressType),
244248
cfParam(parameterListenerSslPolicyParameter, spec.sslPolicy),
245249
cfParam(parameterIpAddressTypeParameter, spec.ipAddressType),
246250
cfParam(parameterLoadBalancerTypeParameter, spec.loadbalancerType),
@@ -317,6 +321,7 @@ func updateStack(ctx context.Context, svc CloudFormationAPI, spec *stackSpec) (s
317321
cfParam(parameterTargetGroupVPCIDParameter, spec.vpcID),
318322
cfParam(parameterTargetGroupTargetPortParameter, fmt.Sprintf("%d", spec.targetPort)),
319323
cfParam(parameterListenerSslPolicyParameter, spec.sslPolicy),
324+
cfParam(parameterTargetGroupIPAddressTypeParameter, spec.targetGroupIPAddressType),
320325
cfParam(parameterIpAddressTypeParameter, spec.ipAddressType),
321326
cfParam(parameterLoadBalancerTypeParameter, spec.loadbalancerType),
322327
cfParam(parameterHTTP2Parameter, fmt.Sprintf("%t", spec.http2)),
@@ -490,24 +495,30 @@ func mapToManagedStack(stack *types.Stack) *Stack {
490495
http2 = false
491496
}
492497

498+
targetGroupIPAddressType := parameters[parameterTargetGroupIPAddressTypeParameter]
499+
if targetGroupIPAddressType == "" {
500+
targetGroupIPAddressType = DefaultTargetGroupIPAddressType
501+
}
502+
493503
return &Stack{
494-
Name: aws.ToString(stack.StackName),
495-
LoadBalancerARN: outputs.loadBalancerARN(),
496-
DNSName: outputs.dnsName(),
497-
TargetGroupARNs: outputs.targetGroupARNs(),
498-
Scheme: parameters[parameterLoadBalancerSchemeParameter],
499-
SecurityGroup: parameters[parameterLoadBalancerSecurityGroupParameter],
500-
SSLPolicy: parameters[parameterListenerSslPolicyParameter],
501-
IpAddressType: parameters[parameterIpAddressTypeParameter],
502-
LoadBalancerType: parameters[parameterLoadBalancerTypeParameter],
503-
HTTP2: http2,
504-
CertificateARNs: certificateARNs,
505-
tags: tags,
506-
OwnerIngress: ownerIngress,
507-
status: stack.StackStatus,
508-
statusReason: aws.ToString(stack.StackStatusReason),
509-
CWAlarmConfigHash: tags[cwAlarmConfigHashTag],
510-
WAFWebACLID: parameters[parameterLoadBalancerWAFWebACLIDParameter],
504+
Name: aws.ToString(stack.StackName),
505+
LoadBalancerARN: outputs.loadBalancerARN(),
506+
DNSName: outputs.dnsName(),
507+
TargetGroupARNs: outputs.targetGroupARNs(),
508+
Scheme: parameters[parameterLoadBalancerSchemeParameter],
509+
SecurityGroup: parameters[parameterLoadBalancerSecurityGroupParameter],
510+
SSLPolicy: parameters[parameterListenerSslPolicyParameter],
511+
IpAddressType: parameters[parameterIpAddressTypeParameter],
512+
LoadBalancerType: parameters[parameterLoadBalancerTypeParameter],
513+
HTTP2: http2,
514+
CertificateARNs: certificateARNs,
515+
tags: tags,
516+
OwnerIngress: ownerIngress,
517+
status: stack.StackStatus,
518+
statusReason: aws.ToString(stack.StackStatusReason),
519+
CWAlarmConfigHash: tags[cwAlarmConfigHashTag],
520+
WAFWebACLID: parameters[parameterLoadBalancerWAFWebACLIDParameter],
521+
targetGroupIPAddressType: targetGroupIPAddressType,
511522
}
512523
}
513524

aws/cf_template.go

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,11 @@ func generateTemplate(spec *stackSpec) (string, error) {
8787
Type: "AWS::EC2::VPC::Id",
8888
Description: "The VPCID for the TargetGroup",
8989
},
90+
parameterTargetGroupIPAddressTypeParameter: {
91+
Type: "String",
92+
Description: "Target group IP Address Type, 'ipv4' or 'ipv6'",
93+
Default: IPAddressTypeIPV4,
94+
},
9095
parameterListenerSslPolicyParameter: {
9196
Type: "String",
9297
Description: "The HTTPS SSL Security Policy Name",
@@ -495,6 +500,7 @@ func newTargetGroup(spec *stackSpec, targetPortParameter string) *cloudformation
495500
HealthCheckProtocol: cloudformation.String(healthCheckProtocol),
496501
HealthyThresholdCount: cloudformation.Integer(int64(healthyThresholdCount)),
497502
UnhealthyThresholdCount: cloudformation.Integer(int64(unhealthyThresholdCount)),
503+
IPAddressType: cloudformation.Ref(parameterTargetGroupIPAddressTypeParameter).String(),
498504
Port: cloudformation.Ref(targetPortParameter).Integer(),
499505
Protocol: cloudformation.String(protocol),
500506
TargetType: targetType,

0 commit comments

Comments
 (0)