Skip to content

Commit 2079725

Browse files
authored
Support custom listener ports (#745)
Problem: NKG only supported listener ports 80 and 443. This limitation prevents the conformance tests from running because the conformance tests create a base Gateway that listens on port 8080. Solution: Allow users to specify any port between 1-65535.
1 parent f64d045 commit 2079725

22 files changed

+793
-347
lines changed

conformance/README.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,14 @@ List available commands:
1313
```bash
1414
$ make
1515

16-
build-test-image Build conformance test image
16+
build-test-runner-image Build conformance test runner image
1717
create-kind-cluster Create a kind cluster
1818
delete-kind-cluster Delete kind cluster
1919
help Display this help
20-
install-nkg Install NKG on configured kind cluster
20+
install-nkg Install NKG with provisioner on configured kind cluster
21+
prepare-nkg Build and load NKG container on configured kind cluster
2122
run-conformance-tests Run conformance tests
22-
uninstall-nkg Uninstall NKG from configured kind cluster
23+
uninstall-nkg Uninstall NKG on configured kind cluster
2324
update-test-kind-config Update kind config
2425
```
2526
### Step 1 - Create a kind Cluster

deploy/manifests/service/loadbalancer-aws-nlb.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,14 @@ metadata:
77
service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
88
spec:
99
type: LoadBalancer
10-
ports:
10+
ports: # Update the following ports to match your Gateway Listener ports
1111
- port: 80
1212
targetPort: 80
1313
protocol: TCP
1414
name: http
15+
- port: 443
16+
targetPort: 443
17+
protocol: TCP
18+
name: https
1519
selector:
1620
app: nginx-gateway

deploy/manifests/service/loadbalancer.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ metadata:
66
spec:
77
externalTrafficPolicy: Local
88
type: LoadBalancer
9-
ports:
9+
ports: # Update the following ports to match your Gateway Listener ports
1010
- port: 80
1111
targetPort: 80
1212
protocol: TCP

deploy/manifests/service/nodeport.yaml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,14 @@ metadata:
55
namespace: nginx-gateway
66
spec:
77
type: NodePort
8-
ports:
8+
ports: # Update the following ports to match your Gateway Listener ports
99
- port: 80
1010
targetPort: 80
1111
protocol: TCP
1212
name: http
13+
- port: 443
14+
targetPort: 443
15+
protocol: TCP
16+
name: https
1317
selector:
1418
app: nginx-gateway

docs/gateway-api-compatibility.md

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ Fields:
5858
* `listeners`
5959
* `name` - supported.
6060
* `hostname` - partially supported. Wildcard hostnames like `*.example.com` are not yet supported.
61-
* `port` - partially supported. Allowed values: `80` for HTTP listeners and `443` for HTTPS listeners.
61+
* `port` - supported.
6262
* `protocol` - partially supported. Allowed values: `HTTP`, `HTTPS`.
6363
* `tls`
6464
* `mode` - partially supported. Allowed value: `Terminate`.
@@ -86,13 +86,12 @@ Fields:
8686
* `Accepted/True/Accepted`
8787
* `Accepted/False/UnsupportedProtocol`
8888
* `Accepted/False/InvalidCertificateRef`
89-
* `Accepted/False/HostnameConflict`
90-
* `Accepted/False/PortUnavailable`
89+
* `Accepted/False/ProtocolConflict`
9190
* `Accepted/False/UnsupportedValue`: Custom reason for when a value of a field in a Listener is invalid or not supported.
9291
* `Accepted/False/GatewayConflict`: Custom reason for when the Gateway is ignored due to a conflicting Gateway. NKG only supports a single Gateway.
9392
* `ResolvedRefs/True/ResolvedRefs`
9493
* `ResolvedRefs/False/InvalidCertificateRef`
95-
* `Conflicted/True/HostnameConflict`
94+
* `Conflicted/True/ProtocolConflict`
9695
* `Conflicted/False/NoConflicts`
9796

9897
### HTTPRoute

docs/installation.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,11 @@ This guide walks you through how to install NGINX Kubernetes Gateway on a generi
7171
7272
You can gain access to NGINX Kubernetes Gateway by creating a `NodePort` Service or a `LoadBalancer` Service.
7373
74+
> Important
75+
>
76+
> The Service manifests expose NGINX Kubernetes Gateway on ports 80 and 443, which exposes any Gateway [Listener](https://gateway-api.sigs.k8s.io/references/spec/#gateway.networking.k8s.io/v1beta1.Listener) configured for those ports. If you'd like to use different ports in your listeners,
77+
> update the manifests accordingly.
78+
7479
### Create a NodePort Service
7580
7681
Create a Service with type `NodePort`:

internal/manager/manager.go

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,9 @@ func Start(cfg config.Config) error {
5656
options := manager.Options{
5757
Scheme: scheme,
5858
Logger: logger,
59+
// We disable the metrics server because we reserve all ports (1-65535) for the data plane.
60+
// Once we add support for Prometheus, we can make this port configurable by the user.
61+
MetricsBindAddress: "0",
5962
}
6063

6164
eventCh := make(chan interface{})

internal/nginx/config/generator_test.go

Lines changed: 11 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
package config_test
22

33
import (
4-
"strings"
54
"testing"
65

6+
. "github.com/onsi/gomega"
77
"k8s.io/apimachinery/pkg/types"
88

99
"github.com/nginxinc/nginx-kubernetes-gateway/internal/nginx/config"
@@ -26,20 +26,24 @@ func TestGenerate(t *testing.T) {
2626
HTTPServers: []dataplane.VirtualServer{
2727
{
2828
IsDefault: true,
29+
Port: 80,
2930
},
3031
{
3132
Hostname: "example.com",
33+
Port: 80,
3234
},
3335
},
3436
SSLServers: []dataplane.VirtualServer{
3537
{
3638
IsDefault: true,
39+
Port: 443,
3740
},
3841
{
3942
Hostname: "example.com",
4043
SSL: &dataplane.SSL{
4144
CertificatePath: "/etc/nginx/secrets/default",
4245
},
46+
Port: 443,
4347
},
4448
},
4549
Upstreams: []dataplane.Upstream{
@@ -50,22 +54,13 @@ func TestGenerate(t *testing.T) {
5054
},
5155
BackendGroups: []dataplane.BackendGroup{bg},
5256
}
57+
g := NewGomegaWithT(t)
58+
5359
generator := config.NewGeneratorImpl()
5460
cfg := string(generator.Generate(conf))
5561

56-
if !strings.Contains(cfg, "listen 80") {
57-
t.Errorf("Generate() did not generate a config with a default HTTP server; config: %s", cfg)
58-
}
59-
60-
if !strings.Contains(cfg, "listen 443") {
61-
t.Errorf("Generate() did not generate a config with an SSL server; config: %s", cfg)
62-
}
63-
64-
if !strings.Contains(cfg, "upstream") {
65-
t.Errorf("Generate() did not generate a config with an upstream block; config: %s", cfg)
66-
}
67-
68-
if !strings.Contains(cfg, "split_clients") {
69-
t.Errorf("Generate() did not generate a config with an split_clients block; config: %s", cfg)
70-
}
62+
g.Expect(cfg).To(ContainSubstring("listen 80"))
63+
g.Expect(cfg).To(ContainSubstring("listen 443"))
64+
g.Expect(cfg).To(ContainSubstring("upstream"))
65+
g.Expect(cfg).To(ContainSubstring("split_clients"))
7166
}

internal/nginx/config/http/config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ type Server struct {
77
Locations []Location
88
IsDefaultHTTP bool
99
IsDefaultSSL bool
10+
Port int32
1011
}
1112

1213
// Location holds all configuration for an HTTP location.

internal/nginx/config/servers.go

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,10 @@ func createServers(httpServers, sslServers []dataplane.VirtualServer) []http.Ser
4242

4343
func createSSLServer(virtualServer dataplane.VirtualServer) http.Server {
4444
if virtualServer.IsDefault {
45-
return createDefaultSSLServer()
45+
return http.Server{
46+
IsDefaultSSL: true,
47+
Port: virtualServer.Port,
48+
}
4649
}
4750

4851
return http.Server{
@@ -51,22 +54,27 @@ func createSSLServer(virtualServer dataplane.VirtualServer) http.Server {
5154
Certificate: virtualServer.SSL.CertificatePath,
5255
CertificateKey: virtualServer.SSL.CertificatePath,
5356
},
54-
Locations: createLocations(virtualServer.PathRules, 443),
57+
Locations: createLocations(virtualServer.PathRules, virtualServer.Port),
58+
Port: virtualServer.Port,
5559
}
5660
}
5761

5862
func createServer(virtualServer dataplane.VirtualServer) http.Server {
5963
if virtualServer.IsDefault {
60-
return createDefaultHTTPServer()
64+
return http.Server{
65+
IsDefaultHTTP: true,
66+
Port: virtualServer.Port,
67+
}
6168
}
6269

6370
return http.Server{
6471
ServerName: virtualServer.Hostname,
65-
Locations: createLocations(virtualServer.PathRules, 80),
72+
Locations: createLocations(virtualServer.PathRules, virtualServer.Port),
73+
Port: virtualServer.Port,
6674
}
6775
}
6876

69-
func createLocations(pathRules []dataplane.PathRule, listenerPort int) []http.Location {
77+
func createLocations(pathRules []dataplane.PathRule, listenerPort int32) []http.Location {
7078
lenPathRules := len(pathRules)
7179

7280
if lenPathRules == 0 {
@@ -171,15 +179,7 @@ func createLocations(pathRules []dataplane.PathRule, listenerPort int) []http.Lo
171179
return locs
172180
}
173181

174-
func createDefaultSSLServer() http.Server {
175-
return http.Server{IsDefaultSSL: true}
176-
}
177-
178-
func createDefaultHTTPServer() http.Server {
179-
return http.Server{IsDefaultHTTP: true}
180-
}
181-
182-
func createReturnValForRedirectFilter(filter *v1beta1.HTTPRequestRedirectFilter, listenerPort int) *http.Return {
182+
func createReturnValForRedirectFilter(filter *v1beta1.HTTPRequestRedirectFilter, listenerPort int32) *http.Return {
183183
if filter == nil {
184184
return nil
185185
}
@@ -196,7 +196,7 @@ func createReturnValForRedirectFilter(filter *v1beta1.HTTPRequestRedirectFilter,
196196

197197
port := listenerPort
198198
if filter.Port != nil {
199-
port = int(*filter.Port)
199+
port = int32(*filter.Port)
200200
}
201201

202202
scheme := "$scheme"

internal/nginx/config/servers_template.go

Lines changed: 39 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,57 +1,59 @@
11
package config
22

33
var serversTemplateText = `
4-
{{ range $s := . -}}
5-
{{ if $s.IsDefaultSSL -}}
4+
{{- range $s := . -}}
5+
{{ if $s.IsDefaultSSL -}}
66
server {
7-
listen 443 ssl default_server;
7+
listen {{ $s.Port }} ssl default_server;
88
9-
ssl_reject_handshake on;
9+
ssl_reject_handshake on;
1010
}
11-
{{- else if $s.IsDefaultHTTP }}
11+
{{- else if $s.IsDefaultHTTP }}
1212
server {
13-
listen 80 default_server;
13+
listen {{ $s.Port }} default_server;
1414
15-
default_type text/html;
16-
return 404;
15+
default_type text/html;
16+
return 404;
1717
}
18-
{{- else }}
18+
{{- else }}
1919
server {
20-
{{- if $s.SSL }}
21-
listen 443 ssl;
22-
ssl_certificate {{ $s.SSL.Certificate }};
23-
ssl_certificate_key {{ $s.SSL.CertificateKey }};
20+
{{- if $s.SSL }}
21+
listen {{ $s.Port }} ssl;
22+
ssl_certificate {{ $s.SSL.Certificate }};
23+
ssl_certificate_key {{ $s.SSL.CertificateKey }};
2424
25-
if ($ssl_server_name != $host) {
26-
return 421;
27-
}
28-
{{- end }}
25+
if ($ssl_server_name != $host) {
26+
return 421;
27+
}
28+
{{- else }}
29+
listen {{ $s.Port }};
30+
{{- end }}
2931
30-
server_name {{ $s.ServerName }};
32+
server_name {{ $s.ServerName }};
3133
32-
{{ range $l := $s.Locations }}
33-
location {{ if $l.Exact }}= {{ end }}{{ $l.Path }} {
34-
{{ if $l.Internal -}}
35-
internal;
36-
{{ end }}
34+
{{ range $l := $s.Locations }}
35+
location {{ if $l.Exact }}= {{ end }}{{ $l.Path }} {
36+
{{ if $l.Internal -}}
37+
internal;
38+
{{ end }}
3739
38-
{{- if $l.Return -}}
39-
return {{ $l.Return.Code }} "{{ $l.Return.Body }}";
40-
{{ end }}
40+
{{- if $l.Return -}}
41+
return {{ $l.Return.Code }} "{{ $l.Return.Body }}";
42+
{{ end }}
4143
42-
{{- if $l.HTTPMatchVar -}}
43-
set $http_matches {{ $l.HTTPMatchVar | printf "%q" }};
44-
js_content httpmatches.redirect;
45-
{{ end }}
44+
{{- if $l.HTTPMatchVar -}}
45+
set $http_matches {{ $l.HTTPMatchVar | printf "%q" }};
46+
js_content httpmatches.redirect;
47+
{{ end }}
4648
47-
{{- if $l.ProxyPass -}}
48-
proxy_set_header Host $host;
49-
proxy_pass {{ $l.ProxyPass }}$request_uri;
50-
{{- end }}
51-
}
52-
{{ end }}
49+
{{- if $l.ProxyPass -}}
50+
proxy_set_header Host $host;
51+
proxy_pass {{ $l.ProxyPass }}$request_uri;
52+
{{- end }}
53+
}
54+
{{ end }}
5355
}
54-
{{- end }}
56+
{{- end }}
5557
{{ end }}
5658
server {
5759
listen unix:/var/lib/nginx/nginx-502-server.sock;

0 commit comments

Comments
 (0)