mirror of https://github.com/kubernetes/kops.git
				
				
				
			Allow IPv6-only subnets
This commit is contained in:
		
							parent
							
								
									6b2cd12d6e
								
							
						
					
					
						commit
						f9071dd0d5
					
				|  | @ -299,7 +299,7 @@ func TestMinimalIPv6(t *testing.T) { | |||
| // TestMinimalIPv6 runs the test on a minimum IPv6 configuration
 | ||||
| func TestMinimalIPv6Private(t *testing.T) { | ||||
| 	newIntegrationTest("minimal-ipv6.example.com", "minimal-ipv6-private"). | ||||
| 		withAddons(awsCCMAddon, awsEBSCSIAddon, dnsControllerAddon). | ||||
| 		withAddons(awsCCMAddon, awsEBSCSIAddon, dnsControllerAddon, leaderElectionAddon). | ||||
| 		runTestTerraformAWS(t) | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -338,7 +338,11 @@ func ValidateCluster(c *kops.Cluster, strict bool) field.ErrorList { | |||
| 			fieldSubnet := fieldSpec.Child("subnets").Index(i) | ||||
| 			if s.CIDR == "" { | ||||
| 				if requiresSubnetCIDR && strict { | ||||
| 					if !strings.Contains(c.Spec.NonMasqueradeCIDR, ":") || s.IPv6CIDR == "" { | ||||
| 						allErrs = append(allErrs, field.Required(fieldSubnet.Child("cidr"), "subnet did not have a cidr set")) | ||||
| 					} else if c.IsKubernetesLT("1.23") { | ||||
| 						allErrs = append(allErrs, field.Required(fieldSubnet.Child("cidr"), "IPv6-only subnets require Kubernetes 1.23+")) | ||||
| 					} | ||||
| 				} | ||||
| 			} else { | ||||
| 				_, subnetCIDR, err := net.ParseCIDR(s.CIDR) | ||||
|  |  | |||
|  | @ -104,7 +104,7 @@ func validateClusterSpec(spec *kops.ClusterSpec, c *kops.Cluster, fieldPath *fie | |||
| 	} | ||||
| 
 | ||||
| 	if spec.Topology != nil { | ||||
| 		allErrs = append(allErrs, validateTopology(spec.Topology, fieldPath.Child("topology"))...) | ||||
| 		allErrs = append(allErrs, validateTopology(c, spec.Topology, fieldPath.Child("topology"))...) | ||||
| 	} | ||||
| 
 | ||||
| 	// UpdatePolicy
 | ||||
|  | @ -360,7 +360,7 @@ func validateIPv6CIDR(cidr string, fieldPath *field.Path) field.ErrorList { | |||
| 	return allErrs | ||||
| } | ||||
| 
 | ||||
| func validateTopology(topology *kops.TopologySpec, fieldPath *field.Path) field.ErrorList { | ||||
| func validateTopology(c *kops.Cluster, topology *kops.TopologySpec, fieldPath *field.Path) field.ErrorList { | ||||
| 	allErrs := field.ErrorList{} | ||||
| 
 | ||||
| 	if topology.Masters == "" { | ||||
|  | @ -373,6 +373,10 @@ func validateTopology(topology *kops.TopologySpec, fieldPath *field.Path) field. | |||
| 		allErrs = append(allErrs, field.Required(fieldPath.Child("nodes"), "")) | ||||
| 	} else { | ||||
| 		allErrs = append(allErrs, IsValidValue(fieldPath.Child("nodes"), &topology.Nodes, kops.SupportedTopologies)...) | ||||
| 
 | ||||
| 		if topology.Nodes == "private" && c.Spec.IsIPv6Only() && c.IsKubernetesLT("1.23") { | ||||
| 			allErrs = append(allErrs, field.Forbidden(fieldPath.Child("nodes"), "private topology in IPv6 clusters requires Kubernetes 1.23+")) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
| 	if topology.Bastion != nil { | ||||
|  |  | |||
|  | @ -254,7 +254,6 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error { | |||
| 			Lifecycle:        b.Lifecycle, | ||||
| 			VPC:              b.LinkToVPC(), | ||||
| 			AvailabilityZone: fi.String(subnetSpec.Zone), | ||||
| 			CIDR:             fi.String(subnetSpec.CIDR), | ||||
| 			Shared:           fi.Bool(sharedSubnet), | ||||
| 			Tags:             tags, | ||||
| 		} | ||||
|  | @ -263,6 +262,10 @@ func (b *NetworkModelBuilder) Build(c *fi.ModelBuilderContext) error { | |||
| 			subnet.ResourceBasedNaming = fi.Bool(true) | ||||
| 		} | ||||
| 
 | ||||
| 		if subnetSpec.CIDR != "" { | ||||
| 			subnet.CIDR = fi.String(subnetSpec.CIDR) | ||||
| 		} | ||||
| 
 | ||||
| 		if subnetSpec.IPv6CIDR != "" { | ||||
| 			if !sharedVPC { | ||||
| 				subnet.AmazonIPv6CIDR = b.LinkToAmazonVPCIPv6CIDR() | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ spec: | |||
|   iam: {} | ||||
|   kubelet: | ||||
|     anonymousAuth: false | ||||
|   kubernetesVersion: v1.21.0 | ||||
|   kubernetesVersion: v1.23.0 | ||||
|   masterInternalName: api.internal.minimal-ipv6.example.com | ||||
|   masterPublicName: api.minimal-ipv6.example.com | ||||
|   networkCIDR: 172.20.0.0/16 | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ func (e *Subnet) Find(c *fi.Context) (*Subnet, error) { | |||
| 
 | ||||
| 	actual.ResourceBasedNaming = fi.Bool(aws.StringValue(subnet.PrivateDnsNameOptionsOnLaunch.HostnameType) == ec2.HostnameTypeResourceName) | ||||
| 	if *actual.ResourceBasedNaming { | ||||
| 		if !aws.BoolValue(subnet.PrivateDnsNameOptionsOnLaunch.EnableResourceNameDnsARecord) { | ||||
| 		if fi.StringValue(actual.CIDR) != "" && !aws.BoolValue(subnet.PrivateDnsNameOptionsOnLaunch.EnableResourceNameDnsARecord) { | ||||
| 			actual.ResourceBasedNaming = nil | ||||
| 		} | ||||
| 		if fi.StringValue(actual.IPv6CIDR) != "" && !aws.BoolValue(subnet.PrivateDnsNameOptionsOnLaunch.EnableResourceNameDnsAAAARecord) { | ||||
|  | @ -175,9 +175,8 @@ func (s *Subnet) CheckChanges(a, e, changes *Subnet) error { | |||
| 			errors = append(errors, field.Required(fieldPath.Child("VPC"), "must specify a VPC")) | ||||
| 		} | ||||
| 
 | ||||
| 		if e.CIDR == nil { | ||||
| 			// TODO: Auto-assign CIDR?
 | ||||
| 			errors = append(errors, field.Required(fieldPath.Child("CIDR"), "must specify a CIDR")) | ||||
| 		if e.CIDR == nil && e.IPv6CIDR == nil { | ||||
| 			errors = append(errors, field.Required(fieldPath.Child("CIDR"), "must specify a CIDR or IPv6CIDR")) | ||||
| 		} | ||||
| 	} | ||||
| 
 | ||||
|  | @ -256,7 +255,7 @@ func (_ *Subnet) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Subnet) error { | |||
| 	} | ||||
| 
 | ||||
| 	if a == nil { | ||||
| 		klog.V(2).Infof("Creating Subnet with CIDR: %q", *e.CIDR) | ||||
| 		klog.V(2).Infof("Creating Subnet with CIDR: %q IPv6CIDR: %q", fi.StringValue(e.CIDR), fi.StringValue(e.IPv6CIDR)) | ||||
| 
 | ||||
| 		request := &ec2.CreateSubnetInput{ | ||||
| 			CidrBlock:         e.CIDR, | ||||
|  | @ -266,6 +265,10 @@ func (_ *Subnet) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Subnet) error { | |||
| 			TagSpecifications: awsup.EC2TagSpecification(ec2.ResourceTypeSubnet, e.Tags), | ||||
| 		} | ||||
| 
 | ||||
| 		if e.CIDR == nil { | ||||
| 			request.Ipv6Native = aws.Bool(true) | ||||
| 		} | ||||
| 
 | ||||
| 		response, err := t.Cloud.EC2().CreateSubnet(request) | ||||
| 		if err != nil { | ||||
| 			return fmt.Errorf("error creating subnet: %v", err) | ||||
|  | @ -300,6 +303,16 @@ func (_ *Subnet) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Subnet) error { | |||
| 			return fmt.Errorf("error modifying hostname type: %w", err) | ||||
| 		} | ||||
| 
 | ||||
| 		if fi.StringValue(e.CIDR) == "" { | ||||
| 			request = &ec2.ModifySubnetAttributeInput{ | ||||
| 				SubnetId:    e.ID, | ||||
| 				EnableDns64: &ec2.AttributeBooleanValue{Value: aws.Bool(true)}, | ||||
| 			} | ||||
| 			_, err = t.Cloud.EC2().ModifySubnetAttribute(request) | ||||
| 			if err != nil { | ||||
| 				return fmt.Errorf("error enabling DNS64: %w", err) | ||||
| 			} | ||||
| 		} else { | ||||
| 			request = &ec2.ModifySubnetAttributeInput{ | ||||
| 				SubnetId:                             e.ID, | ||||
| 				EnableResourceNameDnsARecordOnLaunch: &ec2.AttributeBooleanValue{Value: changes.ResourceBasedNaming}, | ||||
|  | @ -308,6 +321,7 @@ func (_ *Subnet) RenderAWS(t *awsup.AWSAPITarget, a, e, changes *Subnet) error { | |||
| 			if err != nil { | ||||
| 				return fmt.Errorf("error modifying A records: %w", err) | ||||
| 			} | ||||
| 		} | ||||
| 
 | ||||
| 		if fi.StringValue(e.IPv6CIDR) != "" { | ||||
| 			request = &ec2.ModifySubnetAttributeInput{ | ||||
|  |  | |||
|  | @ -174,6 +174,10 @@ func assignCIDRsToSubnets(c *kops.Cluster, cloud fi.Cloud) error { | |||
| 		if subnet.CIDR != "" { | ||||
| 			continue | ||||
| 		} | ||||
| 		// TODO: Replace this with a check against type "dualstack" if has IPv6CIDR
 | ||||
| 		if subnet.IPv6CIDR != "" && subnet.Name != subnet.Zone { | ||||
| 			continue | ||||
| 		} | ||||
| 
 | ||||
| 		if len(bigCIDRs) == 0 { | ||||
| 			return fmt.Errorf("insufficient (big) CIDRs remaining for automatic CIDR allocation to subnet %q", subnet.Name) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue