From 4c7154407f8a0f433ec2e4e5e68d584f6dad9c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Alberto=20Novoa=20Rojas?= <112587171+iamjanr@users.noreply.github.com> Date: Thu, 5 Dec 2024 15:49:50 +0100 Subject: [PATCH] [PLT-1246] [GKE] Manage Cluster Secondary Range (#33) * [GKE] Manage Cluster Secondary Range * Modify changelog --- CHANGELOG.md | 1 + .../services/container/clusters/reconcile.go | 9 +++ ...ster.x-k8s.io_gcpmanagedcontrolplanes.yaml | 44 +++++++++++++ .../v1beta1/gcpmanagedcontrolplane_types.go | 40 ++++++++++++ .../v1beta1/gcpmanagedcontrolplane_webhook.go | 61 +++++++++++++++++++ exp/api/v1beta1/types.go | 18 ++++++ exp/api/v1beta1/zz_generated.deepcopy.go | 50 +++++++++++++++ 7 files changed, 223 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1fbb79b84..f60aebecd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## 1.6.1-0.2.1 (upcoming) +* [PLT-1313] Soportar rangos secundarios de CIDR * [PLT-1246] CMEK Support ## 1.6.1-0.2.0 (2024-10-24) diff --git a/cloud/services/container/clusters/reconcile.go b/cloud/services/container/clusters/reconcile.go index 7c4954ed2..3df867fcd 100644 --- a/cloud/services/container/clusters/reconcile.go +++ b/cloud/services/container/clusters/reconcile.go @@ -300,6 +300,15 @@ func (s *Service) createCluster(ctx context.Context, log *logr.Logger) error { } } + // Add IPAllocationPolicy for CIDR support (PLT-1246) + if s.scope.GCPManagedControlPlane.Spec.ClusterIpv4Cidr != nil { + cluster.ClusterIpv4Cidr = *s.scope.GCPManagedControlPlane.Spec.ClusterIpv4Cidr + } + + if s.scope.GCPManagedControlPlane.Spec.IPAllocationPolicy != nil { + cluster.IpAllocationPolicy = infrav1exp.ConvertToSdkIPAllocationPolicy(s.scope.GCPManagedControlPlane.Spec.IPAllocationPolicy) + } + // If the cluster is autopilot, we don't need to specify node pools. if !s.scope.IsAutopilotCluster() { cluster.NodePools = scope.ConvertToSdkNodePools(nodePools, machinePools, isRegional, cluster.Name) diff --git a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml index fc95fd635..57003e6e6 100644 --- a/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml +++ b/config/crd/bases/infrastructure.cluster.x-k8s.io_gcpmanagedcontrolplanes.yaml @@ -62,6 +62,14 @@ spec: spec: description: GCPManagedControlPlaneSpec defines the desired state of GCPManagedControlPlane. properties: + clusterIpv4Cidr: + description: |- + ClusterIpv4Cidr is the IP address range of the container pods in the GKE cluster, in + [CIDR](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) + notation (e.g. `10.96.0.0/14`). + If not specified then one will be automatically chosen. + If this field is specified then IPAllocationPolicy.ClusterIpv4CidrBlock should be left blank. + type: string clusterName: description: |- ClusterName allows you to specify the name of the GKE cluster. @@ -118,6 +126,42 @@ spec: - host - port type: object + ipAllocationPolicy: + description: |- + IPAllocationPolicy represents configuration options for GKE cluster IP allocation. + If not specified then GKE default values will be used. + properties: + clusterIpv4CidrBlock: + description: |- + ClusterIpv4CidrBlock represents the IP address range for the GKE cluster pod IPs. If this field is set, then + GCPManagedControlPlaneSpec.ClusterIpv4Cidr must be left blank. + This field is only applicable when use_ip_aliases is set to true. + If not specified the range will be chosen with the default size. + type: string + clusterSecondaryRangeName: + description: |- + ClusterSecondaryRangeName represents the name of the secondary range to be used for the GKE cluster CIDR block. + The range will be used for pod IP addresses and must be an existing secondary range associated with the cluster subnetwork. + This field is only applicable when use_ip_aliases is set to true. + type: string + servicesIpv4CidrBlock: + description: |- + ServicesIpv4CidrBlock represents the IP address range for services IPs in the GKE cluster. + This field is only applicable when use_ip_aliases is set to true. + If not specified the range will be chosen with the default size. + type: string + servicesSecondaryRangeName: + description: |- + ServicesSecondaryRangeName represents the name of the secondary range to be used for the services CIDR block. + The range will be used for service ClusterIPs and must be an existing secondary range associated with the cluster subnetwork. + This field is only applicable when use_ip_aliases is set to true. + type: string + useIPAliases: + description: |- + UseIPAliases represents whether alias IPs will be used for pod IPs in the cluster. + If unspecified will default to false. + type: boolean + type: object location: description: |- Location represents the location (region or zone) in which the GKE cluster diff --git a/exp/api/v1beta1/gcpmanagedcontrolplane_types.go b/exp/api/v1beta1/gcpmanagedcontrolplane_types.go index 2541a0b5d..ccc652ba7 100644 --- a/exp/api/v1beta1/gcpmanagedcontrolplane_types.go +++ b/exp/api/v1beta1/gcpmanagedcontrolplane_types.go @@ -89,6 +89,17 @@ type GCPManagedControlPlaneSpec struct { // Location represents the location (region or zone) in which the GKE cluster // will be created. Location string `json:"location"` + // ClusterIpv4Cidr is the IP address range of the container pods in the GKE cluster, in + // [CIDR](http://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing) + // notation (e.g. `10.96.0.0/14`). + // If not specified then one will be automatically chosen. + // If this field is specified then IPAllocationPolicy.ClusterIpv4CidrBlock should be left blank. + // +optional + ClusterIpv4Cidr *string `json:"clusterIpv4Cidr,omitempty"` + // IPAllocationPolicy represents configuration options for GKE cluster IP allocation. + // If not specified then GKE default values will be used. + // +optional + IPAllocationPolicy *IPAllocationPolicy `json:"ipAllocationPolicy,omitempty"` // EnableAutopilot indicates whether to enable autopilot for this GKE cluster. // +optional EnableAutopilot bool `json:"enableAutopilot"` @@ -173,6 +184,35 @@ const ( Stable ReleaseChannel = "stable" ) +// IPAllocationPolicy represents configuration options for GKE cluster IP allocation. +type IPAllocationPolicy struct { + // UseIPAliases represents whether alias IPs will be used for pod IPs in the cluster. + // If unspecified will default to false. + // +optional + UseIPAliases *bool `json:"useIPAliases,omitempty"` + // ClusterSecondaryRangeName represents the name of the secondary range to be used for the GKE cluster CIDR block. + // The range will be used for pod IP addresses and must be an existing secondary range associated with the cluster subnetwork. + // This field is only applicable when use_ip_aliases is set to true. + // +optional + ClusterSecondaryRangeName *string `json:"clusterSecondaryRangeName,omitempty"` + // ServicesSecondaryRangeName represents the name of the secondary range to be used for the services CIDR block. + // The range will be used for service ClusterIPs and must be an existing secondary range associated with the cluster subnetwork. + // This field is only applicable when use_ip_aliases is set to true. + // +optional + ServicesSecondaryRangeName *string `json:"servicesSecondaryRangeName,omitempty"` + // ClusterIpv4CidrBlock represents the IP address range for the GKE cluster pod IPs. If this field is set, then + // GCPManagedControlPlaneSpec.ClusterIpv4Cidr must be left blank. + // This field is only applicable when use_ip_aliases is set to true. + // If not specified the range will be chosen with the default size. + // +optional + ClusterIpv4CidrBlock *string `json:"clusterIpv4CidrBlock,omitempty"` + // ServicesIpv4CidrBlock represents the IP address range for services IPs in the GKE cluster. + // This field is only applicable when use_ip_aliases is set to true. + // If not specified the range will be chosen with the default size. + // +optional + ServicesIpv4CidrBlock *string `json:"servicesIpv4CidrBlock,omitempty"` +} + // MasterAuthorizedNetworksConfig contains configuration options for the master authorized networks feature. // Enabled master authorized networks will disallow all external traffic to access // Kubernetes master through HTTPS except traffic from the given CIDR blocks, diff --git a/exp/api/v1beta1/gcpmanagedcontrolplane_webhook.go b/exp/api/v1beta1/gcpmanagedcontrolplane_webhook.go index 947b23024..18664ef69 100644 --- a/exp/api/v1beta1/gcpmanagedcontrolplane_webhook.go +++ b/exp/api/v1beta1/gcpmanagedcontrolplane_webhook.go @@ -24,6 +24,7 @@ import ( apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/util/validation/field" + "k8s.io/utils/pointer" "github.com/pkg/errors" "k8s.io/apimachinery/pkg/runtime" @@ -123,6 +124,15 @@ func (r *GCPManagedControlPlane) ValidateUpdate(oldRaw runtime.Object) (admissio ) } + // Add IPAllocationPolicy for CIDR support (PLT-1246) + + if !cmp.Equal(r.Spec.ClusterIpv4Cidr, old.Spec.ClusterIpv4Cidr) { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec", "ClusterIpv4Cidr"), + pointer.StringDeref(r.Spec.ClusterIpv4Cidr, ""), "field is immutable"), + ) + } + if !cmp.Equal(r.Spec.EnableAutopilot, old.Spec.EnableAutopilot) { allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "EnableAutopilot"), @@ -167,3 +177,54 @@ func generateGKEName(resourceName, namespace string, maxLength int) (string, err return fmt.Sprintf("%s%s", resourcePrefix, hashedName), nil } + +// Add IPAllocationPolicy for CIDR support (PLT-1246) + +func validateIPAllocationPolicy(spec GCPManagedControlPlaneSpec) field.ErrorList { + var allErrs field.ErrorList + + if spec.IPAllocationPolicy == nil { + return allErrs + } + + path := field.NewPath("spec", "IPAllocationPolicy") + + isUseIPAliases := pointer.BoolDeref(spec.IPAllocationPolicy.UseIPAliases, false) + if spec.IPAllocationPolicy.ClusterSecondaryRangeName != nil && !isUseIPAliases { + allErrs = append(allErrs, + field.Invalid(path.Child("ClusterSecondaryRangeName"), + spec.IPAllocationPolicy.ClusterSecondaryRangeName, + "field cannot be set unless UseIPAliases is set to true"), + ) + } + if spec.IPAllocationPolicy.ServicesSecondaryRangeName != nil && !isUseIPAliases { + allErrs = append(allErrs, + field.Invalid(path.Child("ServicesSecondaryRangeName"), + spec.IPAllocationPolicy.ServicesSecondaryRangeName, + "field cannot be set unless UseIPAliases is set to true"), + ) + } + if spec.IPAllocationPolicy.ServicesIpv4CidrBlock != nil && !isUseIPAliases { + allErrs = append(allErrs, + field.Invalid(path.Child("ServicesIpv4CidrBlock"), + spec.IPAllocationPolicy.ServicesIpv4CidrBlock, + "field cannot be set unless UseIPAliases is set to true"), + ) + } + if spec.IPAllocationPolicy.ClusterIpv4CidrBlock != nil && !isUseIPAliases { + allErrs = append(allErrs, + field.Invalid(path.Child("ClusterIpv4CidrBlock"), + spec.IPAllocationPolicy.ClusterIpv4CidrBlock, + "field cannot be set unless UseIPAliases is set to true"), + ) + } + if spec.IPAllocationPolicy.ClusterIpv4CidrBlock != nil && spec.ClusterIpv4Cidr != nil { + allErrs = append(allErrs, + field.Invalid(path.Child("ClusterIpv4CidrBlock"), + spec.IPAllocationPolicy.ClusterIpv4CidrBlock, + "only one of spec.ClusterIpv4Cidr and spec.IPAllocationPolicy.ClusterIpv4CidrBlock can be set"), + ) + } + + return allErrs +} diff --git a/exp/api/v1beta1/types.go b/exp/api/v1beta1/types.go index 53eb3dc85..05d230856 100644 --- a/exp/api/v1beta1/types.go +++ b/exp/api/v1beta1/types.go @@ -20,6 +20,7 @@ import ( "strings" "cloud.google.com/go/container/apiv1/containerpb" + "k8s.io/utils/pointer" ) // TaintEffect is the effect for a Kubernetes taint. @@ -144,3 +145,20 @@ func ConvertToSdkLinuxNodeConfig(linuxNodeConfig *LinuxNodeConfig) *containerpb. } return &sdkLinuxNodeConfig } + +// Add IPAllocationPolicy for CIDR support (PLT-1246) + +// ConvertToSdkIPAllocationPolicy converts the CAPG IPAllocationPolicy to a containerpb IPAllocationPolicy. +func ConvertToSdkIPAllocationPolicy(policy *IPAllocationPolicy) *containerpb.IPAllocationPolicy { + if policy == nil { + return nil + } + + return &containerpb.IPAllocationPolicy{ + UseIpAliases: pointer.BoolDeref(policy.UseIPAliases, false), + ClusterSecondaryRangeName: pointer.StringDeref(policy.ClusterSecondaryRangeName, ""), + ServicesSecondaryRangeName: pointer.StringDeref(policy.ServicesSecondaryRangeName, ""), + ClusterIpv4CidrBlock: pointer.StringDeref(policy.ClusterIpv4CidrBlock, ""), + ServicesIpv4CidrBlock: pointer.StringDeref(policy.ServicesIpv4CidrBlock, ""), + } +} diff --git a/exp/api/v1beta1/zz_generated.deepcopy.go b/exp/api/v1beta1/zz_generated.deepcopy.go index 3d864d535..3cf803c9f 100644 --- a/exp/api/v1beta1/zz_generated.deepcopy.go +++ b/exp/api/v1beta1/zz_generated.deepcopy.go @@ -247,6 +247,16 @@ func (in *GCPManagedControlPlaneSpec) DeepCopyInto(out *GCPManagedControlPlaneSp *out = new(MonitoringConfig) **out = **in } + if in.ClusterIpv4Cidr != nil { + in, out := &in.ClusterIpv4Cidr, &out.ClusterIpv4Cidr + *out = new(string) + **out = **in + } + if in.IPAllocationPolicy != nil { + in, out := &in.IPAllocationPolicy, &out.IPAllocationPolicy + *out = new(IPAllocationPolicy) + (*in).DeepCopyInto(*out) + } if in.ReleaseChannel != nil { in, out := &in.ReleaseChannel, &out.ReleaseChannel *out = new(ReleaseChannel) @@ -484,6 +494,46 @@ func (in *GCPManagedMachinePoolStatus) DeepCopy() *GCPManagedMachinePoolStatus { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IPAllocationPolicy) DeepCopyInto(out *IPAllocationPolicy) { + *out = *in + if in.UseIPAliases != nil { + in, out := &in.UseIPAliases, &out.UseIPAliases + *out = new(bool) + **out = **in + } + if in.ClusterSecondaryRangeName != nil { + in, out := &in.ClusterSecondaryRangeName, &out.ClusterSecondaryRangeName + *out = new(string) + **out = **in + } + if in.ServicesSecondaryRangeName != nil { + in, out := &in.ServicesSecondaryRangeName, &out.ServicesSecondaryRangeName + *out = new(string) + **out = **in + } + if in.ClusterIpv4CidrBlock != nil { + in, out := &in.ClusterIpv4CidrBlock, &out.ClusterIpv4CidrBlock + *out = new(string) + **out = **in + } + if in.ServicesIpv4CidrBlock != nil { + in, out := &in.ServicesIpv4CidrBlock, &out.ServicesIpv4CidrBlock + *out = new(string) + **out = **in + } +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IPAllocationPolicy. +func (in *IPAllocationPolicy) DeepCopy() *IPAllocationPolicy { + if in == nil { + return nil + } + out := new(IPAllocationPolicy) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *LinuxNodeConfig) DeepCopyInto(out *LinuxNodeConfig) { *out = *in