Add support to enable/disable proxy buffering (#1998)

* Enable proxy buffering using configmap and annotation

* add documentation
This commit is contained in:
Anish Ramasekar 2018-01-29 08:43:55 -06:00 committed by Manuel Alejandro de Brito Fontes
parent 86889532aa
commit b020686599
8 changed files with 41 additions and 2 deletions

View file

@ -58,6 +58,7 @@ The following annotations are supported:
|[nginx.ingress.kubernetes.io/upstream-hash-by](#custom-nginx-upstream-hashing)|string| |[nginx.ingress.kubernetes.io/upstream-hash-by](#custom-nginx-upstream-hashing)|string|
|[nginx.ingress.kubernetes.io/upstream-vhost](#custom-nginx-upstream-vhost)|string| |[nginx.ingress.kubernetes.io/upstream-vhost](#custom-nginx-upstream-vhost)|string|
|[nginx.ingress.kubernetes.io/whitelist-source-range](#whitelist-source-range)|CIDR| |[nginx.ingress.kubernetes.io/whitelist-source-range](#whitelist-source-range)|CIDR|
|[nginx.ingress.kubernetes.io/proxy-buffering](#proxy-buffering)|string|
**Note:** all the values must be a string. In case of booleans or number it must be quoted. **Note:** all the values must be a string. In case of booleans or number it must be quoted.
@ -406,3 +407,15 @@ To use custom values in an Ingress rule define these annotation:
```yaml ```yaml
nginx.ingress.kubernetes.io/proxy-body-size: 8m nginx.ingress.kubernetes.io/proxy-body-size: 8m
``` ```
### Proxy buffering
Enable or disable proxy buffering [`proxy_buffering`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering).
By default proxy buffering is disabled in the nginx config.
To configure this setting globally for all Ingress rules, the `proxy-buffering` value may be set in the NGINX ConfigMap.
To use custom values in an Ingress rule define these annotation:
```yaml
nginx.ingress.kubernetes.io/proxy-buffering: "on"
```

View file

@ -126,6 +126,7 @@ The following table shows a configuration option's name, type, and the default v
|[limit‑rate](#limit-rate)|int|0| |[limit‑rate](#limit-rate)|int|0|
|[limit‑rate‑after](#limit-rate-after)|int|0| |[limit‑rate‑after](#limit-rate-after)|int|0|
|[http‑redirect‑code](#http-redirect-code)|int|308| |[http‑redirect‑code](#http-redirect-code)|int|308|
|[proxy‑buffering](#proxy-buffering)|string|"off"|
## add-headers ## add-headers
@ -698,3 +699,7 @@ Default code is 308.
Why the default code is 308? Why the default code is 308?
[RFC 7238](https://tools.ietf.org/html/rfc7238) was created to define the 308 (Permanent Redirect) status code that is similar to 301 (Moved Permanently) but it keeps the payload in the redirect. This is important if the we send a redirect in methods like POST. [RFC 7238](https://tools.ietf.org/html/rfc7238) was created to define the 308 (Permanent Redirect) status code that is similar to 301 (Moved Permanently) but it keeps the payload in the redirect. This is important if the we send a redirect in methods like POST.
## proxy-buffering
Enables or disables [buffering of responses from the proxied server](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering).

View file

@ -37,6 +37,7 @@ type Config struct {
ProxyRedirectFrom string `json:"proxyRedirectFrom"` ProxyRedirectFrom string `json:"proxyRedirectFrom"`
ProxyRedirectTo string `json:"proxyRedirectTo"` ProxyRedirectTo string `json:"proxyRedirectTo"`
RequestBuffering string `json:"requestBuffering"` RequestBuffering string `json:"requestBuffering"`
ProxyBuffering string `json:"proxyBuffering"`
} }
// Equal tests for equality between two Configuration types // Equal tests for equality between two Configuration types
@ -83,6 +84,9 @@ func (l1 *Config) Equal(l2 *Config) bool {
if l1.ProxyRedirectTo != l2.ProxyRedirectTo { if l1.ProxyRedirectTo != l2.ProxyRedirectTo {
return false return false
} }
if l1.ProxyBuffering != l2.ProxyBuffering {
return false
}
return true return true
} }
@ -99,6 +103,7 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// ParseAnnotations parses the annotations contained in the ingress // ParseAnnotations parses the annotations contained in the ingress
// rule used to configure upstream check parameters // rule used to configure upstream check parameters
func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) { func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
defBackend := a.r.GetDefaultBackend() defBackend := a.r.GetDefaultBackend()
ct, err := parser.GetIntAnnotation("proxy-connect-timeout", ing) ct, err := parser.GetIntAnnotation("proxy-connect-timeout", ing)
if err != nil { if err != nil {
@ -160,5 +165,10 @@ func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
prt = defBackend.ProxyRedirectTo prt = defBackend.ProxyRedirectTo
} }
return &Config{bs, ct, st, rt, bufs, cd, cp, nu, pp, prf, prt, rb}, nil pb, err := parser.GetStringAnnotation("proxy-buffering", ing)
if err != nil || pb == "" {
pb = defBackend.ProxyBuffering
}
return &Config{bs, ct, st, rt, bufs, cd, cp, nu, pp, prf, prt, rb, pb}, nil
} }

View file

@ -79,6 +79,7 @@ func (m mockBackend) GetDefaultBackend() defaults.Backend {
ProxyNextUpstream: "error", ProxyNextUpstream: "error",
ProxyPassParams: "nocanon keepalive=On", ProxyPassParams: "nocanon keepalive=On",
ProxyRequestBuffering: "on", ProxyRequestBuffering: "on",
ProxyBuffering: "off",
} }
} }
@ -94,6 +95,7 @@ func TestProxy(t *testing.T) {
data[parser.GetAnnotationWithPrefix("proxy-next-upstream")] = "off" data[parser.GetAnnotationWithPrefix("proxy-next-upstream")] = "off"
data[parser.GetAnnotationWithPrefix("proxy-pass-params")] = "smax=5 max=10" data[parser.GetAnnotationWithPrefix("proxy-pass-params")] = "smax=5 max=10"
data[parser.GetAnnotationWithPrefix("proxy-request-buffering")] = "off" data[parser.GetAnnotationWithPrefix("proxy-request-buffering")] = "off"
data[parser.GetAnnotationWithPrefix("proxy-buffering")] = "on"
ing.SetAnnotations(data) ing.SetAnnotations(data)
i, err := NewParser(mockBackend{}).Parse(ing) i, err := NewParser(mockBackend{}).Parse(ing)
@ -128,6 +130,9 @@ func TestProxy(t *testing.T) {
if p.RequestBuffering != "off" { if p.RequestBuffering != "off" {
t.Errorf("expected off as request-buffering but returned %v", p.RequestBuffering) t.Errorf("expected off as request-buffering but returned %v", p.RequestBuffering)
} }
if p.ProxyBuffering != "on" {
t.Errorf("expected on as proxy-buffering but returned %v", p.ProxyBuffering)
}
} }
func TestProxyWithNoAnnotation(t *testing.T) { func TestProxyWithNoAnnotation(t *testing.T) {

View file

@ -548,6 +548,7 @@ func NewDefault() Configuration {
SkipAccessLogURLs: []string{}, SkipAccessLogURLs: []string{},
LimitRate: 0, LimitRate: 0,
LimitRateAfter: 0, LimitRateAfter: 0,
ProxyBuffering: "off",
}, },
UpstreamKeepaliveConnections: 32, UpstreamKeepaliveConnections: 32,
LimitConnZoneVariable: defaultLimitConnZoneVariable, LimitConnZoneVariable: defaultLimitConnZoneVariable,

View file

@ -814,6 +814,7 @@ func (n *NGINXController) createServers(data []*extensions.Ingress,
NextUpstream: bdef.ProxyNextUpstream, NextUpstream: bdef.ProxyNextUpstream,
RequestBuffering: bdef.ProxyRequestBuffering, RequestBuffering: bdef.ProxyRequestBuffering,
ProxyRedirectFrom: bdef.ProxyRedirectFrom, ProxyRedirectFrom: bdef.ProxyRedirectFrom,
ProxyBuffering: bdef.ProxyBuffering,
} }
// generated on Start() with createDefaultSSLCertificate() // generated on Start() with createDefaultSSLCertificate()

View file

@ -138,4 +138,8 @@ type Backend struct {
// Sets the initial amount after which the further transmission of a response to a client will be rate limited. // Sets the initial amount after which the further transmission of a response to a client will be rate limited.
// http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate_after // http://nginx.org/en/docs/http/ngx_http_core_module.html#limit_rate_after
LimitRateAfter int `json:"limit-rate-after"` LimitRateAfter int `json:"limit-rate-after"`
// Enables or disables buffering of responses from the proxied server.
// http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
ProxyBuffering string `json:"proxy-buffering"`
} }

View file

@ -828,7 +828,7 @@ stream {
proxy_send_timeout {{ $location.Proxy.SendTimeout }}s; proxy_send_timeout {{ $location.Proxy.SendTimeout }}s;
proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s; proxy_read_timeout {{ $location.Proxy.ReadTimeout }}s;
proxy_buffering off; proxy_buffering "{{ $location.Proxy.ProxyBuffering }}";
proxy_buffer_size "{{ $location.Proxy.BufferSize }}"; proxy_buffer_size "{{ $location.Proxy.BufferSize }}";
proxy_buffers 4 "{{ $location.Proxy.BufferSize }}"; proxy_buffers 4 "{{ $location.Proxy.BufferSize }}";
proxy_request_buffering "{{ $location.Proxy.RequestBuffering }}"; proxy_request_buffering "{{ $location.Proxy.RequestBuffering }}";