Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support proxy_next_upstream_timeout #4005

Merged
merged 1 commit into from
Apr 15, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions docs/user-guide/nginx-configuration/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/proxy-send-timeout](#custom-timeouts)|number|
|[nginx.ingress.kubernetes.io/proxy-read-timeout](#custom-timeouts)|number|
|[nginx.ingress.kubernetes.io/proxy-next-upstream](#custom-timeouts)|string|
|[nginx.ingress.kubernetes.io/proxy-next-upstream-timeout](#custom-timeouts)|number|
|[nginx.ingress.kubernetes.io/proxy-next-upstream-tries](#custom-timeouts)|number|
|[nginx.ingress.kubernetes.io/proxy-request-buffering](#custom-timeouts)|string|
|[nginx.ingress.kubernetes.io/proxy-redirect-from](#proxy-redirect)|string|
Expand Down Expand Up @@ -489,6 +490,7 @@ In some scenarios is required to have different values. To allow this we provide
- `nginx.ingress.kubernetes.io/proxy-send-timeout`
- `nginx.ingress.kubernetes.io/proxy-read-timeout`
- `nginx.ingress.kubernetes.io/proxy-next-upstream`
- `nginx.ingress.kubernetes.io/proxy-next-upstream-timeout`
- `nginx.ingress.kubernetes.io/proxy-next-upstream-tries`
- `nginx.ingress.kubernetes.io/proxy-request-buffering`

Expand Down
5 changes: 5 additions & 0 deletions docs/user-guide/nginx-configuration/configmap.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,7 @@ The following table shows a configuration option's name, type, and the default v
|[proxy-cookie-path](#proxy-cookie-path)|string|"off"|
|[proxy-cookie-domain](#proxy-cookie-domain)|string|"off"|
|[proxy-next-upstream](#proxy-next-upstream)|string|"error timeout"|
|[proxy-next-upstream-timeout](#proxy-next-upstream-timeout)|int|0|
|[proxy-next-upstream-tries](#proxy-next-upstream-tries)|int|3|
|[proxy-redirect-from](#proxy-redirect-from)|string|"off"|
|[proxy-request-buffering](#proxy-request-buffering)|string|"on"|
Expand Down Expand Up @@ -789,6 +790,10 @@ Sets a text that [should be changed in the domain attribute](http://nginx.org/en

Specifies in [which cases](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream) a request should be passed to the next server.

## proxy-next-upstream-timeout

[Limits the time](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_timeout) in seconds during which a request can be passed to the next server.

## proxy-next-upstream-tries

Limit the number of [possible tries](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_tries) a request should be passed to the next server.
Expand Down
37 changes: 23 additions & 14 deletions internal/ingress/annotations/proxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,21 @@ import (

// Config returns the proxy timeout to use in the upstream server/s
type Config struct {
BodySize string `json:"bodySize"`
ConnectTimeout int `json:"connectTimeout"`
SendTimeout int `json:"sendTimeout"`
ReadTimeout int `json:"readTimeout"`
BuffersNumber int `json:"buffersNumber"`
BufferSize string `json:"bufferSize"`
CookieDomain string `json:"cookieDomain"`
CookiePath string `json:"cookiePath"`
NextUpstream string `json:"nextUpstream"`
NextUpstreamTries int `json:"nextUpstreamTries"`
ProxyRedirectFrom string `json:"proxyRedirectFrom"`
ProxyRedirectTo string `json:"proxyRedirectTo"`
RequestBuffering string `json:"requestBuffering"`
ProxyBuffering string `json:"proxyBuffering"`
BodySize string `json:"bodySize"`
ConnectTimeout int `json:"connectTimeout"`
SendTimeout int `json:"sendTimeout"`
ReadTimeout int `json:"readTimeout"`
BuffersNumber int `json:"buffersNumber"`
BufferSize string `json:"bufferSize"`
CookieDomain string `json:"cookieDomain"`
CookiePath string `json:"cookiePath"`
NextUpstream string `json:"nextUpstream"`
NextUpstreamTimeout int `json:"nextUpstreamTimeout"`
NextUpstreamTries int `json:"nextUpstreamTries"`
ProxyRedirectFrom string `json:"proxyRedirectFrom"`
ProxyRedirectTo string `json:"proxyRedirectTo"`
RequestBuffering string `json:"requestBuffering"`
ProxyBuffering string `json:"proxyBuffering"`
}

// Equal tests for equality between two Configuration types
Expand Down Expand Up @@ -76,6 +77,9 @@ func (l1 *Config) Equal(l2 *Config) bool {
if l1.NextUpstream != l2.NextUpstream {
return false
}
if l1.NextUpstreamTimeout != l2.NextUpstreamTimeout {
return false
}
if l1.NextUpstreamTries != l2.NextUpstreamTries {
return false
}
Expand Down Expand Up @@ -157,6 +161,11 @@ func (a proxy) Parse(ing *extensions.Ingress) (interface{}, error) {
config.NextUpstream = defBackend.ProxyNextUpstream
}

config.NextUpstreamTimeout, err = parser.GetIntAnnotation("proxy-next-upstream-timeout", ing)
if err != nil {
config.NextUpstreamTimeout = defBackend.ProxyNextUpstreamTimeout
}

config.NextUpstreamTries, err = parser.GetIntAnnotation("proxy-next-upstream-tries", ing)
if err != nil {
config.NextUpstreamTries = defBackend.ProxyNextUpstreamTries
Expand Down
28 changes: 18 additions & 10 deletions internal/ingress/annotations/proxy/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,17 @@ type mockBackend struct {

func (m mockBackend) GetDefaultBackend() defaults.Backend {
return defaults.Backend{
ProxyConnectTimeout: 10,
ProxySendTimeout: 15,
ProxyReadTimeout: 20,
ProxyBuffersNumber: 4,
ProxyBufferSize: "10k",
ProxyBodySize: "3k",
ProxyNextUpstream: "error",
ProxyNextUpstreamTries: 3,
ProxyRequestBuffering: "on",
ProxyBuffering: "off",
ProxyConnectTimeout: 10,
ProxySendTimeout: 15,
ProxyReadTimeout: 20,
ProxyBuffersNumber: 4,
ProxyBufferSize: "10k",
ProxyBodySize: "3k",
ProxyNextUpstream: "error",
ProxyNextUpstreamTimeout: 0,
ProxyNextUpstreamTries: 3,
ProxyRequestBuffering: "on",
ProxyBuffering: "off",
}
}

Expand All @@ -94,6 +95,7 @@ func TestProxy(t *testing.T) {
data[parser.GetAnnotationWithPrefix("proxy-buffer-size")] = "1k"
data[parser.GetAnnotationWithPrefix("proxy-body-size")] = "2k"
data[parser.GetAnnotationWithPrefix("proxy-next-upstream")] = "off"
data[parser.GetAnnotationWithPrefix("proxy-next-upstream-timeout")] = "5"
data[parser.GetAnnotationWithPrefix("proxy-next-upstream-tries")] = "3"
data[parser.GetAnnotationWithPrefix("proxy-request-buffering")] = "off"
data[parser.GetAnnotationWithPrefix("proxy-buffering")] = "on"
Expand Down Expand Up @@ -128,6 +130,9 @@ func TestProxy(t *testing.T) {
if p.NextUpstream != "off" {
t.Errorf("expected off as next-upstream but returned %v", p.NextUpstream)
}
if p.NextUpstreamTimeout != 5 {
t.Errorf("expected 5 as next-upstream-timeout but returned %v", p.NextUpstreamTimeout)
}
if p.NextUpstreamTries != 3 {
t.Errorf("expected 3 as next-upstream-tries but returned %v", p.NextUpstreamTries)
}
Expand Down Expand Up @@ -174,6 +179,9 @@ func TestProxyWithNoAnnotation(t *testing.T) {
if p.NextUpstream != "error" {
t.Errorf("expected error as next-upstream but returned %v", p.NextUpstream)
}
if p.NextUpstreamTimeout != 0 {
t.Errorf("expected 0 as next-upstream-timeout but returned %v", p.NextUpstreamTimeout)
}
if p.NextUpstreamTries != 3 {
t.Errorf("expected 3 as next-upstream-tries but returned %v", p.NextUpstreamTries)
}
Expand Down
41 changes: 21 additions & 20 deletions internal/ingress/controller/config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -672,26 +672,27 @@ func NewDefault() Configuration {
UseHTTP2: true,
ProxyStreamTimeout: "600s",
Backend: defaults.Backend{
ProxyBodySize: bodySize,
ProxyConnectTimeout: 5,
ProxyReadTimeout: 60,
ProxySendTimeout: 60,
ProxyBuffersNumber: 4,
ProxyBufferSize: "4k",
ProxyCookieDomain: "off",
ProxyCookiePath: "off",
ProxyNextUpstream: "error timeout",
ProxyNextUpstreamTries: 3,
ProxyRequestBuffering: "on",
ProxyRedirectFrom: "off",
ProxyRedirectTo: "off",
SSLRedirect: true,
CustomHTTPErrors: []int{},
WhitelistSourceRange: []string{},
SkipAccessLogURLs: []string{},
LimitRate: 0,
LimitRateAfter: 0,
ProxyBuffering: "off",
ProxyBodySize: bodySize,
ProxyConnectTimeout: 5,
ProxyReadTimeout: 60,
ProxySendTimeout: 60,
ProxyBuffersNumber: 4,
ProxyBufferSize: "4k",
ProxyCookieDomain: "off",
ProxyCookiePath: "off",
ProxyNextUpstream: "error timeout",
ProxyNextUpstreamTimeout: 0,
ProxyNextUpstreamTries: 3,
ProxyRequestBuffering: "on",
ProxyRedirectFrom: "off",
ProxyRedirectTo: "off",
SSLRedirect: true,
CustomHTTPErrors: []int{},
WhitelistSourceRange: []string{},
SkipAccessLogURLs: []string{},
LimitRate: 0,
LimitRateAfter: 0,
ProxyBuffering: "off",
},
UpstreamKeepaliveConnections: 32,
UpstreamKeepaliveTimeout: 60,
Expand Down
30 changes: 16 additions & 14 deletions internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,13 @@ package controller

import (
"fmt"
"k8s.io/ingress-nginx/internal/ingress/annotations/log"
"sort"
"strconv"
"strings"
"time"

"k8s.io/ingress-nginx/internal/ingress/annotations/log"

"github.com/mitchellh/hashstructure"
"k8s.io/klog"

Expand Down Expand Up @@ -841,19 +842,20 @@ func (n *NGINXController) createServers(data []*ingress.Ingress,

bdef := n.store.GetDefaultBackend()
ngxProxy := proxy.Config{
BodySize: bdef.ProxyBodySize,
ConnectTimeout: bdef.ProxyConnectTimeout,
SendTimeout: bdef.ProxySendTimeout,
ReadTimeout: bdef.ProxyReadTimeout,
BuffersNumber: bdef.ProxyBuffersNumber,
BufferSize: bdef.ProxyBufferSize,
CookieDomain: bdef.ProxyCookieDomain,
CookiePath: bdef.ProxyCookiePath,
NextUpstream: bdef.ProxyNextUpstream,
NextUpstreamTries: bdef.ProxyNextUpstreamTries,
RequestBuffering: bdef.ProxyRequestBuffering,
ProxyRedirectFrom: bdef.ProxyRedirectFrom,
ProxyBuffering: bdef.ProxyBuffering,
BodySize: bdef.ProxyBodySize,
ConnectTimeout: bdef.ProxyConnectTimeout,
SendTimeout: bdef.ProxySendTimeout,
ReadTimeout: bdef.ProxyReadTimeout,
BuffersNumber: bdef.ProxyBuffersNumber,
BufferSize: bdef.ProxyBufferSize,
CookieDomain: bdef.ProxyCookieDomain,
CookiePath: bdef.ProxyCookiePath,
NextUpstream: bdef.ProxyNextUpstream,
NextUpstreamTimeout: bdef.ProxyNextUpstreamTimeout,
NextUpstreamTries: bdef.ProxyNextUpstreamTries,
RequestBuffering: bdef.ProxyRequestBuffering,
ProxyRedirectFrom: bdef.ProxyRedirectFrom,
ProxyBuffering: bdef.ProxyBuffering,
}

// generated on Start() with createDefaultSSLCertificate()
Expand Down
4 changes: 4 additions & 0 deletions internal/ingress/defaults/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ type Backend struct {
// http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream
ProxyNextUpstream string `json:"proxy-next-upstream"`

// Limits the time during which a request can be passed to the next server.
// http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_timeout
ProxyNextUpstreamTimeout int `json:"proxy-next-upstream-timeout"`

// Limits the number of possible tries for passing a request to the next server.
// https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream_tries
ProxyNextUpstreamTries int `json:"proxy-next-upstream-tries"`
Expand Down
1 change: 1 addition & 0 deletions rootfs/etc/nginx/template/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1237,6 +1237,7 @@ stream {

# In case of errors try the next upstream server before returning an error
proxy_next_upstream {{ buildNextUpstream $location.Proxy.NextUpstream $all.Cfg.RetryNonIdempotent }};
proxy_next_upstream_timeout {{ $location.Proxy.NextUpstreamTimeout }};
proxy_next_upstream_tries {{ $location.Proxy.NextUpstreamTries }};

{{/* Add any additional configuration defined */}}
Expand Down
25 changes: 23 additions & 2 deletions test/e2e/annotations/proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,8 +180,9 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {

It("should build proxy next upstream", func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/proxy-next-upstream": "error timeout http_502",
"nginx.ingress.kubernetes.io/proxy-next-upstream-tries": "5",
"nginx.ingress.kubernetes.io/proxy-next-upstream": "error timeout http_502",
"nginx.ingress.kubernetes.io/proxy-next-upstream-timeout": "10",
"nginx.ingress.kubernetes.io/proxy-next-upstream-tries": "5",
}

ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, &annotations)
Expand All @@ -190,10 +191,30 @@ var _ = framework.IngressNginxDescribe("Annotations - Proxy", func() {
f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_next_upstream error timeout http_502;") &&
strings.Contains(server, "proxy_next_upstream_timeout 10;") &&
strings.Contains(server, "proxy_next_upstream_tries 5;")
})
})

It("should build proxy next upstream using configmap values", func() {
annotations := map[string]string{}
ing := framework.NewSingleIngress(host, "/", host, f.Namespace, "http-svc", 80, &annotations)
f.EnsureIngress(ing)

f.SetNginxConfigMapData(map[string]string{
"proxy-next-upstream": "timeout http_502",
"proxy-next-upstream-timeout": "53",
"proxy-next-upstream-tries": "44",
})

f.WaitForNginxServer(host,
func(server string) bool {
return strings.Contains(server, "proxy_next_upstream timeout http_502;") &&
strings.Contains(server, "proxy_next_upstream_timeout 53;") &&
strings.Contains(server, "proxy_next_upstream_tries 44;")
})
})

It("should setup proxy cookies", func() {
annotations := map[string]string{
"nginx.ingress.kubernetes.io/proxy-cookie-domain": "localhost example.org",
Expand Down