diff --git a/deployments/common/crds/k8s.nginx.org_transportservers.yaml b/deployments/common/crds/k8s.nginx.org_transportservers.yaml index d1a291ff51..dfd6e4aed2 100644 --- a/deployments/common/crds/k8s.nginx.org_transportservers.yaml +++ b/deployments/common/crds/k8s.nginx.org_transportservers.yaml @@ -71,6 +71,8 @@ spec: properties: timeout: type: string + streamSnippets: + type: string upstreamParameters: description: UpstreamParameters defines parameters for an upstream. type: object diff --git a/deployments/helm-chart/crds/k8s.nginx.org_transportservers.yaml b/deployments/helm-chart/crds/k8s.nginx.org_transportservers.yaml index d1a291ff51..dfd6e4aed2 100644 --- a/deployments/helm-chart/crds/k8s.nginx.org_transportservers.yaml +++ b/deployments/helm-chart/crds/k8s.nginx.org_transportservers.yaml @@ -71,6 +71,8 @@ spec: properties: timeout: type: string + streamSnippets: + type: string upstreamParameters: description: UpstreamParameters defines parameters for an upstream. type: object diff --git a/docs-web/configuration/transportserver-resource.md b/docs-web/configuration/transportserver-resource.md index 1d1dfa971a..c06f05eee3 100644 --- a/docs-web/configuration/transportserver-resource.md +++ b/docs-web/configuration/transportserver-resource.md @@ -123,6 +123,10 @@ The TransportServer resource defines load balancing configuration for TCP, UDP, - Specifies which Ingress Controller must handle the TransportServer resource. - ``string`` - No + * - ``streamSnippets`` + - Sets a custom snippet in the ``stream`` context. + - ``string`` + - No * - ``serverSnippets`` - Sets a custom snippet in the ``server`` context. - ``string`` @@ -396,6 +400,23 @@ spec: port: 80 ``` +Snippets can also be specified for a stream. In the example below, we use snippets to [limit the number of connections](https://nginx.org/en/docs/stream/ngx_stream_limit_conn_module.html): + +```yaml +apiVersion: k8s.nginx.org/v1alpha1 +kind: TransportServer +metadata: + name: cafe +spec: + host: cafe.example.com + streamSnippets: limit_conn_zone $binary_remote_addr zone=addr:10m; + serverSnippets: limit_conn addr 1; + upstreams: + - name: tea + service: tea-svc + port: 80 +``` + Snippets are intended to be used by advanced NGINX users who need more control over the generated NGINX configuration. However, because of the disadvantages described below, snippets are disabled by default. To use snippets, set the [`enable-snippets`](/nginx-ingress-controller/configuration/global-configuration/command-line-arguments#cmdoption-enable-snippets) command-line argument. diff --git a/internal/configs/transportserver.go b/internal/configs/transportserver.go index b01b13b159..87afd00be7 100644 --- a/internal/configs/transportserver.go +++ b/internal/configs/transportserver.go @@ -61,6 +61,8 @@ func generateTransportServerConfig(transportServerEx *TransportServerEx, listene serverSnippets := generateSnippets(true, transportServerEx.TransportServer.Spec.ServerSnippets, []string{}) + streamSnippets := generateSnippets(true, transportServerEx.TransportServer.Spec.StreamSnippets, []string{}) + statusZone := transportServerEx.TransportServer.Spec.Listener.Name if transportServerEx.TransportServer.Spec.Listener.Name == conf_v1alpha1.TLSPassthroughListenerName { statusZone = transportServerEx.TransportServer.Spec.Host @@ -84,9 +86,10 @@ func generateTransportServerConfig(transportServerEx *TransportServerEx, listene ProxyNextUpstreamTimeout: generateTimeWithDefault(nextUpstreamTimeout, "0s"), ProxyNextUpstreamTries: nextUpstreamTries, HealthCheck: healthCheck, - Snippets: serverSnippets, + ServerSnippets: serverSnippets, }, - Upstreams: upstreams, + Upstreams: upstreams, + StreamSnippets: streamSnippets, } return tsConfig diff --git a/internal/configs/transportserver_test.go b/internal/configs/transportserver_test.go index 3ea91322f5..faa0ec9ba9 100644 --- a/internal/configs/transportserver_test.go +++ b/internal/configs/transportserver_test.go @@ -84,6 +84,7 @@ func TestGenerateTransportServerConfigForTCPSnippets(t *testing.T) { Pass: "tcp-app", }, ServerSnippets: "deny 192.168.1.1;\nallow 192.168.1.0/24;", + StreamSnippets: "limit_conn_zone $binary_remote_addr zone=addr:10m;", }, }, Endpoints: map[string][]string{ @@ -127,8 +128,9 @@ func TestGenerateTransportServerConfigForTCPSnippets(t *testing.T) { ProxyNextUpstreamTimeout: "0s", ProxyTimeout: "10m", HealthCheck: nil, - Snippets: []string{"deny 192.168.1.1;", "allow 192.168.1.0/24;"}, + ServerSnippets: []string{"deny 192.168.1.1;", "allow 192.168.1.0/24;"}, }, + StreamSnippets: []string{"limit_conn_zone $binary_remote_addr zone=addr:10m;"}, } result := generateTransportServerConfig(&transportServerEx, listenerPort, true) @@ -211,8 +213,9 @@ func TestGenerateTransportServerConfigForTCP(t *testing.T) { ProxyNextUpstreamTimeout: "0s", ProxyTimeout: "50s", HealthCheck: nil, - Snippets: []string{}, + ServerSnippets: []string{}, }, + StreamSnippets: []string{}, } result := generateTransportServerConfig(&transportServerEx, listenerPort, true) @@ -296,8 +299,9 @@ func TestGenerateTransportServerConfigForTLSPasstrhough(t *testing.T) { ProxyNextUpstreamTries: 0, ProxyTimeout: "10m", HealthCheck: nil, - Snippets: []string{}, + ServerSnippets: []string{}, }, + StreamSnippets: []string{}, } result := generateTransportServerConfig(&transportServerEx, listenerPort, true) @@ -385,8 +389,9 @@ func TestGenerateTransportServerConfigForUDP(t *testing.T) { ProxyNextUpstreamTries: 0, ProxyTimeout: "10m", HealthCheck: nil, - Snippets: []string{}, + ServerSnippets: []string{}, }, + StreamSnippets: []string{}, } result := generateTransportServerConfig(&transportServerEx, listenerPort, true) diff --git a/internal/configs/version2/nginx-plus.transportserver.tmpl b/internal/configs/version2/nginx-plus.transportserver.tmpl index 1bed8a9d55..bd66d43c81 100644 --- a/internal/configs/version2/nginx-plus.transportserver.tmpl +++ b/internal/configs/version2/nginx-plus.transportserver.tmpl @@ -10,6 +10,10 @@ upstream {{ $u.Name }} { } {{ end }} +{{ range $snippet := .StreamSnippets }} +{{- $snippet }} +{{ end }} + {{ $s := .Server }} server { {{ if $s.TLSPassthrough }} @@ -28,7 +32,7 @@ server { proxy_responses {{ $s.ProxyResponses }}; {{ end }} - {{ range $snippet := $s.Snippets }} + {{ range $snippet := $s.ServerSnippets }} {{- $snippet }} {{ end }} diff --git a/internal/configs/version2/nginx.transportserver.tmpl b/internal/configs/version2/nginx.transportserver.tmpl index 014f5ee2a2..d197ee2740 100644 --- a/internal/configs/version2/nginx.transportserver.tmpl +++ b/internal/configs/version2/nginx.transportserver.tmpl @@ -10,6 +10,10 @@ upstream {{ $u.Name }} { } {{ end }} +{{ range $snippet := .StreamSnippets }} +{{- $snippet }} +{{ end }} + {{ $s := .Server }} server { {{ if $s.TLSPassthrough }} @@ -26,7 +30,7 @@ server { proxy_responses {{ $s.ProxyResponses }}; {{ end }} - {{ range $snippet := $s.Snippets }} + {{ range $snippet := $s.ServerSnippets }} {{- $snippet }} {{ end }} diff --git a/internal/configs/version2/stream.go b/internal/configs/version2/stream.go index 4ef2ceaeed..d7e58c4508 100644 --- a/internal/configs/version2/stream.go +++ b/internal/configs/version2/stream.go @@ -2,8 +2,9 @@ package version2 // TransportServerConfig holds NGINX configuration for a TransportServer. type TransportServerConfig struct { - Server StreamServer - Upstreams []StreamUpstream + Server StreamServer + Upstreams []StreamUpstream + StreamSnippets []string } // StreamUpstream defines a stream upstream. @@ -38,7 +39,7 @@ type StreamServer struct { ProxyNextUpstreamTimeout string ProxyNextUpstreamTries int HealthCheck *StreamHealthCheck - Snippets []string + ServerSnippets []string } // StreamHealthCheck defines a health check for a StreamUpstream in a StreamServer. diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index 30d5fe5d4d..c8660b6412 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -603,7 +603,6 @@ func (lbc *LoadBalancerController) createExtendedResources(resources []Resource) case *TransportServerConfiguration: tsEx := lbc.createTransportServerEx(impl.TransportServer, impl.ListenerPort) result.TransportServerExes = append(result.TransportServerExes, tsEx) - } } diff --git a/pkg/apis/configuration/v1alpha1/types.go b/pkg/apis/configuration/v1alpha1/types.go index 72bc48fb19..10a8588eb8 100644 --- a/pkg/apis/configuration/v1alpha1/types.go +++ b/pkg/apis/configuration/v1alpha1/types.go @@ -69,6 +69,7 @@ type TransportServerSpec struct { IngressClass string `json:"ingressClassName"` Listener TransportServerListener `json:"listener"` ServerSnippets string `json:"serverSnippets"` + StreamSnippets string `json:"streamSnippets"` Host string `json:"host"` Upstreams []Upstream `json:"upstreams"` UpstreamParameters *UpstreamParameters `json:"upstreamParameters"` diff --git a/pkg/apis/configuration/validation/transportserver.go b/pkg/apis/configuration/validation/transportserver.go index 55ba51be07..ed622a001d 100644 --- a/pkg/apis/configuration/validation/transportserver.go +++ b/pkg/apis/configuration/validation/transportserver.go @@ -52,6 +52,8 @@ func (tsv *TransportServerValidator) validateTransportServerSpec(spec *v1alpha1. allErrs = append(allErrs, validateSnippets(spec.ServerSnippets, fieldPath.Child("serverSnippets"), tsv.snippetsEnabled)...) + allErrs = append(allErrs, validateSnippets(spec.StreamSnippets, fieldPath.Child("streamSnippets"), tsv.snippetsEnabled)...) + return allErrs }