Skip to content

Commit 9149f71

Browse files
committed
CP/DP Split: Support configuring NodePorts
Problem: Now that the control plane provisions the NGINX Service, users can't set specific NodePorts values. Solution: Allow users to specify NodePorts in the helm chart (globally) and in the NginxProxy resource.
1 parent f9cad70 commit 9149f71

File tree

16 files changed

+611
-49
lines changed

16 files changed

+611
-49
lines changed

apis/v1alpha2/nginxproxy_types.go

+22
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,13 @@ type ServiceSpec struct {
533533
//
534534
// +optional
535535
LoadBalancerSourceRanges []string `json:"loadBalancerSourceRanges,omitempty"`
536+
537+
// NodePorts are the list of NodePorts to expose on the NGINX data plane service.
538+
// Each NodePort MUST map to a Gateway listener port, otherwise it will be ignored.
539+
// The default NodePort range enforced by Kubernetes is 30000-32767.
540+
//
541+
// +optional
542+
NodePorts []NodePort `json:"nodePorts,omitempty"`
536543
}
537544

538545
// ServiceType describes ingress method for the Service.
@@ -569,3 +576,18 @@ const (
569576
// (dropping the traffic if there are no local endpoints).
570577
ExternalTrafficPolicyLocal ExternalTrafficPolicy = ExternalTrafficPolicy(corev1.ServiceExternalTrafficPolicyLocal)
571578
)
579+
580+
// NodePort creates a port on each node on which the NGINX data plane service is exposed. The NodePort MUST
581+
// map to a Gateway listener port, otherwise it will be ignored. If not specified, Kubernetes allocates a NodePort
582+
// automatically if required. The default NodePort range enforced by Kubernetes is 30000-32767.
583+
type NodePort struct {
584+
// Port is the NodePort to expose.
585+
// kubebuilder:validation:Minimum=1
586+
// kubebuilder:validation:Maximum=65535
587+
Port int32 `json:"port"`
588+
589+
// ListenerPort is the Gateway listener port that this NodePort maps to.
590+
// kubebuilder:validation:Minimum=1
591+
// kubebuilder:validation:Maximum=65535
592+
ListenerPort int32 `json:"listenerPort"`
593+
}

apis/v1alpha2/zz_generated.deepcopy.go

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

charts/nginx-gateway-fabric/README.md

+10-5
Original file line numberDiff line numberDiff line change
@@ -258,19 +258,24 @@ The following table lists the configurable parameters of the NGINX Gateway Fabri
258258
| `certGenerator.overwrite` | Overwrite existing TLS Secrets on startup. | bool | `false` |
259259
| `certGenerator.serverTLSSecretName` | The name of the Secret containing TLS CA, certificate, and key for the NGINX Gateway Fabric control plane to securely communicate with the NGINX Agent. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `"server-tls"` |
260260
| `clusterDomain` | The DNS cluster domain of your Kubernetes cluster. | string | `"cluster.local"` |
261-
| `nginx` | The nginx section contains the configuration for all NGINX data plane deployments installed by the NGINX Gateway Fabric control plane. | object | `{"config":{},"container":{},"debug":false,"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric/nginx","tag":"edge"},"imagePullSecret":"","imagePullSecrets":[],"kind":"deployment","plus":false,"pod":{},"replicas":1,"service":{"externalTrafficPolicy":"Local","type":"LoadBalancer"},"usage":{"caSecretName":"","clientSSLSecretName":"","endpoint":"","resolver":"","secretName":"nplus-license","skipVerify":false}}` |
262-
| `nginx.config` | The configuration for the data plane that is contained in the NginxProxy resource. | object | `{}` |
263-
| `nginx.container` | The container configuration for the NGINX container. | object | `{}` |
261+
| `nginx` | The nginx section contains the configuration for all NGINX data plane deployments installed by the NGINX Gateway Fabric control plane. | object | `{"config":{},"container":{},"debug":false,"image":{"pullPolicy":"Always","repository":"ghcr.io/nginx/nginx-gateway-fabric/nginx","tag":"edge"},"imagePullSecret":"","imagePullSecrets":[],"kind":"deployment","plus":false,"pod":{},"replicas":1,"service":{"annotations":{},"externalTrafficPolicy":"Local","loadBalancerClass":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"nodePorts":[],"type":"LoadBalancer"},"usage":{"caSecretName":"","clientSSLSecretName":"","endpoint":"","resolver":"","secretName":"nplus-license","skipVerify":false}}` |
262+
| `nginx.config` | The configuration for the data plane that is contained in the NginxProxy resource. This is applied globally to all Gateways. | object | `{}` |
263+
| `nginx.container` | The container configuration for the NGINX container. This is applied globally to all Gateways. | object | `{}` |
264264
| `nginx.debug` | Enable debugging for NGINX. Uses the nginx-debug binary. The NGINX error log level should be set to debug in the NginxProxy resource. | bool | `false` |
265265
| `nginx.image.repository` | The NGINX image to use. | string | `"ghcr.io/nginx/nginx-gateway-fabric/nginx"` |
266266
| `nginx.imagePullSecret` | The name of the secret containing docker registry credentials. Secret must exist in the same namespace as the helm release. The control plane will copy this secret into any namespace where NGINX is deployed. | string | `""` |
267267
| `nginx.imagePullSecrets` | A list of secret names containing docker registry credentials. Secrets must exist in the same namespace as the helm release. The control plane will copy these secrets into any namespace where NGINX is deployed. | list | `[]` |
268268
| `nginx.kind` | The kind of NGINX deployment. | string | `"deployment"` |
269269
| `nginx.plus` | Is NGINX Plus image being used. | bool | `false` |
270-
| `nginx.pod` | The pod configuration for the NGINX data plane pod. | object | `{}` |
270+
| `nginx.pod` | The pod configuration for the NGINX data plane pod. This is applied globally to all Gateways. | object | `{}` |
271271
| `nginx.replicas` | The number of replicas of the NGINX Deployment. | int | `1` |
272-
| `nginx.service` | The service configuration for the NGINX data plane. | object | `{"externalTrafficPolicy":"Local","type":"LoadBalancer"}` |
272+
| `nginx.service` | The service configuration for the NGINX data plane. This is applied globally to all Gateways. | object | `{"annotations":{},"externalTrafficPolicy":"Local","loadBalancerClass":"","loadBalancerIP":"","loadBalancerSourceRanges":[],"nodePorts":[],"type":"LoadBalancer"}` |
273+
| `nginx.service.annotations` | The annotations of the NGINX data plane service. | object | `{}` |
273274
| `nginx.service.externalTrafficPolicy` | The externalTrafficPolicy of the service. The value Local preserves the client source IP. | string | `"Local"` |
275+
| `nginx.service.loadBalancerClass` | LoadBalancerClass is the class of the load balancer implementation this Service belongs to. Requires nginx.service.type set to LoadBalancer. | string | `""` |
276+
| `nginx.service.loadBalancerIP` | The static IP address for the load balancer. Requires nginx.service.type set to LoadBalancer. | string | `""` |
277+
| `nginx.service.loadBalancerSourceRanges` | The IP ranges (CIDR) that are allowed to access the load balancer. Requires nginx.service.type set to LoadBalancer. | list | `[]` |
278+
| `nginx.service.nodePorts` | A list of NodePorts to expose on the NGINX data plane service. Each NodePort MUST map to a Gateway listener port, otherwise it will be ignored. The default NodePort range enforced by Kubernetes is 30000-32767. | list | `[]` |
274279
| `nginx.service.type` | The type of service to create for the NGINX data plane. | string | `"LoadBalancer"` |
275280
| `nginx.usage.caSecretName` | The name of the Secret containing the NGINX Instance Manager CA certificate. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `""` |
276281
| `nginx.usage.clientSSLSecretName` | The name of the Secret containing the client certificate and key for authenticating with NGINX Instance Manager. Must exist in the same namespace that the NGINX Gateway Fabric control plane is running in (default namespace: nginx-gateway). | string | `""` |

charts/nginx-gateway-fabric/templates/_helpers.tpl

+13
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,16 @@ Expand leader election lock name.
9191
{{- printf "%s-%s" (include "nginx-gateway.fullname" .) "leader-election" -}}
9292
{{- end -}}
9393
{{- end -}}
94+
95+
{{/*
96+
Filters out empty fields from a struct.
97+
*/}}
98+
{{- define "filterEmptyFields" -}}
99+
{{- $result := dict }}
100+
{{- range $key, $value := . }}
101+
{{- if and (not (empty $value)) (not (and (kindIs "slice" $value) (eq (len $value) 0))) }}
102+
{{- $result = merge $result (dict $key $value) }}
103+
{{- end }}
104+
{{- end }}
105+
{{- $result | toYaml }}
106+
{{- end }}

charts/nginx-gateway-fabric/templates/nginxproxy.yaml

+3-1
Original file line numberDiff line numberDiff line change
@@ -29,5 +29,7 @@ spec:
2929
{{- end }}
3030
{{- if .Values.nginx.service }}
3131
service:
32-
{{- toYaml .Values.nginx.service | nindent 6 }}
32+
{{- with .Values.nginx.service }}
33+
{{- include "filterEmptyFields" . | nindent 6 }}
34+
{{- end }}
3335
{{- end }}

charts/nginx-gateway-fabric/values.schema.json

+57-4
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@
5353
"description": "The nginx section contains the configuration for all NGINX data plane deployments\ninstalled by the NGINX Gateway Fabric control plane.",
5454
"properties": {
5555
"config": {
56-
"description": "The configuration for the data plane that is contained in the NginxProxy resource.",
56+
"description": "The configuration for the data plane that is contained in the NginxProxy resource. This is applied globally to all Gateways.",
5757
"properties": {
5858
"disableHTTP2": {
5959
"description": "DisableHTTP2 defines if http2 should be disabled for all servers.",
@@ -266,7 +266,7 @@
266266
"type": "object"
267267
},
268268
"container": {
269-
"description": "The container configuration for the NGINX container.",
269+
"description": "The container configuration for the NGINX container. This is applied globally to all Gateways.",
270270
"required": [],
271271
"title": "container",
272272
"type": "object"
@@ -341,7 +341,7 @@
341341
"type": "boolean"
342342
},
343343
"pod": {
344-
"description": "The pod configuration for the NGINX data plane pod.",
344+
"description": "The pod configuration for the NGINX data plane pod. This is applied globally to all Gateways.",
345345
"required": [],
346346
"title": "pod",
347347
"type": "object"
@@ -354,8 +354,14 @@
354354
"type": "integer"
355355
},
356356
"service": {
357-
"description": "The service configuration for the NGINX data plane.",
357+
"description": "The service configuration for the NGINX data plane. This is applied globally to all Gateways.",
358358
"properties": {
359+
"annotations": {
360+
"description": "The annotations of the NGINX data plane service.",
361+
"required": [],
362+
"title": "annotations",
363+
"type": "object"
364+
},
359365
"externalTrafficPolicy": {
360366
"default": "Local",
361367
"description": "The externalTrafficPolicy of the service. The value Local preserves the client source IP.",
@@ -366,6 +372,53 @@
366372
"required": [],
367373
"title": "externalTrafficPolicy"
368374
},
375+
"loadBalancerClass": {
376+
"default": "",
377+
"description": "LoadBalancerClass is the class of the load balancer implementation this Service belongs to.\nRequires nginx.service.type set to LoadBalancer.",
378+
"required": [],
379+
"title": "loadBalancerClass",
380+
"type": "string"
381+
},
382+
"loadBalancerIP": {
383+
"default": "",
384+
"description": "The static IP address for the load balancer. Requires nginx.service.type set to LoadBalancer.",
385+
"required": [],
386+
"title": "loadBalancerIP",
387+
"type": "string"
388+
},
389+
"loadBalancerSourceRanges": {
390+
"description": "The IP ranges (CIDR) that are allowed to access the load balancer. Requires nginx.service.type set to LoadBalancer.",
391+
"items": {
392+
"required": []
393+
},
394+
"required": [],
395+
"title": "loadBalancerSourceRanges",
396+
"type": "array"
397+
},
398+
"nodePorts": {
399+
"description": "A list of NodePorts to expose on the NGINX data plane service. Each NodePort MUST map to a Gateway listener port,\notherwise it will be ignored. The default NodePort range enforced by Kubernetes is 30000-32767.",
400+
"items": {
401+
"properties": {
402+
"listenerPort": {
403+
"maximum": 65535,
404+
"minimum": 1,
405+
"required": [],
406+
"type": "integer"
407+
},
408+
"port": {
409+
"maximum": 65535,
410+
"minimum": 1,
411+
"required": [],
412+
"type": "integer"
413+
}
414+
},
415+
"required": [],
416+
"type": "object"
417+
},
418+
"required": [],
419+
"title": "nodePorts",
420+
"type": "array"
421+
},
369422
"type": {
370423
"default": "LoadBalancer",
371424
"description": "The type of service to create for the NGINX data plane.",

charts/nginx-gateway-fabric/values.yaml

+30-8
Original file line numberDiff line numberDiff line change
@@ -367,10 +367,10 @@ nginx:
367367
# value:
368368
# type: string
369369
# @schema
370-
# -- The configuration for the data plane that is contained in the NginxProxy resource.
370+
# -- The configuration for the data plane that is contained in the NginxProxy resource. This is applied globally to all Gateways.
371371
config: {}
372372

373-
# -- The pod configuration for the NGINX data plane pod.
373+
# -- The pod configuration for the NGINX data plane pod. This is applied globally to all Gateways.
374374
pod: {}
375375
# -- The termination grace period of the NGINX data plane pod.
376376
# terminationGracePeriodSeconds: 30
@@ -391,7 +391,7 @@ nginx:
391391
# nginx.container.extraVolumeMounts mount additional volumes to the container.
392392
# extraVolumes: []
393393

394-
# -- The container configuration for the NGINX container.
394+
# -- The container configuration for the NGINX container. This is applied globally to all Gateways.
395395
container: {}
396396
# -- The resource requirements of the NGINX container.
397397
# resources: {}
@@ -402,7 +402,7 @@ nginx:
402402
# -- extraVolumeMounts are the additional volume mounts for the NGINX container.
403403
# extraVolumeMounts: []
404404

405-
# -- The service configuration for the NGINX data plane.
405+
# -- The service configuration for the NGINX data plane. This is applied globally to all Gateways.
406406
service:
407407
# @schema
408408
# enum:
@@ -422,17 +422,39 @@ nginx:
422422
externalTrafficPolicy: Local
423423

424424
# -- The annotations of the NGINX data plane service.
425-
# annotations: {}
425+
annotations: {}
426426

427427
# -- The static IP address for the load balancer. Requires nginx.service.type set to LoadBalancer.
428-
# loadBalancerIP: ""
428+
loadBalancerIP: ""
429429

430430
# -- LoadBalancerClass is the class of the load balancer implementation this Service belongs to.
431431
# Requires nginx.service.type set to LoadBalancer.
432-
# loadBalancerClass: ""
432+
loadBalancerClass: ""
433433

434434
# -- The IP ranges (CIDR) that are allowed to access the load balancer. Requires nginx.service.type set to LoadBalancer.
435-
# loadBalancerSourceRanges: []
435+
loadBalancerSourceRanges: []
436+
437+
# @schema
438+
# type: array
439+
# items:
440+
# type: object
441+
# properties:
442+
# port:
443+
# type: integer
444+
# required: true
445+
# minimum: 1
446+
# maximum: 65535
447+
# listenerPort:
448+
# type: integer
449+
# required: true
450+
# minimum: 1
451+
# maximum: 65535
452+
# @schema
453+
# -- A list of NodePorts to expose on the NGINX data plane service. Each NodePort MUST map to a Gateway listener port,
454+
# otherwise it will be ignored. The default NodePort range enforced by Kubernetes is 30000-32767.
455+
nodePorts: []
456+
# - port: 30025
457+
# listenerPort: 80
436458

437459
# -- Enable debugging for NGINX. Uses the nginx-debug binary. The NGINX error log level should be set to debug in the NginxProxy resource.
438460
debug: false

config/crd/bases/gateway.nginx.org_nginxproxies.yaml

+30
Original file line numberDiff line numberDiff line change
@@ -3498,6 +3498,36 @@ spec:
34983498
items:
34993499
type: string
35003500
type: array
3501+
nodePorts:
3502+
description: |-
3503+
NodePorts are the list of NodePorts to expose on the NGINX data plane service.
3504+
Each NodePort MUST map to a Gateway listener port, otherwise it will be ignored.
3505+
The default NodePort range enforced by Kubernetes is 30000-32767.
3506+
items:
3507+
description: |-
3508+
NodePort creates a port on each node on which the NGINX data plane service is exposed. The NodePort MUST
3509+
map to a Gateway listener port, otherwise it will be ignored. If not specified, Kubernetes allocates a NodePort
3510+
automatically if required. The default NodePort range enforced by Kubernetes is 30000-32767.
3511+
properties:
3512+
listenerPort:
3513+
description: |-
3514+
ListenerPort is the Gateway listener port that this NodePort maps to.
3515+
kubebuilder:validation:Minimum=1
3516+
kubebuilder:validation:Maximum=65535
3517+
format: int32
3518+
type: integer
3519+
port:
3520+
description: |-
3521+
Port is the NodePort to expose.
3522+
kubebuilder:validation:Minimum=1
3523+
kubebuilder:validation:Maximum=65535
3524+
format: int32
3525+
type: integer
3526+
required:
3527+
- listenerPort
3528+
- port
3529+
type: object
3530+
type: array
35013531
type:
35023532
default: LoadBalancer
35033533
description: ServiceType describes ingress method for the

0 commit comments

Comments
 (0)