Skip to content

Commit db4142d

Browse files
authored
[1.18] Backport configure NodePort with GatewayParams (#10563)
1 parent cdaa04d commit db4142d

File tree

13 files changed

+206
-2
lines changed

13 files changed

+206
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2+
changelog:
3+
- type: FIX
4+
issueLink: https://github.com/solo-io/solo-projects/issues/7504
5+
resolvesIssue: true
6+
description: >
7+
Add a new Ports field to the `GatewayParameters` `Kube.Service` Spec in order to allow admin users
8+
to configure additional information about the ports that the Gateway should listen on. This is useful
9+
if the user wants to specify a static `NodePort`

docs/content/reference/api/github.com/solo-io/gloo/projects/gateway2/api/v1alpha1/gateway_parameters.md

+41
Original file line numberDiff line numberDiff line change
@@ -7678,6 +7678,13 @@ Resource Types:
76787678
<br/>
76797679
</td>
76807680
<td>false</td>
7681+
</tr><tr>
7682+
<td><b><a href="#gatewayparametersspeckubeserviceportsindex">ports</a></b></td>
7683+
<td>[]object</td>
7684+
<td>
7685+
<br/>
7686+
</td>
7687+
<td>false</td>
76817688
</tr><tr>
76827689
<td><b>type</b></td>
76837690
<td>string</td>
@@ -7689,6 +7696,40 @@ Resource Types:
76897696
</table>
76907697

76917698

7699+
### GatewayParameters.spec.kube.service.ports[index]
7700+
<sup><sup>[↩ Parent](#gatewayparametersspeckubeservice)</sup></sup>
7701+
7702+
7703+
7704+
7705+
7706+
<table>
7707+
<thead>
7708+
<tr>
7709+
<th>Name</th>
7710+
<th>Type</th>
7711+
<th>Description</th>
7712+
<th>Required</th>
7713+
</tr>
7714+
</thead>
7715+
<tbody><tr>
7716+
<td><b>port</b></td>
7717+
<td>integer</td>
7718+
<td>
7719+
<br/>
7720+
</td>
7721+
<td>true</td>
7722+
</tr><tr>
7723+
<td><b>nodePort</b></td>
7724+
<td>integer</td>
7725+
<td>
7726+
<br/>
7727+
</td>
7728+
<td>false</td>
7729+
</tr></tbody>
7730+
</table>
7731+
7732+
76927733
### GatewayParameters.spec.kube.serviceAccount
76937734
<sup><sup>[↩ Parent](#gatewayparametersspeckube)</sup></sup>
76947735

install/helm/gloo/crds/gateway.gloo.solo.io_gatewayparameters.yaml

+12
Original file line numberDiff line numberDiff line change
@@ -2085,6 +2085,18 @@ spec:
20852085
additionalProperties:
20862086
type: string
20872087
type: object
2088+
ports:
2089+
items:
2090+
properties:
2091+
nodePort:
2092+
type: integer
2093+
port:
2094+
type: integer
2095+
required:
2096+
- port
2097+
type: object
2098+
maxItems: 8
2099+
type: array
20882100
type:
20892101
type: string
20902102
type: object

install/helm/gloo/templates/43-gatewayparameters.yaml

+4
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,10 @@ spec:
4242
extraAnnotations:
4343
{{- toYaml . | nindent 8 }}
4444
{{- end }}
45+
{{- with ($gg.service).ports }}
46+
ports:
47+
{{- toYaml . | nindent 8 }}
48+
{{- end }}
4549
{{- if $gg.serviceAccount }}
4650
serviceAccount:
4751
{{- with $gg.serviceAccount.extraLabels }}

projects/gateway2/api/v1alpha1/gateway_parameters_types.go

+14
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,20 @@ type GatewayParametersSpec struct {
4545
SelfManaged *SelfManagedGateway `json:"selfManaged,omitempty"`
4646
}
4747

48+
func (in *GatewayParametersSpec) GetKube() *KubernetesProxyConfig {
49+
if in == nil {
50+
return nil
51+
}
52+
return in.Kube
53+
}
54+
55+
func (in *GatewayParametersSpec) GetSelfManaged() *SelfManagedGateway {
56+
if in == nil {
57+
return nil
58+
}
59+
return in.SelfManaged
60+
}
61+
4862
// The current conditions of the GatewayParameters. This is not currently implemented.
4963
type GatewayParametersStatus struct {
5064
}

projects/gateway2/api/v1alpha1/kube_types.go

+40
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,12 @@ type Service struct {
9797
// +kubebuilder:validation:Optional
9898
ExtraAnnotations map[string]string `json:"extraAnnotations,omitempty"`
9999

100+
// Additional configuration for the service ports.
101+
// The actual port numbers are specified in the Gateway resource.
102+
//
103+
// +optional
104+
// +kubebuilder:validation:MaxItems=8
105+
Ports []*Port `json:"ports"`
100106
// External Traffic Policy on the Service object.
101107
//
102108
// +kubebuilder:validation:Optional
@@ -131,13 +137,47 @@ func (in *Service) GetExtraAnnotations() map[string]string {
131137
return in.ExtraAnnotations
132138
}
133139

140+
func (in *Service) GetPorts() []*Port {
141+
if in == nil {
142+
return nil
143+
}
144+
return in.Ports
145+
}
146+
134147
func (in *Service) GetExternalTrafficPolicy() *corev1.ServiceExternalTrafficPolicy {
135148
if in == nil {
136149
return nil
137150
}
138151
return in.ExternalTrafficPolicy
139152
}
140153

154+
type Port struct {
155+
// The port number to match on the Gateway
156+
//
157+
// +kubebuilder:validation:Required
158+
Port uint16 `json:"port"`
159+
160+
// The NodePort to be used for the service. If not specified, a random port
161+
// will be assigned by the Kubernetes API server.
162+
//
163+
// +kubebuilder:validation:Optional
164+
NodePort *uint16 `json:"nodePort,omitempty"`
165+
}
166+
167+
func (in *Port) GetPort() uint16 {
168+
if in == nil {
169+
return 0
170+
}
171+
return in.Port
172+
}
173+
174+
func (in *Port) GetNodePort() *uint16 {
175+
if in == nil {
176+
return nil
177+
}
178+
return in.NodePort
179+
}
180+
141181
type ServiceAccount struct {
142182
// Additional labels to add to the ServiceAccount object metadata.
143183
//

projects/gateway2/api/v1alpha1/zz_generated.deepcopy.go

+31
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

projects/gateway2/deployer/deployer.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -262,7 +262,7 @@ func (d *Deployer) getValues(gw *api.Gateway, gwParam *v1alpha1.GatewayParameter
262262
Name: &gw.Name,
263263
GatewayName: &gw.Name,
264264
GatewayNamespace: &gw.Namespace,
265-
Ports: getPortsValues(gw),
265+
Ports: getPortsValues(gw, gwParam),
266266
Xds: &helmXds{
267267
// The xds host/port MUST map to the Service definition for the Control Plane
268268
// This is the socket address that the Proxy will connect to on startup, to receive xds updates

projects/gateway2/deployer/deployer_test.go

+37
Original file line numberDiff line numberDiff line change
@@ -1255,9 +1255,46 @@ var _ = Describe("Deployer", func() {
12551255
port := svc.Spec.Ports[0]
12561256
Expect(port.Port).To(Equal(int32(80)))
12571257
Expect(port.TargetPort.IntVal).To(Equal(int32(8080)))
1258+
Expect(port.NodePort).To(Equal(int32(0)))
12581259
return nil
12591260
},
12601261
}),
1262+
Entry("static NodePort", &input{
1263+
dInputs: defaultDeployerInputs(),
1264+
gw: defaultGatewayWithGatewayParams(gwpOverrideName),
1265+
defaultGwp: defaultGatewayParams(),
1266+
overrideGwp: &gw2_v1alpha1.GatewayParameters{
1267+
ObjectMeta: metav1.ObjectMeta{
1268+
Name: gwpOverrideName,
1269+
Namespace: defaultNamespace,
1270+
},
1271+
Spec: gw2_v1alpha1.GatewayParametersSpec{
1272+
Kube: &gw2_v1alpha1.KubernetesProxyConfig{
1273+
Service: &gw2_v1alpha1.Service{
1274+
Type: ptr.To(corev1.ServiceTypeNodePort),
1275+
Ports: []*gw2_v1alpha1.Port{
1276+
{
1277+
Port: 80,
1278+
NodePort: ptr.To(uint16(30000)),
1279+
},
1280+
},
1281+
},
1282+
},
1283+
},
1284+
},
1285+
}, &expectedOutput{
1286+
validationFunc: func(objs clientObjects, inp *input) error {
1287+
svc := objs.findService(defaultNamespace, defaultServiceName)
1288+
Expect(svc).NotTo(BeNil())
1289+
1290+
port := svc.Spec.Ports[0]
1291+
Expect(port.Port).To(Equal(int32(80)))
1292+
Expect(port.TargetPort.IntVal).To(Equal(int32(8080)))
1293+
Expect(port.NodePort).To(Equal(int32(30000)))
1294+
return nil
1295+
},
1296+
}),
1297+
12611298
Entry("duplicate ports", &input{
12621299
dInputs: defaultDeployerInputs(),
12631300
gw: &api.Gateway{

projects/gateway2/deployer/merge.go

+1
Original file line numberDiff line numberDiff line change
@@ -442,6 +442,7 @@ func deepMergeService(dst, src *v1alpha1.Service) *v1alpha1.Service {
442442

443443
dst.ExtraLabels = deepMergeMaps(dst.GetExtraLabels(), src.GetExtraLabels())
444444
dst.ExtraAnnotations = deepMergeMaps(dst.GetExtraAnnotations(), src.GetExtraAnnotations())
445+
dst.Ports = deepMergeSlices(dst.GetPorts(), src.GetPorts())
445446

446447
if src.GetExternalTrafficPolicy() != nil {
447448
dst.ExternalTrafficPolicy = src.GetExternalTrafficPolicy()

projects/gateway2/deployer/values.go

+1
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,7 @@ type helmPort struct {
7474
Protocol *string `json:"protocol,omitempty"`
7575
Name *string `json:"name,omitempty"`
7676
TargetPort *uint16 `json:"targetPort,omitempty"`
77+
NodePort *uint16 `json:"nodePort,omitempty"`
7778
}
7879

7980
type helmImage struct {

projects/gateway2/deployer/values_helpers.go

+14-1
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import (
1010
"github.com/solo-io/gloo/projects/gateway2/api/v1alpha1"
1111
"github.com/solo-io/gloo/projects/gateway2/ports"
1212
"golang.org/x/exp/slices"
13+
corev1 "k8s.io/api/core/v1"
1314
"k8s.io/utils/ptr"
1415
api "sigs.k8s.io/gateway-api/apis/v1"
1516
)
@@ -24,7 +25,7 @@ var ComponentLogLevelEmptyError = func(key string, value string) error {
2425
// Extract the listener ports from a Gateway. These will be used to populate:
2526
// 1. the ports exposed on the envoy container
2627
// 2. the ports exposed on the proxy service
27-
func getPortsValues(gw *api.Gateway) []helmPort {
28+
func getPortsValues(gw *api.Gateway, gwp *v1alpha1.GatewayParameters) []helmPort {
2829
gwPorts := []helmPort{}
2930
for _, l := range gw.Spec.Listeners {
3031
listenerPort := uint16(l.Port)
@@ -38,11 +39,23 @@ func getPortsValues(gw *api.Gateway) []helmPort {
3839
portName := string(l.Name)
3940
protocol := "TCP"
4041

42+
// Search for static NodePort set from the GatewayParameters spec
43+
// If not found the default value of `nil` will not render anything.
44+
var nodePort *uint16 = nil
45+
if gwp.Spec.GetKube().GetService().GetType() != nil && *(gwp.Spec.GetKube().GetService().GetType()) == corev1.ServiceTypeNodePort {
46+
if idx := slices.IndexFunc(gwp.Spec.GetKube().GetService().GetPorts(), func(p *v1alpha1.Port) bool {
47+
return p.GetPort() == uint16(listenerPort)
48+
}); idx != -1 {
49+
nodePort = ptr.To(uint16(*gwp.Spec.GetKube().GetService().GetPorts()[idx].GetNodePort()))
50+
}
51+
}
52+
4153
gwPorts = append(gwPorts, helmPort{
4254
Port: &listenerPort,
4355
TargetPort: &targetPort,
4456
Name: &portName,
4557
Protocol: &protocol,
58+
NodePort: nodePort,
4659
})
4760
}
4861
return gwPorts

projects/gateway2/helm/gloo-gateway/templates/gateway/proxy-deployment.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -392,6 +392,7 @@ spec:
392392
protocol: {{ $p.protocol }}
393393
targetPort: {{ $p.targetPort }}
394394
port: {{ $p.port }}
395+
nodePort: {{ $p.nodePort }}
395396
{{- end }}
396397
selector:
397398
{{- include "gloo-gateway.gateway.selectorLabels" . | nindent 4 }}

0 commit comments

Comments
 (0)