-
Notifications
You must be signed in to change notification settings - Fork 634
✨ IPv6 support for self-managed clusters #5603
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
7949ccb
c1bafb0
842f85a
60308b2
7826e7e
987bc9c
7bbae60
cd6c178
1ebffda
2c7e1e4
da96854
cd7c9b2
def75f2
9851222
ea41d67
bfbbb84
4d38ed3
e5e3ad3
04d4286
b8ca23a
3292f75
78cb9d4
061134a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -585,14 +585,25 @@ func (s *Service) runInstance(role string, i *infrav1.Instance) (*infrav1.Instan | |
|
||
input.NetworkInterfaces = netInterfaces | ||
} else { | ||
input.NetworkInterfaces = []types.InstanceNetworkInterfaceSpecification{ | ||
{ | ||
DeviceIndex: aws.Int32(0), | ||
SubnetId: aws.String(i.SubnetID), | ||
Groups: i.SecurityGroupIDs, | ||
AssociatePublicIpAddress: i.PublicIPOnLaunch, | ||
}, | ||
netInterface := types.InstanceNetworkInterfaceSpecification{ | ||
DeviceIndex: aws.Int32(0), | ||
SubnetId: aws.String(i.SubnetID), | ||
Groups: i.SecurityGroupIDs, | ||
AssociatePublicIpAddress: i.PublicIPOnLaunch, | ||
} | ||
|
||
// When registering targets by instance ID for an IPv6 target group, the targets must have an assigned primary IPv6 address. | ||
// Use case: registering controlplane nodes to the API LBs. | ||
enablePrimaryIpv6, err := s.shouldEnablePrimaryIpv6(i) | ||
if err != nil { | ||
return nil, fmt.Errorf("failed to determine whether to enable PrimaryIpv6 for instance: %w", err) | ||
} | ||
if enablePrimaryIpv6 { | ||
netInterface.PrimaryIpv6 = aws.Bool(true) | ||
netInterface.Ipv6AddressCount = aws.Int32(1) | ||
} | ||
|
||
input.NetworkInterfaces = []types.InstanceNetworkInterfaceSpecification{netInterface} | ||
} | ||
|
||
if i.NetworkInterfaceType != "" { | ||
|
@@ -1307,3 +1318,34 @@ func getInstanceCPUOptionsRequest(cpuOptions infrav1.CPUOptions) *types.CpuOptio | |
|
||
return request | ||
} | ||
|
||
func (s *Service) shouldEnablePrimaryIpv6(i *infrav1.Instance) (bool, error) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method is making the assumption that when IPv6 is enabled, IPv6 would be the primary. If correct, could you please add that as a comment to this method? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Right, I will add the above comment in. Thanks! |
||
var enablePrimaryIpv6 bool | ||
|
||
// We should enable IPv6 capabilities only when the users explicitly configure so. | ||
if !s.scope.VPC().IsIPv6Enabled() { | ||
return false, nil | ||
} | ||
|
||
sn := s.scope.Subnets().FindByID(i.SubnetID) | ||
if sn != nil { | ||
enablePrimaryIpv6 = sn.IsIPv6 | ||
} else { | ||
// The subnet is in a different VPC than the cluster VPC. Then, we query AWS API. | ||
sns, err := s.getFilteredSubnets(types.Filter{Name: aws.String("subnet-id"), Values: []string{i.SubnetID}}) | ||
if err != nil { | ||
return false, fmt.Errorf("failed to find subnet info with id %q for instance: %w", i.SubnetID, err) | ||
} | ||
if len(sns) == 0 { | ||
return false, fmt.Errorf("expected subnet %q for instance to exist, but found none", i.SubnetID) | ||
} | ||
for _, set := range sns[0].Ipv6CidrBlockAssociationSet { | ||
if set.Ipv6CidrBlockState.State == types.SubnetCidrBlockStateCodeAssociated { | ||
enablePrimaryIpv6 = true | ||
break | ||
} | ||
} | ||
} | ||
|
||
return enablePrimaryIpv6, nil | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is possible to have an IPv6-enabled VPC that contains IPv4 subnets. In that case, I would assume that this field would be unset or explicitly set to false i.e even of IPv6 enabled VPCs, IPV4 subnets would be the default? Could you please confirm if that is the case and also update description to reflect what the default would be?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So far, I only consider the "happy" default path that vpc and subnets are dual-stack. Let me add this to my list of questions to confirm. Will get back asap.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Update: I updated the CRD description to:
This should mean that
IsIPv6
reflects the state of the subnet (i.e. not depending on the VPC). So, an Ipv4 subnet will havesn.IsIPv6==false
as expected even in a dualstack VPC.Commit: 43d6ec8
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That being said, CAPA will describe the subnet and update the field to reflect the correct state (i.e. IPv6 or not, depending on whether there is an associated IPv6 CIDR)
Describing subnets:
cluster-api-provider-aws/pkg/cloud/services/network/subnets.go
Lines 405 to 411 in f3c2166
Deep-copy subnet state to spec:
cluster-api-provider-aws/pkg/cloud/services/network/subnets.go
Lines 136 to 137 in f3c2166