From 37ca2cc802c88f31f41e22a352edc535d040eb6a Mon Sep 17 00:00:00 2001 From: Oren Cohen Date: Thu, 7 May 2026 14:42:37 +0300 Subject: [PATCH] fix(api): OCPBUGS-84303: add IPv6 OVN join subnet config to prevent dual-stack routing collision Cherry-pick of #8421 to release-4.21. On KubeVirt dual-stack hosted clusters, the guest OVN-Kubernetes cluster shares the same default IPv6 join subnet (fd98::/64) as the management cluster. When external IPv6 LoadBalancer traffic is SNAT'd to a join switch IP, the guest cluster intercepts the response because both clusters own the same fd98::/64 range, causing a routing black hole. This fix: - Defaults the guest cluster's IPv6 OVN join subnet to fd99::/64 for KubeVirt hosted clusters, avoiding the collision automatically - Adds OVNIPv6Config API type allowing users to explicitly configure IPv6 internalJoinSubnet and internalTransitSwitchSubnet - Extends CIDR overlap validation to cover IPv6 OVN subnets including the implicit KubeVirt default (fd99::/64) - Adds unit tests for all new IPv6 validation and reconciliation logic Signed-off-by: Oren Cohen Assisted-by: Claude Opus 4 (via Cursor) Co-authored-by: Cursor --- api/hypershift/v1beta1/operator.go | 49 +++++++ .../v1beta1/zz_generated.deepcopy.go | 16 +++ .../AAA_ungated.yaml | 64 +++++++++ .../AutoNodeKarpenter.yaml | 64 +++++++++ .../ClusterVersionOperatorConfiguration.yaml | 64 +++++++++ .../ExternalOIDC.yaml | 64 +++++++++ ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 64 +++++++++ .../GCPPlatform.yaml | 64 +++++++++ ...perShiftOnlyDynamicResourceAllocation.yaml | 64 +++++++++ .../ImageStreamImportMode.yaml | 64 +++++++++ .../KMSEncryptionProvider.yaml | 64 +++++++++ .../NetworkDiagnosticsConfig.yaml | 64 +++++++++ .../OpenStack.yaml | 64 +++++++++ .../AAA_ungated.yaml | 64 +++++++++ .../AutoNodeKarpenter.yaml | 64 +++++++++ .../ClusterVersionOperatorConfiguration.yaml | 64 +++++++++ .../ExternalOIDC.yaml | 64 +++++++++ ...ernalOIDCWithUIDAndExtraClaimMappings.yaml | 64 +++++++++ .../GCPPlatform.yaml | 64 +++++++++ ...perShiftOnlyDynamicResourceAllocation.yaml | 64 +++++++++ .../ImageStreamImportMode.yaml | 64 +++++++++ .../KMSEncryptionProvider.yaml | 64 +++++++++ .../NetworkDiagnosticsConfig.yaml | 64 +++++++++ .../OpenStack.yaml | 64 +++++++++ .../hypershift/v1beta1/ovnipv6config.go | 47 +++++++ .../hypershift/v1beta1/ovnkubernetesconfig.go | 9 ++ client/applyconfiguration/utils.go | 2 + ...usters-Hypershift-CustomNoUpgrade.crd.yaml | 64 +++++++++ ...hostedclusters-Hypershift-Default.crd.yaml | 64 +++++++++ ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 64 +++++++++ ...planes-Hypershift-CustomNoUpgrade.crd.yaml | 64 +++++++++ ...dcontrolplanes-Hypershift-Default.crd.yaml | 64 +++++++++ ...s-Hypershift-TechPreviewNoUpgrade.crd.yaml | 64 +++++++++ .../resources/network/reconcile.go | 25 ++++ .../resources/network/reconcile_test.go | 98 ++++++++++++++ docs/content/reference/api.md | 81 ++++++++++++ .../hostedcluster/hostedcluster_controller.go | 28 ++++ .../hostedcluster_controller_test.go | 125 ++++++++++++++++-- .../api/hypershift/v1beta1/operator.go | 49 +++++++ .../v1beta1/zz_generated.deepcopy.go | 16 +++ 40 files changed, 2328 insertions(+), 9 deletions(-) create mode 100644 client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go diff --git a/api/hypershift/v1beta1/operator.go b/api/hypershift/v1beta1/operator.go index c1e455682903..6e902f9c3e29 100644 --- a/api/hypershift/v1beta1/operator.go +++ b/api/hypershift/v1beta1/operator.go @@ -62,6 +62,7 @@ type ClusterNetworkOperatorSpec struct { // OVNKubernetesConfig contains OVN-Kubernetes specific configuration options. // https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L400-L471 // +kubebuilder:validation:XValidation:rule="!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet", message="internalJoinSubnet and internalTransitSwitchSubnet must not be the same" +// +kubebuilder:validation:XValidation:rule="!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet != self.ipv6.internalTransitSwitchSubnet", message="IPv6 internalJoinSubnet and internalTransitSwitchSubnet must not be the same" // +kubebuilder:validation:MinProperties=1 type OVNKubernetesConfig struct { // ipv4 allows users to configure IP settings for IPv4 connections. When omitted, @@ -69,6 +70,15 @@ type OVNKubernetesConfig struct { // fields within ipv4 for details of default values. // +optional IPv4 *OVNIPv4Config `json:"ipv4,omitempty"` + + // ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + // this means no opinions and the default configuration is used. Check individual + // fields within ipv6 for details of default values. + // For KubeVirt hosted clusters using dual-stack networking, it is recommended to + // set ipv6.internalJoinSubnet to a value different from the management cluster's + // join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + // +optional + IPv6 OVNIPv6Config `json:"ipv6,omitzero,omitempty"` } // OVNIPv4Config contains IPv4-specific configuration options for OVN-Kubernetes. @@ -108,6 +118,45 @@ type OVNIPv4Config struct { InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` } +// OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes. +// +kubebuilder:validation:MinProperties=1 +type OVNIPv6Config struct { + // internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + // by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + // architecture that connects the cluster routers on each node together to enable + // east west traffic. The subnet chosen should not overlap with other networks + // specified for OVN-Kubernetes as well as other networks used on the host. + // When omitted, this means no opinion and the platform is left to choose a reasonable + // default which is subject to change over time. + // The current default subnet is fd97::/64. + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be in proper IPv6 CIDR format. + // Note that IPv6 dual addresses are not permitted. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="self.matches('^\\\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$')", message="Subnet must be in valid IPv6 CIDR format (e.g., fd97::/64)" + // +kubebuilder:validation:XValidation:rule="self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +optional + InternalTransitSwitchSubnet string `json:"internalTransitSwitchSubnet,omitempty"` + // internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + // default one is being already used by something else. It must not overlap with + // any other subnet being used by OpenShift or by the node network. The size of the + // subnet must be larger than the number of nodes. + // The current default value is fd98::/64. + // For KubeVirt hosted clusters, if this field is not set, HyperShift will + // automatically use fd99::/64 to avoid collisions with the management cluster's + // default join subnet (fd98::/64). + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be in proper IPv6 CIDR format. + // Note that IPv6 dual addresses are not permitted. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="self.matches('^\\\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$')", message="Subnet must be in valid IPv6 CIDR format (e.g., fd98::/64)" + // +kubebuilder:validation:XValidation:rule="self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +optional + InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` +} + // IngressOperatorSpec is the specification of the desired behavior of the Ingress Operator. type IngressOperatorSpec struct { // endpointPublishingStrategy is used to publish the default ingress controller endpoints. diff --git a/api/hypershift/v1beta1/zz_generated.deepcopy.go b/api/hypershift/v1beta1/zz_generated.deepcopy.go index 033c005b7996..06e27795385d 100644 --- a/api/hypershift/v1beta1/zz_generated.deepcopy.go +++ b/api/hypershift/v1beta1/zz_generated.deepcopy.go @@ -3205,6 +3205,21 @@ func (in *OVNIPv4Config) DeepCopy() *OVNIPv4Config { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OVNIPv6Config) DeepCopyInto(out *OVNIPv6Config) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNIPv6Config. +func (in *OVNIPv6Config) DeepCopy() *OVNIPv6Config { + if in == nil { + return nil + } + out := new(OVNIPv6Config) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = *in @@ -3213,6 +3228,7 @@ func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = new(OVNIPv4Config) **out = **in } + out.IPv6 = in.IPv6 } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNKubernetesConfig. diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml index 67d4c67aa1b8..fa76c5bd88a6 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AAA_ungated.yaml @@ -2908,6 +2908,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2915,6 +2974,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml index 6f97b3457f9c..2b6acde6cc57 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/AutoNodeKarpenter.yaml @@ -2946,6 +2946,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2953,6 +3012,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml index 0a323bb4efe0..7f68212bb754 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml @@ -2899,6 +2899,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2906,6 +2965,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object clusterVersionOperator: description: clusterVersionOperator specifies the configuration diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml index 6754575c6eb3..1eede2f18bfa 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDC.yaml @@ -3256,6 +3256,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3263,6 +3322,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml index 2d921aefee19..c53ce18fc700 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml @@ -3410,6 +3410,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3417,6 +3476,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml index 22364d504b01..b4b900474429 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/GCPPlatform.yaml @@ -2899,6 +2899,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2906,6 +2965,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml index a289044c10fc..7365430d6092 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml @@ -2921,6 +2921,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2928,6 +2987,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml index 8367c5054ed6..0f34b3ea661b 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/ImageStreamImportMode.yaml @@ -2917,6 +2917,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2924,6 +2983,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml index 0dc3539806fc..228b7ef738ba 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/KMSEncryptionProvider.yaml @@ -2975,6 +2975,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2982,6 +3041,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml index e4f7780bc9d6..6d628fbc1e31 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml @@ -3051,6 +3051,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3058,6 +3117,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml index ca5271513024..7ea39d59e856 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedclusters.hypershift.openshift.io/OpenStack.yaml @@ -2899,6 +2899,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2906,6 +2965,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml index b3f2af593574..36deab38e0e5 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AAA_ungated.yaml @@ -2808,6 +2808,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2815,6 +2874,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml index 5f530d52a9d0..23cb4c34122a 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/AutoNodeKarpenter.yaml @@ -2846,6 +2846,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2853,6 +2912,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml index 9fe3f7cdda1e..78987c3ceb74 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ClusterVersionOperatorConfiguration.yaml @@ -2799,6 +2799,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2806,6 +2865,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object clusterVersionOperator: description: clusterVersionOperator specifies the configuration diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml index bbc0a377f1cf..1989eb0a7d65 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDC.yaml @@ -3156,6 +3156,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3163,6 +3222,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml index 8cd1b1a5fadc..8faee6f2a4b4 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ExternalOIDCWithUIDAndExtraClaimMappings.yaml @@ -3310,6 +3310,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3317,6 +3376,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml index 8841aba982ec..2b0778a66d25 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/GCPPlatform.yaml @@ -2799,6 +2799,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2806,6 +2865,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml index b6fbd0537dfa..9418b0426b55 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/HyperShiftOnlyDynamicResourceAllocation.yaml @@ -2821,6 +2821,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2828,6 +2887,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml index 1ca8beb484a9..5b16187601c4 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/ImageStreamImportMode.yaml @@ -2817,6 +2817,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2824,6 +2883,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml index d6aa6a4163cd..49799e6d6c9e 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/KMSEncryptionProvider.yaml @@ -2875,6 +2875,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2882,6 +2941,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml index 99810c89aef7..8ca736db2b15 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/NetworkDiagnosticsConfig.yaml @@ -2951,6 +2951,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2958,6 +3017,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml index 9e019144a409..a5dda6b1f681 100644 --- a/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml +++ b/api/hypershift/v1beta1/zz_generated.featuregated-crd-manifests/hostedcontrolplanes.hypershift.openshift.io/OpenStack.yaml @@ -2799,6 +2799,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -2806,6 +2865,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go b/client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go new file mode 100644 index 000000000000..2205ac30a97e --- /dev/null +++ b/client/applyconfiguration/hypershift/v1beta1/ovnipv6config.go @@ -0,0 +1,47 @@ +/* + + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ +// Code generated by applyconfiguration-gen. DO NOT EDIT. + +package v1beta1 + +// OVNIPv6ConfigApplyConfiguration represents a declarative configuration of the OVNIPv6Config type for use +// with apply. +type OVNIPv6ConfigApplyConfiguration struct { + InternalTransitSwitchSubnet *string `json:"internalTransitSwitchSubnet,omitempty"` + InternalJoinSubnet *string `json:"internalJoinSubnet,omitempty"` +} + +// OVNIPv6ConfigApplyConfiguration constructs a declarative configuration of the OVNIPv6Config type for use with +// apply. +func OVNIPv6Config() *OVNIPv6ConfigApplyConfiguration { + return &OVNIPv6ConfigApplyConfiguration{} +} + +// WithInternalTransitSwitchSubnet sets the InternalTransitSwitchSubnet field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the InternalTransitSwitchSubnet field is set to the value of the last call. +func (b *OVNIPv6ConfigApplyConfiguration) WithInternalTransitSwitchSubnet(value string) *OVNIPv6ConfigApplyConfiguration { + b.InternalTransitSwitchSubnet = &value + return b +} + +// WithInternalJoinSubnet sets the InternalJoinSubnet field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the InternalJoinSubnet field is set to the value of the last call. +func (b *OVNIPv6ConfigApplyConfiguration) WithInternalJoinSubnet(value string) *OVNIPv6ConfigApplyConfiguration { + b.InternalJoinSubnet = &value + return b +} diff --git a/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go b/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go index 28220930f5cd..0e2832da983d 100644 --- a/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go +++ b/client/applyconfiguration/hypershift/v1beta1/ovnkubernetesconfig.go @@ -21,6 +21,7 @@ package v1beta1 // with apply. type OVNKubernetesConfigApplyConfiguration struct { IPv4 *OVNIPv4ConfigApplyConfiguration `json:"ipv4,omitempty"` + IPv6 *OVNIPv6ConfigApplyConfiguration `json:"ipv6,omitempty"` } // OVNKubernetesConfigApplyConfiguration constructs a declarative configuration of the OVNKubernetesConfig type for use with @@ -36,3 +37,11 @@ func (b *OVNKubernetesConfigApplyConfiguration) WithIPv4(value *OVNIPv4ConfigApp b.IPv4 = value return b } + +// WithIPv6 sets the IPv6 field in the declarative configuration to the given value +// and returns the receiver, so that objects can be built by chaining "With" function invocations. +// If called multiple times, the IPv6 field is set to the value of the last call. +func (b *OVNKubernetesConfigApplyConfiguration) WithIPv6(value *OVNIPv6ConfigApplyConfiguration) *OVNKubernetesConfigApplyConfiguration { + b.IPv6 = value + return b +} diff --git a/client/applyconfiguration/utils.go b/client/applyconfiguration/utils.go index 00fde501d38c..d1dafc8ed848 100644 --- a/client/applyconfiguration/utils.go +++ b/client/applyconfiguration/utils.go @@ -293,6 +293,8 @@ func ForKind(kind schema.GroupVersionKind) interface{} { return &hypershiftv1beta1.OperatorConfigurationApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("OVNIPv4Config"): return &hypershiftv1beta1.OVNIPv4ConfigApplyConfiguration{} + case v1beta1.SchemeGroupVersion.WithKind("OVNIPv6Config"): + return &hypershiftv1beta1.OVNIPv6ConfigApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("OVNKubernetesConfig"): return &hypershiftv1beta1.OVNKubernetesConfigApplyConfiguration{} case v1beta1.SchemeGroupVersion.WithKind("PersistentVolumeEtcdStorageSpec"): diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml index 9fdbd7f66d07..b7dc8ef45557 100644 --- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml +++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-CustomNoUpgrade.crd.yaml @@ -3727,6 +3727,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3734,6 +3793,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object clusterVersionOperator: description: clusterVersionOperator specifies the configuration diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml index a38ac68dfd6d..71c2a8626206 100644 --- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml +++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-Default.crd.yaml @@ -3591,6 +3591,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3598,6 +3657,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml index 6e1abf441e60..27bdfb998229 100644 --- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml +++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedclusters-Hypershift-TechPreviewNoUpgrade.crd.yaml @@ -3638,6 +3638,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3645,6 +3704,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object clusterVersionOperator: description: clusterVersionOperator specifies the configuration diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml index 79c28ac986aa..401ff1ec16b9 100644 --- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml +++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-CustomNoUpgrade.crd.yaml @@ -3627,6 +3627,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3634,6 +3693,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object clusterVersionOperator: description: clusterVersionOperator specifies the configuration diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml index c2d3f779771d..7fc7b4cc4a5f 100644 --- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml +++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-Default.crd.yaml @@ -3491,6 +3491,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3498,6 +3557,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object ingressOperator: description: |- diff --git a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml index 5062a7530618..532ec687a0ca 100644 --- a/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml +++ b/cmd/install/assets/hypershift-operator/zz_generated.crd-manifests/hostedcontrolplanes-Hypershift-TechPreviewNoUpgrade.crd.yaml @@ -3538,6 +3538,65 @@ spec: rule: self.matches('^[0-9]{1,3}\\..*') && int(self.split('/')[0].split('.')[0]) > 0 type: object + ipv6: + description: |- + ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + this means no opinions and the default configuration is used. Check individual + fields within ipv6 for details of default values. + For KubeVirt hosted clusters using dual-stack networking, it is recommended to + set ipv6.internalJoinSubnet to a value different from the management cluster's + join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + minProperties: 1 + properties: + internalJoinSubnet: + description: |- + internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + default one is being already used by something else. It must not overlap with + any other subnet being used by OpenShift or by the node network. The size of the + subnet must be larger than the number of nodes. + The current default value is fd98::/64. + For KubeVirt hosted clusters, if this field is not set, HyperShift will + automatically use fd99::/64 to avoid collisions with the management cluster's + default join subnet (fd98::/64). + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd98::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + internalTransitSwitchSubnet: + description: |- + internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + architecture that connects the cluster routers on each node together to enable + east west traffic. The subnet chosen should not overlap with other networks + specified for OVN-Kubernetes as well as other networks used on the host. + When omitted, this means no opinion and the platform is left to choose a reasonable + default which is subject to change over time. + The current default subnet is fd97::/64. + The subnet must be large enough to accommodate one IP per node in your cluster. + The value must be in proper IPv6 CIDR format. + Note that IPv6 dual addresses are not permitted. + maxLength: 48 + minLength: 3 + type: string + x-kubernetes-validations: + - message: Subnet must be in valid IPv6 CIDR format + (e.g., fd97::/64) + rule: self.matches('^\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$') + - message: subnet must be in the range /0 to /125 + inclusive + rule: self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) + <= 125 + type: object type: object x-kubernetes-validations: - message: internalJoinSubnet and internalTransitSwitchSubnet @@ -3545,6 +3604,11 @@ spec: rule: '!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet' + - message: IPv6 internalJoinSubnet and internalTransitSwitchSubnet + must not be the same + rule: '!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) + || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet + != self.ipv6.internalTransitSwitchSubnet' type: object clusterVersionOperator: description: clusterVersionOperator specifies the configuration diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go index b37768bc8563..5bd16b71f1b1 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile.go @@ -36,6 +36,12 @@ const kubevirtDefaultGenevePort = uint32(9880) // is 100.65.0.0/16. We need to avoid that for kubernetes which runs nested. const kubevirtDefaultV4InternalSubnet = "100.66.0.0/16" +// The default OVN IPv6 join subnet is fd98::/64. We need to avoid that for +// KubeVirt hosted clusters which run nested, because both the management and +// guest clusters would use the same join subnet, causing IPv6 routing conflicts +// when external traffic is SNAT'd to a join switch IP. +const kubevirtDefaultV6InternalJoinSubnet = "fd99::/64" + func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.NetworkType, platformType hyperv1.PlatformType, disableMultiNetwork bool, ovnConfig *hyperv1.OVNKubernetesConfig) { switch platformType { case hyperv1.KubevirtPlatform: @@ -60,6 +66,12 @@ func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.N if network.Spec.DefaultNetwork.OVNKubernetesConfig.GenevePort == nil { network.Spec.DefaultNetwork.OVNKubernetesConfig.GenevePort = &port } + if network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6 == nil { + network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6 = &operatorv1.IPv6OVNKubernetesConfig{} + } + if network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6.InternalJoinSubnet == "" { + network.Spec.DefaultNetwork.OVNKubernetesConfig.IPv6.InternalJoinSubnet = kubevirtDefaultV6InternalJoinSubnet + } } case hyperv1.PowerVSPlatform: if networkType == hyperv1.OVNKubernetes { @@ -94,6 +106,19 @@ func ReconcileNetworkOperator(network *operatorv1.Network, networkType hyperv1.N ovnCfg.IPv4.InternalTransitSwitchSubnet = ovnConfig.IPv4.InternalTransitSwitchSubnet } } + // Apply IPv6 configuration + if ovnConfig.IPv6.InternalJoinSubnet != "" { + if ovnCfg.IPv6 == nil { + ovnCfg.IPv6 = &operatorv1.IPv6OVNKubernetesConfig{} + } + ovnCfg.IPv6.InternalJoinSubnet = ovnConfig.IPv6.InternalJoinSubnet + } + if ovnConfig.IPv6.InternalTransitSwitchSubnet != "" { + if ovnCfg.IPv6 == nil { + ovnCfg.IPv6 = &operatorv1.IPv6OVNKubernetesConfig{} + } + ovnCfg.IPv6.InternalTransitSwitchSubnet = ovnConfig.IPv6.InternalTransitSwitchSubnet + } } // Setting the management state is required in order to create diff --git a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go index 19160194dbc9..734246d77c71 100644 --- a/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go +++ b/control-plane-operator/hostedclusterconfigoperator/controllers/resources/network/reconcile_test.go @@ -16,6 +16,7 @@ func TestReconcileDefaultIngressController(t *testing.T) { vxlanPort := kubevirtDefaultVXLANPort genevePort := kubevirtDefaultGenevePort v4InternalSubnet := kubevirtDefaultV4InternalSubnet + v6InternalJoinSubnet := kubevirtDefaultV6InternalJoinSubnet fakePort := uint32(11111) testsCases := []struct { @@ -43,6 +44,9 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ GenevePort: &genevePort, V4InternalSubnet: v4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, }, }, }, @@ -129,6 +133,9 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ GenevePort: &fakePort, V4InternalSubnet: kubevirtDefaultV4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, }, }, }, @@ -163,6 +170,9 @@ func TestReconcileDefaultIngressController(t *testing.T) { OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ V4InternalSubnet: "100.66.0.0/16", GenevePort: &genevePort, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: v6InternalJoinSubnet, + }, }, }, }, @@ -356,6 +366,94 @@ func TestReconcileDefaultIngressController(t *testing.T) { }, }, }, + { + name: "When IPv6 subnets configured for OVN Kubernetes it should propagate to network operator", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.AWSPlatform, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd97::/64", + }, + }, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd97::/64", + }, + }, + }, + }, + }, + }, + { + name: "When OVN config has IPv4 and IPv6 subnets it should propagate both", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.AWSPlatform, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv4: &hyperv1.OVNIPv4Config{ + InternalJoinSubnet: "100.64.0.0/16", + }, + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + IPv4: &operatorv1.IPv4OVNKubernetesConfig{ + InternalJoinSubnet: "100.64.0.0/16", + }, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fd99::/64", + }, + }, + }, + }, + }, + }, + { + name: "When KubeVirt with user-specified IPv6 join subnet it should not override", + inputNetwork: NetworkOperator(), + inputNetworkType: hyperv1.OVNKubernetes, + inputPlatformType: hyperv1.KubevirtPlatform, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fdbb::/64", + }, + }, + expectedNetwork: &operatorv1.Network{ + ObjectMeta: NetworkOperator().ObjectMeta, + Spec: operatorv1.NetworkSpec{ + OperatorSpec: operatorv1.OperatorSpec{ + ManagementState: "Managed", + }, + DefaultNetwork: operatorv1.DefaultNetworkDefinition{ + OVNKubernetesConfig: &operatorv1.OVNKubernetesConfig{ + GenevePort: &genevePort, + V4InternalSubnet: v4InternalSubnet, + IPv6: &operatorv1.IPv6OVNKubernetesConfig{ + InternalJoinSubnet: "fdbb::/64", + }, + }, + }, + }, + }, + }, } for _, tc := range testsCases { diff --git a/docs/content/reference/api.md b/docs/content/reference/api.md index ed2fdc2c4da9..fc2dede23c5b 100644 --- a/docs/content/reference/api.md +++ b/docs/content/reference/api.md @@ -10911,6 +10911,68 @@ The value must be in proper IPV4 CIDR format

+###OVNIPv6Config { #hypershift.openshift.io/v1beta1.OVNIPv6Config } +

+(Appears on: +OVNKubernetesConfig) +

+

+

OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes.

+

+ + + + + + + + + + + + + + + + + +
FieldDescription
+internalTransitSwitchSubnet
+ +string + +
+(Optional) +

internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally +by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect +architecture that connects the cluster routers on each node together to enable +east west traffic. The subnet chosen should not overlap with other networks +specified for OVN-Kubernetes as well as other networks used on the host. +When omitted, this means no opinion and the platform is left to choose a reasonable +default which is subject to change over time. +The current default subnet is fd97::/64. +The subnet must be large enough to accommodate one IP per node in your cluster. +The value must be in proper IPv6 CIDR format. +Note that IPv6 dual addresses are not permitted.

+
+internalJoinSubnet
+ +string + +
+(Optional) +

internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the +default one is being already used by something else. It must not overlap with +any other subnet being used by OpenShift or by the node network. The size of the +subnet must be larger than the number of nodes. +The current default value is fd98::/64. +For KubeVirt hosted clusters, if this field is not set, HyperShift will +automatically use fd99::/64 to avoid collisions with the management cluster’s +default join subnet (fd98::/64). +The subnet must be large enough to accommodate one IP per node in your cluster. +The value must be in proper IPv6 CIDR format. +Note that IPv6 dual addresses are not permitted.

+
###OVNKubernetesConfig { #hypershift.openshift.io/v1beta1.OVNKubernetesConfig }

(Appears on: @@ -10944,6 +11006,25 @@ this means no opinions and the default configuration is used. Check individual fields within ipv4 for details of default values.

+ + +ipv6,omitzero
+ + +OVNIPv6Config + + + + +(Optional) +

ipv6 allows users to configure IP settings for IPv6 connections. When omitted, +this means no opinions and the default configuration is used. Check individual +fields within ipv6 for details of default values. +For KubeVirt hosted clusters using dual-stack networking, it is recommended to +set ipv6.internalJoinSubnet to a value different from the management cluster’s +join subnet (default fd98::/64) to avoid IPv6 routing conflicts.

+ + ###ObjectEncodingFormat { #hypershift.openshift.io/v1beta1.ObjectEncodingFormat } diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go index 2c72e5b62554..076a307fb00f 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller.go @@ -4155,6 +4155,34 @@ func validateSliceNetworkCIDRs(hc *hyperv1.HostedCluster) field.ErrorList { } } } + + if hc.Spec.Networking.NetworkType == hyperv1.OVNKubernetes { + var ipv6JoinSubnet, ipv6TransitSubnet string + if hc.Spec.OperatorConfiguration != nil && hc.Spec.OperatorConfiguration.ClusterNetworkOperator != nil && + hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig != nil { + ipv6JoinSubnet = hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig.IPv6.InternalJoinSubnet + ipv6TransitSubnet = hc.Spec.OperatorConfiguration.ClusterNetworkOperator.OVNKubernetesConfig.IPv6.InternalTransitSwitchSubnet + } + // The reconciler defaults KubeVirt IPv6 join subnet to fd99::/64; + // include the effective value so overlaps are caught at admission time. + if ipv6JoinSubnet == "" && hc.Spec.Platform.Type == hyperv1.KubevirtPlatform { + ipv6JoinSubnet = "fd99::/64" + } + if ipv6JoinSubnet != "" { + _, cidr, err := net.ParseCIDR(ipv6JoinSubnet) + if err == nil { + ce := cidrEntry{*cidr, *field.NewPath("spec", "operatorConfiguration", "clusterNetworkOperator", "ovnKubernetesConfig", "ipv6", "internalJoinSubnet")} + cidrEntries = append(cidrEntries, ce) + } + } + if ipv6TransitSubnet != "" { + _, cidr, err := net.ParseCIDR(ipv6TransitSubnet) + if err == nil { + ce := cidrEntry{*cidr, *field.NewPath("spec", "operatorConfiguration", "clusterNetworkOperator", "ovnKubernetesConfig", "ipv6", "internalTransitSwitchSubnet")} + cidrEntries = append(cidrEntries, ce) + } + } + } return compareCIDREntries(cidrEntries) } diff --git a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go index ed2ef823b879..1532253a8931 100644 --- a/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go +++ b/hypershift-operator/controllers/hostedcluster/hostedcluster_controller_test.go @@ -3504,13 +3504,14 @@ func TestComputeAWSEndpointServiceCondition(t *testing.T) { func TestValidateSliceNetworkCIDRs(t *testing.T) { tests := []struct { - name string - mn []hyperv1.MachineNetworkEntry - cn []hyperv1.ClusterNetworkEntry - sn []hyperv1.ServiceNetworkEntry - networkType hyperv1.NetworkType - ovnConfig *hyperv1.OVNKubernetesConfig - wantErr bool + name string + mn []hyperv1.MachineNetworkEntry + cn []hyperv1.ClusterNetworkEntry + sn []hyperv1.ServiceNetworkEntry + networkType hyperv1.NetworkType + platformType hyperv1.PlatformType + ovnConfig *hyperv1.OVNKubernetesConfig + wantErr bool }{ { name: "given a conflicting IPv6 clusterNetwork overlapped with machineNetwork, it should fail", @@ -3655,6 +3656,111 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { }, wantErr: false, }, + { + name: "When OVN-Kubernetes with valid IPv6 internal join and transit subnets it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd97::/64", + }, + }, + wantErr: false, + }, + { + name: "When OVN-Kubernetes IPv6 internal join subnet overlaps with MachineNetwork it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd99::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + wantErr: true, + }, + { + name: "When OVN-Kubernetes IPv6 OVN subnets overlap with each other it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + InternalTransitSwitchSubnet: "fd99::/64", + }, + }, + wantErr: true, + }, + { + name: "When OVN-Kubernetes with combined valid IPv4 and IPv6 subnets it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("10.128.0.0/14")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("172.30.0.0/16")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv4: &hyperv1.OVNIPv4Config{ + InternalJoinSubnet: "100.64.0.0/16", + }, + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fd99::/64", + }, + }, + wantErr: false, + }, + { + name: "When OVN-Kubernetes with empty IPv6 subnet strings it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("192.168.1.0/24")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("10.128.0.0/14")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("172.30.0.0/16")}}, + networkType: hyperv1.OVNKubernetes, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "", + InternalTransitSwitchSubnet: "", + }, + }, + wantErr: false, + }, + { + name: "When KubeVirt OVN-Kubernetes with no IPv6 config and MachineNetwork overlaps default fd99::/64 it should fail", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd99::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/112")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: nil, + wantErr: true, + }, + { + name: "When KubeVirt OVN-Kubernetes with no IPv6 config and non-overlapping networks it should succeed", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd03::/112")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: nil, + wantErr: false, + }, + { + name: "When KubeVirt OVN-Kubernetes with explicit IPv6 join subnet it should use explicit value not default", + mn: []hyperv1.MachineNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd99::/48")}}, + cn: []hyperv1.ClusterNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd01::/64")}}, + sn: []hyperv1.ServiceNetworkEntry{{CIDR: *ipnet.MustParseCIDR("fd02::/112")}}, + networkType: hyperv1.OVNKubernetes, + platformType: hyperv1.KubevirtPlatform, + ovnConfig: &hyperv1.OVNKubernetesConfig{ + IPv6: hyperv1.OVNIPv6Config{ + InternalJoinSubnet: "fdaa::/64", + }, + }, + wantErr: false, + }, } for _, tt := range tests { @@ -3665,6 +3771,9 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { Namespace: "any", }, Spec: hyperv1.HostedClusterSpec{ + Platform: hyperv1.PlatformSpec{ + Type: tt.platformType, + }, Networking: hyperv1.ClusterNetworking{ NetworkType: tt.networkType, MachineNetwork: tt.mn, @@ -3674,9 +3783,7 @@ func TestValidateSliceNetworkCIDRs(t *testing.T) { }, } - // Set OVN configuration if provided if tt.ovnConfig != nil { - //OperatorConfiguration hc.Spec.OperatorConfiguration = &hyperv1.OperatorConfiguration{ ClusterNetworkOperator: &hyperv1.ClusterNetworkOperatorSpec{ OVNKubernetesConfig: tt.ovnConfig, diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go index c1e455682903..6e902f9c3e29 100644 --- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go +++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/operator.go @@ -62,6 +62,7 @@ type ClusterNetworkOperatorSpec struct { // OVNKubernetesConfig contains OVN-Kubernetes specific configuration options. // https://github.com/openshift/api/blob/6d3c4e25a8d3aeb57ad61649d80c38cbd27d1cc8/operator/v1/types_network.go#L400-L471 // +kubebuilder:validation:XValidation:rule="!has(self.ipv4) || !has(self.ipv4.internalJoinSubnet) || !has(self.ipv4.internalTransitSwitchSubnet) || self.ipv4.internalJoinSubnet != self.ipv4.internalTransitSwitchSubnet", message="internalJoinSubnet and internalTransitSwitchSubnet must not be the same" +// +kubebuilder:validation:XValidation:rule="!has(self.ipv6) || !has(self.ipv6.internalJoinSubnet) || !has(self.ipv6.internalTransitSwitchSubnet) || self.ipv6.internalJoinSubnet != self.ipv6.internalTransitSwitchSubnet", message="IPv6 internalJoinSubnet and internalTransitSwitchSubnet must not be the same" // +kubebuilder:validation:MinProperties=1 type OVNKubernetesConfig struct { // ipv4 allows users to configure IP settings for IPv4 connections. When omitted, @@ -69,6 +70,15 @@ type OVNKubernetesConfig struct { // fields within ipv4 for details of default values. // +optional IPv4 *OVNIPv4Config `json:"ipv4,omitempty"` + + // ipv6 allows users to configure IP settings for IPv6 connections. When omitted, + // this means no opinions and the default configuration is used. Check individual + // fields within ipv6 for details of default values. + // For KubeVirt hosted clusters using dual-stack networking, it is recommended to + // set ipv6.internalJoinSubnet to a value different from the management cluster's + // join subnet (default fd98::/64) to avoid IPv6 routing conflicts. + // +optional + IPv6 OVNIPv6Config `json:"ipv6,omitzero,omitempty"` } // OVNIPv4Config contains IPv4-specific configuration options for OVN-Kubernetes. @@ -108,6 +118,45 @@ type OVNIPv4Config struct { InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` } +// OVNIPv6Config contains IPv6-specific configuration options for OVN-Kubernetes. +// +kubebuilder:validation:MinProperties=1 +type OVNIPv6Config struct { + // internalTransitSwitchSubnet is a v6 subnet in IPv6 CIDR format used internally + // by OVN-Kubernetes for the distributed transit switch in the OVN Interconnect + // architecture that connects the cluster routers on each node together to enable + // east west traffic. The subnet chosen should not overlap with other networks + // specified for OVN-Kubernetes as well as other networks used on the host. + // When omitted, this means no opinion and the platform is left to choose a reasonable + // default which is subject to change over time. + // The current default subnet is fd97::/64. + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be in proper IPv6 CIDR format. + // Note that IPv6 dual addresses are not permitted. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="self.matches('^\\\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$')", message="Subnet must be in valid IPv6 CIDR format (e.g., fd97::/64)" + // +kubebuilder:validation:XValidation:rule="self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +optional + InternalTransitSwitchSubnet string `json:"internalTransitSwitchSubnet,omitempty"` + // internalJoinSubnet is a v6 subnet used internally by ovn-kubernetes in case the + // default one is being already used by something else. It must not overlap with + // any other subnet being used by OpenShift or by the node network. The size of the + // subnet must be larger than the number of nodes. + // The current default value is fd98::/64. + // For KubeVirt hosted clusters, if this field is not set, HyperShift will + // automatically use fd99::/64 to avoid collisions with the management cluster's + // default join subnet (fd98::/64). + // The subnet must be large enough to accommodate one IP per node in your cluster. + // The value must be in proper IPv6 CIDR format. + // Note that IPv6 dual addresses are not permitted. + // +kubebuilder:validation:MaxLength=48 + // +kubebuilder:validation:MinLength=3 + // +kubebuilder:validation:XValidation:rule="self.matches('^\\\\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){5}((:[0-9A-Fa-f]{1,4}){1,2}|:))|(([0-9A-Fa-f]{1,4}:){4}((:[0-9A-Fa-f]{1,4}){1,3}|:))|(([0-9A-Fa-f]{1,4}:){3}((:[0-9A-Fa-f]{1,4}){1,4}|:))|(([0-9A-Fa-f]{1,4}:){2}((:[0-9A-Fa-f]{1,4}){1,5}|:))|(([0-9A-Fa-f]{1,4}:){1}((:[0-9A-Fa-f]{1,4}){1,6}|:))|(::((:[0-9A-Fa-f]{1,4}){1,7}|:)))\\\\s*/([0-9]|[1-9][0-9]|1[0-1][0-9]|12[0-8])$')", message="Subnet must be in valid IPv6 CIDR format (e.g., fd98::/64)" + // +kubebuilder:validation:XValidation:rule="self.matches('^.*/[0-9]+$') && int(self.split('/')[1]) <= 125", message="subnet must be in the range /0 to /125 inclusive" + // +optional + InternalJoinSubnet string `json:"internalJoinSubnet,omitempty"` +} + // IngressOperatorSpec is the specification of the desired behavior of the Ingress Operator. type IngressOperatorSpec struct { // endpointPublishingStrategy is used to publish the default ingress controller endpoints. diff --git a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go index 033c005b7996..06e27795385d 100644 --- a/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go +++ b/vendor/github.com/openshift/hypershift/api/hypershift/v1beta1/zz_generated.deepcopy.go @@ -3205,6 +3205,21 @@ func (in *OVNIPv4Config) DeepCopy() *OVNIPv4Config { return out } +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *OVNIPv6Config) DeepCopyInto(out *OVNIPv6Config) { + *out = *in +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNIPv6Config. +func (in *OVNIPv6Config) DeepCopy() *OVNIPv6Config { + if in == nil { + return nil + } + out := new(OVNIPv6Config) + in.DeepCopyInto(out) + return out +} + // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = *in @@ -3213,6 +3228,7 @@ func (in *OVNKubernetesConfig) DeepCopyInto(out *OVNKubernetesConfig) { *out = new(OVNIPv4Config) **out = **in } + out.IPv6 = in.IPv6 } // DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new OVNKubernetesConfig.