Skip to content

Commit 2ab22a7

Browse files
committed
Add Gateway API support for SolrCloud external addressability
Implements Kubernetes Gateway API as a new external addressability method, enabling HTTPRoute-based routing for SolrCloud services. - Add Gateway API types and controller logic - Generate HTTPRoutes for common and per-node services - Add RBAC for HTTPRoute and BackendTLSPolicy - Update CRDs, Helm charts, and documentation - Add E2E tests following existing Ingress test patterns
1 parent ca9d3c5 commit 2ab22a7

13 files changed

Lines changed: 912 additions & 7 deletions

File tree

api/v1beta1/solrcloud_types.go

Lines changed: 69 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -563,11 +563,20 @@ type ExternalAddressability struct {
563563
//
564564
// +optional
565565
IngressTLSTermination *SolrIngressTLSTermination `json:"ingressTLSTermination,omitempty"`
566+
567+
// Gateway defines settings for Kubernetes Gateway API routing.
568+
//
569+
// This option is only available when Method=Gateway.
570+
// The referenced Gateway must already exist and be managed by your platform team.
571+
// The Solr Operator only manages the HTTPRoute resources.
572+
//
573+
// +optional
574+
Gateway *SolrGatewayOptions `json:"gateway,omitempty"`
566575
}
567576

568577
// ExternalAddressabilityMethod is a string enumeration type that enumerates
569578
// all possible ways that a SolrCloud can be made addressable external to the kubernetes cluster.
570-
// +kubebuilder:validation:Enum=Ingress;ExternalDNS
579+
// +kubebuilder:validation:Enum=Ingress;ExternalDNS;Gateway
571580
type ExternalAddressabilityMethod string
572581

573582
const (
@@ -577,6 +586,9 @@ const (
577586
// Use ExternalDNS to make the Solr service(s) externally addressable
578587
ExternalDNS ExternalAddressabilityMethod = "ExternalDNS"
579588

589+
// Use Gateway API to make the Solr service(s) externally addressable
590+
Gateway ExternalAddressabilityMethod = "Gateway"
591+
580592
// Make Solr service(s) type:LoadBalancer to make them externally addressable
581593
// NOTE: This option is not currently supported.
582594
LoadBalancer ExternalAddressabilityMethod = "LoadBalancer"
@@ -626,6 +638,42 @@ type SolrIngressTLSTermination struct {
626638
TLSSecret string `json:"tlsSecret,omitempty"`
627639
}
628640

641+
// SolrGatewayOptions defines how a SolrCloud should be exposed via Kubernetes Gateway API
642+
type SolrGatewayOptions struct {
643+
// ParentRefs specifies the Gateway(s) to attach HTTPRoutes to.
644+
// This is required when using method=Gateway.
645+
//
646+
// The referenced Gateway must already exist and be managed by your platform team.
647+
// The Solr Operator only manages the HTTPRoute resources.
648+
//
649+
// +kubebuilder:validation:MinItems=1
650+
ParentRefs []GatewayParentReference `json:"parentRefs"`
651+
652+
// Annotations to add to HTTPRoute resources
653+
// +optional
654+
Annotations map[string]string `json:"annotations,omitempty"`
655+
656+
// Labels to add to HTTPRoute resources
657+
// +optional
658+
Labels map[string]string `json:"labels,omitempty"`
659+
}
660+
661+
// GatewayParentReference identifies a parent Gateway resource to attach HTTPRoutes to
662+
type GatewayParentReference struct {
663+
// Name of the Gateway resource
664+
Name string `json:"name"`
665+
666+
// Namespace of the Gateway resource.
667+
// If not specified, defaults to the HTTPRoute's namespace.
668+
// +optional
669+
Namespace *string `json:"namespace,omitempty"`
670+
671+
// SectionName refers to a specific listener on the Gateway.
672+
// For example, "https" or "http".
673+
// +optional
674+
SectionName *string `json:"sectionName,omitempty"`
675+
}
676+
629677
type SolrUpdateStrategy struct {
630678
// Method defines the way in which SolrClouds should be updated when the podSpec changes.
631679
// +optional
@@ -1297,6 +1345,16 @@ func (sc *SolrCloud) CommonIngressName() string {
12971345
return fmt.Sprintf("%s-solrcloud-common", sc.GetName())
12981346
}
12991347

1348+
// CommonHTTPRouteName returns the name of the common HTTPRoute for the cloud
1349+
func (sc *SolrCloud) CommonHTTPRouteName() string {
1350+
return fmt.Sprintf("%s-solrcloud-common", sc.GetName())
1351+
}
1352+
1353+
// NodeHTTPRouteName returns the name of the HTTPRoute for a specific node
1354+
func (sc *SolrCloud) NodeHTTPRouteName(nodeName string) string {
1355+
return nodeName
1356+
}
1357+
13001358
// ProvidedZookeeperName returns the provided zk cluster
13011359
func (sc *SolrCloud) ProvidedZookeeperName() string {
13021360
return fmt.Sprintf("%s-solrcloud-zookeeper", sc.GetName())
@@ -1340,8 +1398,8 @@ func (sc *SolrCloud) UsesIndividualNodeServices() bool {
13401398
}
13411399

13421400
func (extOpts *ExternalAddressability) UsesIndividualNodeServices() bool {
1343-
// LoadBalancer and Ingress will not work with headless services if each pod needs to be exposed externally.
1344-
return extOpts != nil && !extOpts.HideNodes && (extOpts.Method == Ingress || extOpts.Method == LoadBalancer)
1401+
// LoadBalancer, Ingress, and Gateway will not work with headless services if each pod needs to be exposed externally.
1402+
return extOpts != nil && !extOpts.HideNodes && (extOpts.Method == Ingress || extOpts.Method == LoadBalancer || extOpts.Method == Gateway)
13451403
}
13461404

13471405
func (sc *SolrCloud) CommonExternalPrefix() string {
@@ -1435,11 +1493,13 @@ func (sc *SolrCloud) ExternalNodeUrl(nodeName string, domainName string, withPor
14351493
url = fmt.Sprintf("%s.%s", sc.NodeIngressPrefix(nodeName), domainName)
14361494
} else if sc.Spec.SolrAddressability.External.Method == ExternalDNS {
14371495
url = fmt.Sprintf("%s.%s", nodeName, sc.ExternalDnsDomain(domainName))
1496+
} else if sc.Spec.SolrAddressability.External.Method == Gateway {
1497+
url = fmt.Sprintf("%s.%s", sc.NodeIngressPrefix(nodeName), domainName)
14381498
}
14391499
// TODO: Add LoadBalancer stuff here
14401500

1441-
if withPort && sc.Spec.SolrAddressability.External.Method != Ingress {
1442-
// Ingress does not require a port, since the port is whatever the ingress is listening on (80 and 443)
1501+
if withPort && sc.Spec.SolrAddressability.External.Method != Ingress && sc.Spec.SolrAddressability.External.Method != Gateway {
1502+
// Ingress and Gateway do not require a port, since the port is whatever the ingress/gateway is listening on (80 and 443)
14431503
url += sc.NodePortSuffix(true)
14441504
}
14451505
return url
@@ -1450,11 +1510,13 @@ func (sc *SolrCloud) ExternalCommonUrl(domainName string, withPort bool) (url st
14501510
url = fmt.Sprintf("%s.%s", sc.CommonExternalPrefix(), domainName)
14511511
} else if sc.Spec.SolrAddressability.External.Method == ExternalDNS {
14521512
url = fmt.Sprintf("%s.%s", sc.CommonServiceName(), sc.ExternalDnsDomain(domainName))
1513+
} else if sc.Spec.SolrAddressability.External.Method == Gateway {
1514+
url = fmt.Sprintf("%s.%s", sc.CommonExternalPrefix(), domainName)
14531515
}
14541516
// TODO: Add LoadBalancer stuff here
14551517

1456-
if withPort && sc.Spec.SolrAddressability.External.Method != Ingress {
1457-
// Ingress does not require a port, since the port is whatever the ingress is listening on (80 and 443)
1518+
if withPort && sc.Spec.SolrAddressability.External.Method != Ingress && sc.Spec.SolrAddressability.External.Method != Gateway {
1519+
// Ingress and Gateway do not require a port, since the port is whatever the ingress/gateway is listening on (80 and 443)
14581520
url += sc.CommonPortSuffix(true)
14591521
}
14601522
return url

api/v1beta1/zz_generated.deepcopy.go

Lines changed: 66 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

config/crd/bases/solr.apache.org_solrclouds.yaml

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9889,6 +9889,56 @@ spec:
98899889
For the LoadBalancer method, this field is optional and will only be used when useExternalAddress=true.
98909890
If used with the LoadBalancer method, you will need DNS routing to the LoadBalancer IP address through the url template given above.
98919891
type: string
9892+
gateway:
9893+
description: |-
9894+
Gateway defines settings for Kubernetes Gateway API routing.
9895+
9896+
This option is only available when Method=Gateway.
9897+
The referenced Gateway must already exist and be managed by your platform team.
9898+
The Solr Operator only manages the HTTPRoute resources.
9899+
properties:
9900+
annotations:
9901+
additionalProperties:
9902+
type: string
9903+
description: Annotations to add to HTTPRoute resources
9904+
type: object
9905+
labels:
9906+
additionalProperties:
9907+
type: string
9908+
description: Labels to add to HTTPRoute resources
9909+
type: object
9910+
parentRefs:
9911+
description: |-
9912+
ParentRefs specifies the Gateway(s) to attach HTTPRoutes to.
9913+
This is required when using method=Gateway.
9914+
9915+
The referenced Gateway must already exist and be managed by your platform team.
9916+
The Solr Operator only manages the HTTPRoute resources.
9917+
items:
9918+
description: GatewayParentReference identifies a parent
9919+
Gateway resource to attach HTTPRoutes to
9920+
properties:
9921+
name:
9922+
description: Name of the Gateway resource
9923+
type: string
9924+
namespace:
9925+
description: |-
9926+
Namespace of the Gateway resource.
9927+
If not specified, defaults to the HTTPRoute's namespace.
9928+
type: string
9929+
sectionName:
9930+
description: |-
9931+
SectionName refers to a specific listener on the Gateway.
9932+
For example, "https" or "http".
9933+
type: string
9934+
required:
9935+
- name
9936+
type: object
9937+
minItems: 1
9938+
type: array
9939+
required:
9940+
- parentRefs
9941+
type: object
98929942
hideCommon:
98939943
description: |-
98949944
Do not expose the common Solr service externally. This affects a single service.
@@ -9928,6 +9978,7 @@ spec:
99289978
enum:
99299979
- Ingress
99309980
- ExternalDNS
9981+
- Gateway
99319982
type: string
99329983
nodePortOverride:
99339984
description: |-

config/rbac/role.yaml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,24 @@ rules:
8282
- statefulsets/status
8383
verbs:
8484
- get
85+
- apiGroups:
86+
- gateway.networking.k8s.io
87+
resources:
88+
- httproutes
89+
verbs:
90+
- create
91+
- delete
92+
- get
93+
- list
94+
- patch
95+
- update
96+
- watch
97+
- apiGroups:
98+
- gateway.networking.k8s.io
99+
resources:
100+
- httproutes/status
101+
verbs:
102+
- get
85103
- apiGroups:
86104
- networking.k8s.io
87105
resources:

0 commit comments

Comments
 (0)