Merge pull request #3898 from rdrgmnzs/additional_cidr

Automatic merge from submit-queue.

Add additionalNetworkCIDRs to support VPCs with multiple CIDRs in AWS

Add additionalNetworkCIDRs to support VPCs with multiple CIDRs in AWS.

@justinsb I cannot find anywhere that does a check on an existing VPC to see if the networkCIDR matches what is on the VPC defined, I was looking for that so I can add a similar check for this. Am I missing something or is there really no check like that?
This commit is contained in:
Kubernetes Submit Queue 2017-12-13 18:25:41 -08:00 committed by GitHub
commit 7bd0a6a703
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 114 additions and 5 deletions

View File

@ -63,6 +63,36 @@ probably remove that tag to indicate that the resources are not owned by that cl
deleting the cluster won't try to delete the VPC. (Deleting the VPC won't succeed anyway, because it's in use,
but it's better to avoid the later confusion!)
### VPC with multiple CIDRs
AWS now allows you to add more CIDRs to a VPC, the param `AdditionalNetworkCIDRs` allows you to specify any additional CIDRs added to the VPC.
```
metadata:
creationTimestamp: "2016-06-27T14:23:34Z"
name: ${CLUSTER_NAME}
spec:
cloudProvider: aws
networkCIDR: 10.1.0.0/16
additionalNetworkCIDRs:
- 10.2.0.0/16
networkID: vpc-00aa5577
subnets:
- cidr: 10.1.0.0/19
name: us-east-1b
type: Public
zone: us-east-1b
id: subnet-1234567
- cidr: 10.2.0.0/19
name: us-east-1b
type: Public
zone: us-east-1b
id: subnet-1234568
```
## Advanced Options for Creating Clusters in Existing VPCs
### Shared Subnets

View File

@ -68,6 +68,10 @@ type ClusterSpec struct {
// This is a real CIDR, not the internal k8s network
// On AWS, it maps to the VPC CIDR. It is not required on GCE.
NetworkCIDR string `json:"networkCIDR,omitempty"`
// AdditionalNetworkCIDRs is a list of aditional CIDR used for the AWS VPC
// or otherwise allocated to k8s. This is a real CIDR, not the internal k8s network
// On AWS, it maps to any aditional CIDRs added to a VPC.
AdditionalNetworkCIDRs []string `json:"additionalNetworkCIDRs,omitempty"`
// NetworkID is an identifier of a network, if we want to reuse/share an existing network (e.g. an AWS VPC)
NetworkID string `json:"networkID,omitempty"`
// Topology defines the type of network topology to use on the cluster - default public

View File

@ -67,6 +67,10 @@ type ClusterSpec struct {
// This is a real CIDR, not the internal k8s network
// On AWS, it maps to the VPC CIDR. It is not required on GCE.
NetworkCIDR string `json:"networkCIDR,omitempty"`
// AdditionalNetworkCIDRs is a list of aditional CIDR used for the AWS VPC
// or otherwise allocated to k8s. This is a real CIDR, not the internal k8s network
// On AWS, it maps to any aditional CIDRs added to a VPC.
AdditionalNetworkCIDRs []string `json:"additionalNetworkCIDRs,omitempty"`
// NetworkID is an identifier of a network, if we want to reuse/share an existing network (e.g. an AWS VPC)
NetworkID string `json:"networkID,omitempty"`
// Topology defines the type of network topology to use on the cluster - default public

View File

@ -590,6 +590,7 @@ func autoConvert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
out.MasterPublicName = in.MasterPublicName
out.MasterInternalName = in.MasterInternalName
out.NetworkCIDR = in.NetworkCIDR
out.AdditionalNetworkCIDRs = in.AdditionalNetworkCIDRs
out.NetworkID = in.NetworkID
if in.Topology != nil {
in, out := &in.Topology, &out.Topology
@ -825,6 +826,7 @@ func autoConvert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(in *kops.ClusterSpec,
out.MasterPublicName = in.MasterPublicName
out.MasterInternalName = in.MasterInternalName
out.NetworkCIDR = in.NetworkCIDR
out.AdditionalNetworkCIDRs = in.AdditionalNetworkCIDRs
out.NetworkID = in.NetworkID
if in.Topology != nil {
in, out := &in.Topology, &out.Topology

View File

@ -753,6 +753,11 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
}
}
}
if in.AdditionalNetworkCIDRs != nil {
in, out := &in.AdditionalNetworkCIDRs, &out.AdditionalNetworkCIDRs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Topology != nil {
in, out := &in.Topology, &out.Topology
if *in == nil {

View File

@ -65,6 +65,10 @@ type ClusterSpec struct {
// This is a real CIDR, not the internal k8s network
// On AWS, it maps to the VPC CIDR. It is not required on GCE.
NetworkCIDR string `json:"networkCIDR,omitempty"`
// AdditionalNetworkCIDRs is a list of aditional CIDR used for the AWS VPC
// or otherwise allocated to k8s. This is a real CIDR, not the internal k8s network
// On AWS, it maps to any aditional CIDRs added to a VPC.
AdditionalNetworkCIDRs []string `json:"additionalNetworkCIDRs,omitempty"`
// NetworkID is an identifier of a network, if we want to reuse/share an existing network (e.g. an AWS VPC)
NetworkID string `json:"networkID,omitempty"`
// Topology defines the type of network topology to use on the cluster - default public

View File

@ -636,6 +636,7 @@ func autoConvert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(in *ClusterSpec, out *
out.MasterPublicName = in.MasterPublicName
out.MasterInternalName = in.MasterInternalName
out.NetworkCIDR = in.NetworkCIDR
out.AdditionalNetworkCIDRs = in.AdditionalNetworkCIDRs
out.NetworkID = in.NetworkID
if in.Topology != nil {
in, out := &in.Topology, &out.Topology
@ -887,6 +888,7 @@ func autoConvert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(in *kops.ClusterSpec,
out.MasterPublicName = in.MasterPublicName
out.MasterInternalName = in.MasterInternalName
out.NetworkCIDR = in.NetworkCIDR
out.AdditionalNetworkCIDRs = in.AdditionalNetworkCIDRs
out.NetworkID = in.NetworkID
if in.Topology != nil {
in, out := &in.Topology, &out.Topology

View File

@ -762,6 +762,11 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = make([]ClusterSubnetSpec, len(*in))
copy(*out, *in)
}
if in.AdditionalNetworkCIDRs != nil {
in, out := &in.AdditionalNetworkCIDRs, &out.AdditionalNetworkCIDRs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Topology != nil {
in, out := &in.Topology, &out.Topology
if *in == nil {

View File

@ -157,6 +157,20 @@ func ValidateCluster(c *kops.Cluster, strict bool) *field.Error {
}
}
// Check AdditionalNetworkCIDRs
var additionalNetworkCIDRs []*net.IPNet
{
if len(c.Spec.AdditionalNetworkCIDRs) > 0 {
for _, AdditionalNetworkCIDR := range c.Spec.AdditionalNetworkCIDRs {
_, IPNetAdditionalNetworkCIDR, err := net.ParseCIDR(AdditionalNetworkCIDR)
if err != nil {
return field.Invalid(fieldSpec.Child("AdditionalNetworkCIDRs"), AdditionalNetworkCIDR, fmt.Sprintf("Cluster had an invalid AdditionalNetworkCIDRs"))
}
additionalNetworkCIDRs = append(additionalNetworkCIDRs, IPNetAdditionalNetworkCIDR)
}
}
}
// Check NonMasqueradeCIDR
var nonMasqueradeCIDR *net.IPNet
{
@ -326,7 +340,7 @@ func ValidateCluster(c *kops.Cluster, strict bool) *field.Error {
return field.Invalid(fieldSubnet.Child("CIDR"), s.CIDR, "Subnet had an invalid CIDR")
}
if networkCIDR != nil && !isSubnet(networkCIDR, subnetCIDR) {
if networkCIDR != nil && !validateSubnetCIDR(networkCIDR, additionalNetworkCIDRs, subnetCIDR) {
return field.Invalid(fieldSubnet.Child("CIDR"), s.CIDR, fmt.Sprintf("Subnet %q had a CIDR %q that was not a subnet of the NetworkCIDR %q", s.Name, s.CIDR, c.Spec.NetworkCIDR))
}
}
@ -482,6 +496,21 @@ func ValidateCluster(c *kops.Cluster, strict bool) *field.Error {
return nil
}
// validateSubnetCIDR is responsible for validating subnets are part of the CIRDs assigned to the cluster.
func validateSubnetCIDR(networkCIDR *net.IPNet, additionalNetworkCIDRs []*net.IPNet, subnetCIDR *net.IPNet) bool {
if isSubnet(networkCIDR, subnetCIDR) {
return true
}
for _, additionalNetworkCIDR := range additionalNetworkCIDRs {
if isSubnet(additionalNetworkCIDR, subnetCIDR) {
return true
}
}
return false
}
// validateEtcdClusterSpec is responsible for validating the etcd cluster spec
func validateEtcdClusterSpec(spec *kops.EtcdClusterSpec, fieldPath *field.Path) *field.Error {
if spec.Name == "" {

View File

@ -71,6 +71,11 @@ func validateClusterSpec(spec *kops.ClusterSpec, fieldPath *field.Path) field.Er
allErrs = append(allErrs, validateCIDR(cidr, fieldPath.Child("nodePortAccess").Index(i))...)
}
// AdditionalNetworkCIDRs
for i, cidr := range spec.AdditionalNetworkCIDRs {
allErrs = append(allErrs, validateCIDR(cidr, fieldPath.Child("additionalNetworkCIDRs").Index(i))...)
}
for i := range spec.Hooks {
allErrs = append(allErrs, validateHookSpec(&spec.Hooks[i], fieldPath.Child("hooks").Index(i))...)
}

View File

@ -907,6 +907,11 @@ func (in *ClusterSpec) DeepCopyInto(out *ClusterSpec) {
*out = make([]ClusterSubnetSpec, len(*in))
copy(*out, *in)
}
if in.AdditionalNetworkCIDRs != nil {
in, out := &in.AdditionalNetworkCIDRs, &out.AdditionalNetworkCIDRs
*out = make([]string, len(*in))
copy(*out, *in)
}
if in.Topology != nil {
in, out := &in.Topology, &out.Topology
if *in == nil {

View File

@ -36,6 +36,7 @@ type VPC struct {
ID *string
CIDR *string
AdditionalCIDR *[]string
EnableDNSHostnames *bool
EnableDNSSupport *bool
@ -75,10 +76,11 @@ func (e *VPC) Find(c *fi.Context) (*VPC, error) {
}
vpc := response.Vpcs[0]
actual := &VPC{
ID: vpc.VpcId,
CIDR: vpc.CidrBlock,
Name: findNameTag(vpc.Tags),
Tags: intersectTags(vpc.Tags, e.Tags),
ID: vpc.VpcId,
CIDR: vpc.CidrBlock,
AdditionalCIDR: getAdditionalCIDR(vpc.CidrBlock, vpc.CidrBlockAssociationSet),
Name: findNameTag(vpc.Tags),
Tags: intersectTags(vpc.Tags, e.Tags),
}
glog.V(4).Infof("found matching VPC %v", actual)
@ -273,3 +275,15 @@ func (e *VPC) CloudformationLink() *cloudformation.Literal {
return cloudformation.Ref("AWS::EC2::VPC", *e.Name)
}
func getAdditionalCIDR(CIDR *string, additionalCIDRSet []*ec2.VpcCidrBlockAssociation) *[]string {
var additionalCIDRs []string
for _, CIDRSet := range additionalCIDRSet {
if *CIDRSet.CidrBlock != *CIDR {
additionalCIDRs = append(additionalCIDRs, *CIDRSet.CidrBlock)
}
}
return &additionalCIDRs
}