From 5acd43efaf076ae2204285e750e41976c29069f2 Mon Sep 17 00:00:00 2001 From: Jared Biel <961717+jbiel@users.noreply.github.com> Date: Thu, 27 Sep 2018 13:16:03 -0500 Subject: [PATCH] Add health check timeout parameter --- autogen/gentemplates/gen.go | 7 +++ cmd/configuration.go | 2 + configuration/configuration.go | 4 ++ docs/basics.md | 12 +++- docs/configuration/backends/consulcatalog.md | 3 +- docs/configuration/backends/docker.md | 3 +- docs/configuration/backends/ecs.md | 3 +- docs/configuration/backends/file.md | 1 + docs/configuration/backends/marathon.md | 3 +- docs/configuration/backends/mesos.md | 3 +- docs/configuration/backends/rancher.md | 3 +- docs/configuration/backends/servicefabric.md | 3 +- docs/configuration/commons.md | 14 +++-- docs/user-guide/marathon.md | 2 +- healthcheck/healthcheck.go | 10 ++-- healthcheck/healthcheck_test.go | 4 +- integration/consul_catalog_test.go | 1 + .../healthcheck/multiple-entrypoints-drr.toml | 1 + .../healthcheck/multiple-entrypoints-wrr.toml | 1 + .../fixtures/healthcheck/port_overload.toml | 1 + integration/fixtures/healthcheck/simple.toml | 1 + provider/consulcatalog/config_test.go | 2 + .../docker/config_container_docker_test.go | 2 + .../docker/config_container_swarm_test.go | 2 + provider/ecs/config_test.go | 11 +++- provider/kv/keynames.go | 1 + provider/kv/kv_config.go | 2 + provider/kv/kv_config_test.go | 11 +++- provider/label/names.go | 2 + provider/label/partial.go | 2 + provider/label/partial_test.go | 3 + provider/marathon/config_test.go | 4 ++ provider/mesos/config_test.go | 4 ++ provider/rancher/config_test.go | 2 + server/server_configuration_test.go | 56 ++++++++++++++++++- server/server_loadbalancer.go | 17 ++++++ templates/consul_catalog.tmpl | 1 + templates/docker.tmpl | 1 + templates/ecs.tmpl | 1 + templates/kv.tmpl | 1 + templates/marathon.tmpl | 1 + templates/mesos.tmpl | 1 + templates/rancher.tmpl | 1 + types/types.go | 1 + .../providers/providers.component.html | 6 ++ 45 files changed, 189 insertions(+), 28 deletions(-) diff --git a/autogen/gentemplates/gen.go b/autogen/gentemplates/gen.go index ac8211c3f..fd86522b8 100644 --- a/autogen/gentemplates/gen.go +++ b/autogen/gentemplates/gen.go @@ -88,6 +88,7 @@ var _templatesConsul_catalogTmpl = []byte(`[backends] path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] @@ -356,6 +357,7 @@ var _templatesDockerTmpl = []byte(`{{$backendServers := .Servers}} path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] @@ -624,6 +626,7 @@ var _templatesEcsTmpl = []byte(`[backends] path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $serviceName }}".healthCheck.headers] @@ -1152,6 +1155,7 @@ var _templatesKvTmpl = []byte(`[backends] path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."{{ $backendName }}".healthCheck.headers] @@ -1437,6 +1441,7 @@ var _templatesMarathonTmpl = []byte(`{{ $apps := .Applications }} path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends.{{ $backendName }}.healthCheck.headers] @@ -1707,6 +1712,7 @@ var _templatesMesosTmpl = []byte(`[backends] path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] @@ -2000,6 +2006,7 @@ var _templatesRancherTmpl = []byte(`{{ $backendServers := .Backends }} path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] diff --git a/cmd/configuration.go b/cmd/configuration.go index 3e9d4aeea..d1e54ff23 100644 --- a/cmd/configuration.go +++ b/cmd/configuration.go @@ -177,6 +177,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration { // default HealthCheckConfig healthCheck := configuration.HealthCheckConfig{ Interval: parse.Duration(configuration.DefaultHealthCheckInterval), + Timeout: parse.Duration(configuration.DefaultHealthCheckTimeout), } // default RespondingTimeouts @@ -302,6 +303,7 @@ func NewTraefikConfiguration() *TraefikConfiguration { MaxIdleConnsPerHost: 200, HealthCheck: &configuration.HealthCheckConfig{ Interval: parse.Duration(configuration.DefaultHealthCheckInterval), + Timeout: parse.Duration(configuration.DefaultHealthCheckTimeout), }, LifeCycle: &configuration.LifeCycle{ GraceTimeOut: parse.Duration(configuration.DefaultGraceTimeout), diff --git a/configuration/configuration.go b/configuration/configuration.go index 5dc736e07..efafd8ef7 100644 --- a/configuration/configuration.go +++ b/configuration/configuration.go @@ -42,6 +42,9 @@ const ( // DefaultHealthCheckInterval is the default health check interval. DefaultHealthCheckInterval = 30 * time.Second + // DefaultHealthCheckTimeout is the default health check request timeout. + DefaultHealthCheckTimeout = 5 * time.Second + // DefaultDialTimeout when connecting to a backend server. DefaultDialTimeout = 30 * time.Second @@ -372,6 +375,7 @@ type Retry struct { // HealthCheckConfig contains health check configuration parameters. type HealthCheckConfig struct { Interval parse.Duration `description:"Default periodicity of enabled health checks" export:"true"` + Timeout parse.Duration `description:"Default request timeout of enabled health checks" export:"true"` } // RespondingTimeouts contains timeout configurations for incoming requests to the Traefik instance. diff --git a/docs/basics.md b/docs/basics.md index 06bdc7105..d9f4edd5e 100644 --- a/docs/basics.md +++ b/docs/basics.md @@ -452,9 +452,11 @@ If not, a new backend will be assigned. #### Health Check -A health check can be configured in order to remove a backend from LB rotation as long as it keeps returning HTTP status codes other than `2xx` or `3xx` to HTTP GET requests periodically carried out by Traefik. -The check is defined by a path appended to the backend URL and an interval (given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration)) specifying how often the health check should be executed (the default being 30 seconds). -Each backend must respond to the health check within 5 seconds. +A health check can be configured in order to remove a backend from LB rotation as long as it keeps returning HTTP status codes other than `2xx` or `3xx` to HTTP GET requests periodically carried out by Traefik. +The check is defined by a path appended to the backend URL and an interval specifying how often the health check should be executed (the default being 30 seconds.) +Each backend must respond to the health check within a timeout duration (the default being 5 seconds.) +Interval and timeout are to be given in a format understood by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration). +The interval must be greater than the timeout. If configuration doesn't reflect this, the interval will be set to timeout + 1 second. By default, the port of the backend server is used, however, this may be overridden. A recovering backend returning `2xx` or `3xx` responses again is being returned to the LB rotation pool. @@ -466,6 +468,7 @@ For example: [backends.backend1.healthcheck] path = "/health" interval = "10s" + timeout = "3s" ``` To use a different port for the health check: @@ -475,6 +478,7 @@ To use a different port for the health check: [backends.backend1.healthcheck] path = "/health" interval = "10s" + timeout = "3s" port = 8080 ``` @@ -486,6 +490,7 @@ To use a different scheme for the health check: [backends.backend1.healthcheck] path = "/health" interval = "10s" + timeout = "3s" scheme = "http" ``` @@ -496,6 +501,7 @@ Additional http headers and hostname to health check request can be specified, f [backends.backend1.healthcheck] path = "/health" interval = "10s" + timeout = "3s" hostname = "myhost.com" port = 8080 [backends.backend1.healthcheck.headers] diff --git a/docs/configuration/backends/consulcatalog.md b/docs/configuration/backends/consulcatalog.md index e1659ee0e..09b201baa 100644 --- a/docs/configuration/backends/consulcatalog.md +++ b/docs/configuration/backends/consulcatalog.md @@ -106,7 +106,8 @@ Additional settings can be defined using Consul Catalog tags. | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend. ex: `NetworkErrorRatio() > 0.` | | `.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | -| `.backend.healthcheck.interval=1s` | Defines the health check interval. | +| `.backend.healthcheck.interval=5s` | Defines the health check interval. | +| `.backend.healthcheck.timeout=3s` | Defines the health check request timeout | | `.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | diff --git a/docs/configuration/backends/docker.md b/docs/configuration/backends/docker.md index 1a1278cf6..d8c687a19 100644 --- a/docs/configuration/backends/docker.md +++ b/docs/configuration/backends/docker.md @@ -223,7 +223,8 @@ Labels can be used on containers to override default behavior. | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. | +| `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. | +| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | diff --git a/docs/configuration/backends/ecs.md b/docs/configuration/backends/ecs.md index c1631d6e0..b5cc87f0c 100644 --- a/docs/configuration/backends/ecs.md +++ b/docs/configuration/backends/ecs.md @@ -145,7 +145,8 @@ Labels can be used on task containers to override default behavior: | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. (Default: 5s) | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | diff --git a/docs/configuration/backends/file.md b/docs/configuration/backends/file.md index 30f1078d7..13753529f 100644 --- a/docs/configuration/backends/file.md +++ b/docs/configuration/backends/file.md @@ -37,6 +37,7 @@ Træfik can be configured with a file. path = "/health" port = 88 interval = "30s" + timeout = "5s" scheme = "http" hostname = "myhost.com" [backends.backend1.healthcheck.headers] diff --git a/docs/configuration/backends/marathon.md b/docs/configuration/backends/marathon.md index f66868610..2549963b3 100644 --- a/docs/configuration/backends/marathon.md +++ b/docs/configuration/backends/marathon.md @@ -209,7 +209,8 @@ The following labels can be defined on Marathon applications. They adjust the be | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. (Default: 5s) | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | diff --git a/docs/configuration/backends/mesos.md b/docs/configuration/backends/mesos.md index 2e62487ad..1939b30e9 100644 --- a/docs/configuration/backends/mesos.md +++ b/docs/configuration/backends/mesos.md @@ -123,7 +123,8 @@ The following labels can be defined on Mesos tasks. They adjust the behavior for | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. (Default: 30s) | +| `traefik.backend.healthcheck.timeout=3s` | Defines the health check request timeout. (Default: 5s) | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | diff --git a/docs/configuration/backends/rancher.md b/docs/configuration/backends/rancher.md index c98b0e1e5..f9aeb2b2e 100644 --- a/docs/configuration/backends/rancher.md +++ b/docs/configuration/backends/rancher.md @@ -153,7 +153,8 @@ Labels can be used on task containers to override default behavior: | `traefik.backend.buffering.retryExpression=EXPR` | See [buffering](/configuration/commons/#buffering) section. | | `traefik.backend.circuitbreaker.expression=EXPR` | Creates a [circuit breaker](/basics/#backends) to be used against the backend | | `traefik.backend.healthcheck.path=/health` | Enables health check for the backend, hitting the container at `path`. | -| `traefik.backend.healthcheck.interval=1s` | Defines the health check interval. | +| `traefik.backend.healthcheck.interval=5s` | Defines the health check interval. | +| `traefik.backend.healthcheck.timeout=3s ` | Defines the health check request timeout. | | `traefik.backend.healthcheck.port=8080` | Sets a different port for the health check. | | `traefik.backend.healthcheck.scheme=http` | Overrides the server URL scheme. | | `traefik.backend.healthcheck.hostname=foobar.com` | Defines the health check hostname. | diff --git a/docs/configuration/backends/servicefabric.md b/docs/configuration/backends/servicefabric.md index f08b9522b..bedf4fb76 100644 --- a/docs/configuration/backends/servicefabric.md +++ b/docs/configuration/backends/servicefabric.md @@ -103,7 +103,8 @@ Labels, set through extensions or the property manager, can be used on services | `traefik.servicefabric.enablelabeloverrides` | Toggle whether labels can be overridden using the Service Fabric Property Manager API | | `traefik.backend.healthcheck.path=/health` | Enable health check for the backend, hitting the container at `path`. | | `traefik.backend.healthcheck.port=8080` | Allow to use a different port for the health check. | -| `traefik.backend.healthcheck.interval=1s` | Define the health check interval. | +| `traefik.backend.healthcheck.interval=5s` | Define the health check interval. | +| `traefik.backend.healthcheck.timeout=3s` | Define the health check request timeout. | | `traefik.backend.healthcheck.hostname=foobar.com` | Define the health check hostname. | | `traefik.backend.healthcheck.headers=EXPR` | Define the health check request headers
Format: HEADER:value||HEADER2:value2 | | `traefik.backend.loadbalancer.method=drr` | Override the default `wrr` load balancer algorithm | diff --git a/docs/configuration/commons.md b/docs/configuration/commons.md index c1c3fa961..20171420a 100644 --- a/docs/configuration/commons.md +++ b/docs/configuration/commons.md @@ -241,19 +241,23 @@ Example configuration: # Enable custom health check options. [healthcheck] -# Set the default health check interval. +# Set the default health check interval and timeout. # # Optional # Default: "30s" # # interval = "30s" +# timeout = "5s" ``` -- `interval` set the default health check interval. -Will only be effective if health check paths are defined. -Given provider-specific support, the value may be overridden on a per-backend basis. -Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits). +- `interval` sets the default health check interval. +- `timeout` sets the default health check request timeout. + +These options will only be effective if health check paths are defined. +Given provider-specific support, the value may be overridden on a per-backend basis. +Can be provided in a format supported by [time.ParseDuration](https://golang.org/pkg/time/#ParseDuration) or as raw values (digits). If no units are provided, the value is parsed assuming seconds. +**Note:** the interval must be greater than the timeout. If configuration doesn't reflect this, the interval will be set to timeout + 1 second. ## Life Cycle diff --git a/docs/user-guide/marathon.md b/docs/user-guide/marathon.md index d437ff1d5..ec62e1497 100644 --- a/docs/user-guide/marathon.md +++ b/docs/user-guide/marathon.md @@ -71,7 +71,7 @@ Beginning with version 1.4, Traefik respects readiness check results if the Trae !!! note Due to the way readiness check results are currently exposed by the Marathon API, ready tasks may be taken into rotation with a small delay. - It is on the order of one readiness check timeout interval (as configured on the application specifiation) and guarantees that non-ready tasks do not receive traffic prematurely. + It is on the order of one readiness check timeout interval (as configured on the application specification) and guarantees that non-ready tasks do not receive traffic prematurely. If readiness checks are not possible, a current mitigation strategy is to enable [retries](/configuration/commons#retry-configuration) and make sure that a sufficient number of healthy application tasks exist so that one retry will likely hit one of those. Apart from its probabilistic nature, the workaround comes at the price of increased latency. diff --git a/healthcheck/healthcheck.go b/healthcheck/healthcheck.go index f948b0867..ad1cb28c7 100644 --- a/healthcheck/healthcheck.go +++ b/healthcheck/healthcheck.go @@ -42,11 +42,12 @@ type Options struct { Port int Transport http.RoundTripper Interval time.Duration + Timeout time.Duration LB BalancerHandler } func (opt Options) String() string { - return fmt.Sprintf("[Hostname: %s Headers: %v Path: %s Port: %d Interval: %s]", opt.Hostname, opt.Headers, opt.Path, opt.Port, opt.Interval) + return fmt.Sprintf("[Hostname: %s Headers: %v Path: %s Port: %d Interval: %s Timeout: %s]", opt.Hostname, opt.Headers, opt.Path, opt.Port, opt.Interval, opt.Timeout) } // BackendConfig HealthCheck configuration for a backend @@ -180,9 +181,8 @@ func newHealthCheck(metrics metricsRegistry) *HealthCheck { // NewBackendConfig Instantiate a new BackendConfig func NewBackendConfig(options Options, backendName string) *BackendConfig { return &BackendConfig{ - Options: options, - name: backendName, - requestTimeout: 5 * time.Second, + Options: options, + name: backendName, } } @@ -197,7 +197,7 @@ func checkHealth(serverURL *url.URL, backend *BackendConfig) error { req = backend.addHeadersAndHost(req) client := http.Client{ - Timeout: backend.requestTimeout, + Timeout: backend.Options.Timeout, Transport: backend.Options.Transport, } diff --git a/healthcheck/healthcheck_test.go b/healthcheck/healthcheck_test.go index 5b7528bf8..756d234c3 100644 --- a/healthcheck/healthcheck_test.go +++ b/healthcheck/healthcheck_test.go @@ -15,7 +15,8 @@ import ( "github.com/vulcand/oxy/roundrobin" ) -const healthCheckInterval = 100 * time.Millisecond +const healthCheckInterval = 200 * time.Millisecond +const healthCheckTimeout = 100 * time.Millisecond type testHandler struct { done func() @@ -105,6 +106,7 @@ func TestSetBackendsConfiguration(t *testing.T) { backend := NewBackendConfig(Options{ Path: "/path", Interval: healthCheckInterval, + Timeout: healthCheckTimeout, LB: lb, }, "backendName") diff --git a/integration/consul_catalog_test.go b/integration/consul_catalog_test.go index e3156d2ff..7bda5adb6 100644 --- a/integration/consul_catalog_test.go +++ b/integration/consul_catalog_test.go @@ -83,6 +83,7 @@ func (s *ConsulCatalogSuite) registerAgentService(name string, address string, p healthCheck = &api.AgentServiceCheck{ HTTP: "http://" + address, Interval: "10s", + Timeout: "3s", } } else { healthCheck = nil diff --git a/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml b/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml index d2d70b319..6f0c9cf72 100644 --- a/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml +++ b/integration/fixtures/healthcheck/multiple-entrypoints-drr.toml @@ -18,6 +18,7 @@ logLevel = "DEBUG" [backends.backend1.healthcheck] path = "/health" interval = "1s" + timeout = "0.9s" [backends.backend1.servers.server1] url = "http://{{.Server1}}:80" weight = 1 diff --git a/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml b/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml index 27614feb3..9fba423b4 100644 --- a/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml +++ b/integration/fixtures/healthcheck/multiple-entrypoints-wrr.toml @@ -18,6 +18,7 @@ logLevel = "DEBUG" [backends.backend1.healthcheck] path = "/health" interval = "1s" + timeout = "0.9s" [backends.backend1.servers.server1] url = "http://{{.Server1}}:80" weight = 1 diff --git a/integration/fixtures/healthcheck/port_overload.toml b/integration/fixtures/healthcheck/port_overload.toml index f2d839d04..45fcf8feb 100644 --- a/integration/fixtures/healthcheck/port_overload.toml +++ b/integration/fixtures/healthcheck/port_overload.toml @@ -15,6 +15,7 @@ logLevel = "DEBUG" path = "/health" port = 80 interval = "1s" + timeout = "0.9s" [backends.backend1.servers.server1] url = "http://{{.Server1}}:81" weight = 1 diff --git a/integration/fixtures/healthcheck/simple.toml b/integration/fixtures/healthcheck/simple.toml index 1553e01b8..ddd47e030 100644 --- a/integration/fixtures/healthcheck/simple.toml +++ b/integration/fixtures/healthcheck/simple.toml @@ -14,6 +14,7 @@ logLevel = "DEBUG" [backends.backend1.healthcheck] path = "/health" interval = "1s" + timeout = "0.9s" [backends.backend1.servers.server1] url = "http://{{.Server1}}:80" weight = 1 diff --git a/provider/consulcatalog/config_test.go b/provider/consulcatalog/config_test.go index 4c1a4089d..8545b8d9c 100644 --- a/provider/consulcatalog/config_test.go +++ b/provider/consulcatalog/config_test.go @@ -410,6 +410,7 @@ func TestProviderBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckScheme + "=http", label.TraefikBackendHealthCheckPort + "=880", label.TraefikBackendHealthCheckInterval + "=6", + label.TraefikBackendHealthCheckTimeout + "=3", label.TraefikBackendHealthCheckHostname + "=foo.com", label.TraefikBackendHealthCheckHeaders + "=Foo:bar || Bar:foo", label.TraefikBackendLoadBalancerMethod + "=drr", @@ -691,6 +692,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", diff --git a/provider/docker/config_container_docker_test.go b/provider/docker/config_container_docker_test.go index ccff446bc..ef755f1a3 100644 --- a/provider/docker/config_container_docker_test.go +++ b/provider/docker/config_container_docker_test.go @@ -437,6 +437,7 @@ func TestDockerBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckInterval: "6", + label.TraefikBackendHealthCheckTimeout: "3", label.TraefikBackendHealthCheckHostname: "foo.com", label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo", label.TraefikBackendLoadBalancerMethod: "drr", @@ -683,6 +684,7 @@ func TestDockerBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", diff --git a/provider/docker/config_container_swarm_test.go b/provider/docker/config_container_swarm_test.go index 538d615ec..5e47ef7c8 100644 --- a/provider/docker/config_container_swarm_test.go +++ b/provider/docker/config_container_swarm_test.go @@ -385,6 +385,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckInterval: "6", + label.TraefikBackendHealthCheckTimeout: "3", label.TraefikBackendHealthCheckHostname: "foo.com", label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo", label.TraefikBackendLoadBalancerMethod: "drr", @@ -600,6 +601,7 @@ func TestSwarmBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", diff --git a/provider/ecs/config_test.go b/provider/ecs/config_test.go index 14874a887..6af3ae455 100644 --- a/provider/ecs/config_test.go +++ b/provider/ecs/config_test.go @@ -68,7 +68,8 @@ func TestBuildConfiguration(t *testing.T) { ID("1"), dockerLabels(map[string]*string{ label.TraefikBackendHealthCheckPath: aws.String("/health"), - label.TraefikBackendHealthCheckInterval: aws.String("1s"), + label.TraefikBackendHealthCheckInterval: aws.String("6s"), + label.TraefikBackendHealthCheckTimeout: aws.String("3s"), }), iMachine( mState(ec2.InstanceStateNameRunning), @@ -84,7 +85,8 @@ func TestBuildConfiguration(t *testing.T) { "backend-instance": { HealthCheck: &types.HealthCheck{ Path: "/health", - Interval: "1s", + Interval: "6s", + Timeout: "3s", }, Servers: map[string]types.Server{ "server-instance-1": { @@ -343,6 +345,7 @@ func TestBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckInterval: aws.String("6"), + label.TraefikBackendHealthCheckTimeout: aws.String("3"), label.TraefikBackendHealthCheckHostname: aws.String("foo.com"), label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"), @@ -470,6 +473,7 @@ func TestBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", @@ -633,6 +637,7 @@ func TestBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckInterval: aws.String("6"), + label.TraefikBackendHealthCheckTimeout: aws.String("3"), label.TraefikBackendHealthCheckHostname: aws.String("foo.com"), label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"), @@ -719,6 +724,7 @@ func TestBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckPath: aws.String("/health"), label.TraefikBackendHealthCheckPort: aws.String("880"), label.TraefikBackendHealthCheckInterval: aws.String("6"), + label.TraefikBackendHealthCheckTimeout: aws.String("3"), label.TraefikBackendHealthCheckHostname: aws.String("bar.com"), label.TraefikBackendHealthCheckHeaders: aws.String("Foo:bar || Bar:foo"), label.TraefikBackendLoadBalancerMethod: aws.String("drr"), @@ -822,6 +828,7 @@ func TestBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", diff --git a/provider/kv/keynames.go b/provider/kv/keynames.go index df3a5fa29..48ed83542 100644 --- a/provider/kv/keynames.go +++ b/provider/kv/keynames.go @@ -7,6 +7,7 @@ const ( pathBackendHealthCheckPath = "/healthcheck/path" pathBackendHealthCheckPort = "/healthcheck/port" pathBackendHealthCheckInterval = "/healthcheck/interval" + pathBackendHealthCheckTimeout = "/healthcheck/timeout" pathBackendHealthCheckHostname = "/healthcheck/hostname" pathBackendHealthCheckHeaders = "/healthcheck/headers/" pathBackendLoadBalancerMethod = "/loadbalancer/method" diff --git a/provider/kv/kv_config.go b/provider/kv/kv_config.go index 030e80f30..0e680abe7 100644 --- a/provider/kv/kv_config.go +++ b/provider/kv/kv_config.go @@ -271,6 +271,7 @@ func (p *Provider) getHealthCheck(rootPath string) *types.HealthCheck { scheme := p.get("", rootPath, pathBackendHealthCheckScheme) port := p.getInt(label.DefaultBackendHealthCheckPort, rootPath, pathBackendHealthCheckPort) interval := p.get("30s", rootPath, pathBackendHealthCheckInterval) + timeout := p.get("5s", rootPath, pathBackendHealthCheckTimeout) hostname := p.get("", rootPath, pathBackendHealthCheckHostname) headers := p.getMap(rootPath, pathBackendHealthCheckHeaders) @@ -279,6 +280,7 @@ func (p *Provider) getHealthCheck(rootPath string) *types.HealthCheck { Path: path, Port: port, Interval: interval, + Timeout: timeout, Hostname: hostname, Headers: headers, } diff --git a/provider/kv/kv_config_test.go b/provider/kv/kv_config_test.go index 1dbab1e6d..94ba889fa 100644 --- a/provider/kv/kv_config_test.go +++ b/provider/kv/kv_config_test.go @@ -260,6 +260,7 @@ func TestProviderBuildConfiguration(t *testing.T) { withPair(pathBackendHealthCheckPath, "/health"), withPair(pathBackendHealthCheckPort, "80"), withPair(pathBackendHealthCheckInterval, "30s"), + withPair(pathBackendHealthCheckTimeout, "5s"), withPair(pathBackendHealthCheckHostname, "foo.com"), withPair(pathBackendHealthCheckHeaders+"Foo", "bar"), withPair(pathBackendHealthCheckHeaders+"Bar", "foo"), @@ -387,6 +388,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Path: "/health", Port: 80, Interval: "30s", + Timeout: "5s", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", @@ -1986,9 +1988,12 @@ func TestProviderGetHealthCheck(t *testing.T) { backend("foo", withPair(pathBackendHealthCheckPath, "/health"), withPair(pathBackendHealthCheckPort, "80"), - withPair(pathBackendHealthCheckInterval, "10s"))), + withPair(pathBackendHealthCheckInterval, "10s"), + withPair(pathBackendHealthCheckTimeout, "3s"))), + expected: &types.HealthCheck{ Interval: "10s", + Timeout: "3s", Path: "/health", Port: 80, }, @@ -2001,6 +2006,7 @@ func TestProviderGetHealthCheck(t *testing.T) { withPair(pathBackendHealthCheckPath, "/health"))), expected: &types.HealthCheck{ Interval: "30s", + Timeout: "5s", Path: "/health", Port: 0, }, @@ -2011,7 +2017,8 @@ func TestProviderGetHealthCheck(t *testing.T) { kvPairs: filler("traefik", backend("foo", withPair(pathBackendHealthCheckPort, "80"), - withPair(pathBackendHealthCheckInterval, "30s"))), + withPair(pathBackendHealthCheckInterval, "30s"), + withPair(pathBackendHealthCheckTimeout, "5s"))), expected: nil, }, } diff --git a/provider/label/names.go b/provider/label/names.go index 1062a8917..bc659ddda 100644 --- a/provider/label/names.go +++ b/provider/label/names.go @@ -19,6 +19,7 @@ const ( SuffixBackendHealthCheckPath = "backend.healthcheck.path" SuffixBackendHealthCheckPort = "backend.healthcheck.port" SuffixBackendHealthCheckInterval = "backend.healthcheck.interval" + SuffixBackendHealthCheckTimeout = "backend.healthcheck.timeout" SuffixBackendHealthCheckHostname = "backend.healthcheck.hostname" SuffixBackendHealthCheckHeaders = "backend.healthcheck.headers" SuffixBackendLoadBalancer = "backend.loadbalancer" @@ -120,6 +121,7 @@ const ( TraefikBackendHealthCheckPath = Prefix + SuffixBackendHealthCheckPath TraefikBackendHealthCheckPort = Prefix + SuffixBackendHealthCheckPort TraefikBackendHealthCheckInterval = Prefix + SuffixBackendHealthCheckInterval + TraefikBackendHealthCheckTimeout = Prefix + SuffixBackendHealthCheckTimeout TraefikBackendHealthCheckHostname = Prefix + SuffixBackendHealthCheckHostname TraefikBackendHealthCheckHeaders = Prefix + SuffixBackendHealthCheckHeaders TraefikBackendLoadBalancer = Prefix + SuffixBackendLoadBalancer diff --git a/provider/label/partial.go b/provider/label/partial.go index 0b98c6703..c02c49146 100644 --- a/provider/label/partial.go +++ b/provider/label/partial.go @@ -342,6 +342,7 @@ func GetHealthCheck(labels map[string]string) *types.HealthCheck { scheme := GetStringValue(labels, TraefikBackendHealthCheckScheme, "") port := GetIntValue(labels, TraefikBackendHealthCheckPort, DefaultBackendHealthCheckPort) interval := GetStringValue(labels, TraefikBackendHealthCheckInterval, "") + timeout := GetStringValue(labels, TraefikBackendHealthCheckTimeout, "") hostname := GetStringValue(labels, TraefikBackendHealthCheckHostname, "") headers := GetMapValue(labels, TraefikBackendHealthCheckHeaders) @@ -350,6 +351,7 @@ func GetHealthCheck(labels map[string]string) *types.HealthCheck { Path: path, Port: port, Interval: interval, + Timeout: timeout, Hostname: hostname, Headers: headers, } diff --git a/provider/label/partial_test.go b/provider/label/partial_test.go index 836903836..abfd81715 100644 --- a/provider/label/partial_test.go +++ b/provider/label/partial_test.go @@ -379,6 +379,7 @@ func TestGetHealthCheck(t *testing.T) { labels: map[string]string{ TraefikBackendHealthCheckPort: "80", TraefikBackendHealthCheckInterval: "6", + TraefikBackendHealthCheckTimeout: "3", }, expected: nil, }, @@ -388,6 +389,7 @@ func TestGetHealthCheck(t *testing.T) { TraefikBackendHealthCheckPath: "/health", TraefikBackendHealthCheckPort: "80", TraefikBackendHealthCheckInterval: "6", + TraefikBackendHealthCheckTimeout: "3", TraefikBackendHealthCheckHeaders: "Foo:bar || Goo:bir", TraefikBackendHealthCheckHostname: "traefik", TraefikBackendHealthCheckScheme: "http", @@ -397,6 +399,7 @@ func TestGetHealthCheck(t *testing.T) { Path: "/health", Port: 80, Interval: "6", + Timeout: "3", Hostname: "traefik", Headers: map[string]string{ "Foo": "bar", diff --git a/provider/marathon/config_test.go b/provider/marathon/config_test.go index f38bc7bb7..d0cfe5f62 100644 --- a/provider/marathon/config_test.go +++ b/provider/marathon/config_test.go @@ -359,6 +359,7 @@ func TestBuildConfiguration(t *testing.T) { withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckInterval, "6"), + withLabel(label.TraefikBackendHealthCheckTimeout, "3"), withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"), withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"), @@ -603,6 +604,7 @@ func TestBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", @@ -779,6 +781,7 @@ func TestBuildConfigurationSegments(t *testing.T) { withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckInterval, "6"), + withLabel(label.TraefikBackendHealthCheckTimeout, "3"), withLabel(label.TraefikBackendLoadBalancerMethod, "drr"), withLabel(label.TraefikBackendLoadBalancerStickiness, "true"), withLabel(label.TraefikBackendLoadBalancerStickinessCookieName, "chocolate"), @@ -1017,6 +1020,7 @@ func TestBuildConfigurationSegments(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", }, Buffering: &types.Buffering{ MaxResponseBodyBytes: 10485760, diff --git a/provider/mesos/config_test.go b/provider/mesos/config_test.go index f0c6a8acb..3431d8675 100644 --- a/provider/mesos/config_test.go +++ b/provider/mesos/config_test.go @@ -316,6 +316,7 @@ func TestBuildConfiguration(t *testing.T) { withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckInterval, "6"), + withLabel(label.TraefikBackendHealthCheckTimeout, "3"), withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"), withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"), @@ -563,6 +564,7 @@ func TestBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", @@ -696,6 +698,7 @@ func TestBuildConfigurationSegments(t *testing.T) { withLabel(label.TraefikBackendHealthCheckPath, "/health"), withLabel(label.TraefikBackendHealthCheckPort, "880"), withLabel(label.TraefikBackendHealthCheckInterval, "6"), + withLabel(label.TraefikBackendHealthCheckTimeout, "3"), withLabel(label.TraefikBackendHealthCheckHostname, "foo.com"), withLabel(label.TraefikBackendHealthCheckHeaders, "Foo:bar || Bar:foo"), withLabel(label.TraefikBackendLoadBalancerMethod, "drr"), @@ -940,6 +943,7 @@ func TestBuildConfigurationSegments(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Bar": "foo", diff --git a/provider/rancher/config_test.go b/provider/rancher/config_test.go index b0049efb9..4cf393ae1 100644 --- a/provider/rancher/config_test.go +++ b/provider/rancher/config_test.go @@ -45,6 +45,7 @@ func TestProviderBuildConfiguration(t *testing.T) { label.TraefikBackendHealthCheckPath: "/health", label.TraefikBackendHealthCheckPort: "880", label.TraefikBackendHealthCheckInterval: "6", + label.TraefikBackendHealthCheckTimeout: "3", label.TraefikBackendHealthCheckHostname: "foo.com", label.TraefikBackendHealthCheckHeaders: "Foo:bar || Bar:foo", label.TraefikBackendLoadBalancerMethod: "drr", @@ -295,6 +296,7 @@ func TestProviderBuildConfiguration(t *testing.T) { Path: "/health", Port: 880, Interval: "6", + Timeout: "3", Hostname: "foo.com", Headers: map[string]string{ "Foo": "bar", diff --git a/server/server_configuration_test.go b/server/server_configuration_test.go index 909a70fd5..319e9a95d 100644 --- a/server/server_configuration_test.go +++ b/server/server_configuration_test.go @@ -90,7 +90,10 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) { for _, healthCheck := range healthChecks { t.Run(fmt.Sprintf("%s/hc=%t", lbMethod, healthCheck != nil), func(t *testing.T) { globalConfig := configuration.GlobalConfiguration{ - HealthCheck: &configuration.HealthCheckConfig{Interval: parse.Duration(5 * time.Second)}, + HealthCheck: &configuration.HealthCheckConfig{ + Interval: parse.Duration(5 * time.Second), + Timeout: parse.Duration(3 * time.Second), + }, } entryPoints := map[string]EntryPoint{ "http": { @@ -424,6 +427,7 @@ func TestServerMultipleFrontendRules(t *testing.T) { func TestServerBuildHealthCheckOptions(t *testing.T) { lb := &testLoadBalancer{} globalInterval := 15 * time.Second + globalTimeout := 3 * time.Second testCases := []struct { desc string @@ -452,6 +456,7 @@ func TestServerBuildHealthCheckOptions(t *testing.T) { Path: "/path", Interval: globalInterval, LB: lb, + Timeout: 3 * time.Second, }, }, { @@ -464,6 +469,7 @@ func TestServerBuildHealthCheckOptions(t *testing.T) { Path: "/path", Interval: globalInterval, LB: lb, + Timeout: 3 * time.Second, }, }, { @@ -476,6 +482,49 @@ func TestServerBuildHealthCheckOptions(t *testing.T) { Path: "/path", Interval: 5 * time.Minute, LB: lb, + Timeout: 3 * time.Second, + }, + }, + { + desc: "unparseable timeout", + hc: &types.HealthCheck{ + Path: "/path", + Interval: "15s", + Timeout: "unparseable", + }, + expectedOpts: &healthcheck.Options{ + Path: "/path", + Interval: globalInterval, + Timeout: globalTimeout, + LB: lb, + }, + }, + { + desc: "sub-zero timeout", + hc: &types.HealthCheck{ + Path: "/path", + Interval: "15s", + Timeout: "-42s", + }, + expectedOpts: &healthcheck.Options{ + Path: "/path", + Interval: globalInterval, + Timeout: globalTimeout, + LB: lb, + }, + }, + { + desc: "parseable timeout", + hc: &types.HealthCheck{ + Path: "/path", + Interval: "15s", + Timeout: "10s", + }, + expectedOpts: &healthcheck.Options{ + Path: "/path", + Interval: globalInterval, + Timeout: 10 * time.Second, + LB: lb, }, }, } @@ -485,7 +534,10 @@ func TestServerBuildHealthCheckOptions(t *testing.T) { t.Run(test.desc, func(t *testing.T) { t.Parallel() - opts := buildHealthCheckOptions(lb, "backend", test.hc, &configuration.HealthCheckConfig{Interval: parse.Duration(globalInterval)}) + opts := buildHealthCheckOptions(lb, "backend", test.hc, &configuration.HealthCheckConfig{ + Interval: parse.Duration(globalInterval), + Timeout: parse.Duration(globalTimeout), + }) assert.Equal(t, test.expectedOpts, opts, "health check options") }) } diff --git a/server/server_loadbalancer.go b/server/server_loadbalancer.go index a6f41a47e..164155a24 100644 --- a/server/server_loadbalancer.go +++ b/server/server_loadbalancer.go @@ -409,11 +409,28 @@ func buildHealthCheckOptions(lb healthcheck.BalancerHandler, backend string, hc } } + timeout := time.Duration(hcConfig.Timeout) + if hc.Timeout != "" { + timeoutOverride, err := time.ParseDuration(hc.Timeout) + if err != nil { + log.Errorf("Illegal health check timeout for backend '%s': %s", backend, err) + } else if timeoutOverride <= 0 { + log.Errorf("Health check timeout smaller than zero for backend '%s', backend", backend) + } else { + timeout = timeoutOverride + } + } + + if timeout >= interval { + log.Warnf("Health check timeout for backend '%s' should be lower than the health check interval. Interval set to timeout + 1 second (%s).", backend) + } + return &healthcheck.Options{ Scheme: hc.Scheme, Path: hc.Path, Port: hc.Port, Interval: interval, + Timeout: timeout, LB: lb, Hostname: hc.Hostname, Headers: hc.Headers, diff --git a/templates/consul_catalog.tmpl b/templates/consul_catalog.tmpl index 7d8964e27..7f11887c8 100644 --- a/templates/consul_catalog.tmpl +++ b/templates/consul_catalog.tmpl @@ -32,6 +32,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] diff --git a/templates/docker.tmpl b/templates/docker.tmpl index 09ac62f0b..43890012e 100644 --- a/templates/docker.tmpl +++ b/templates/docker.tmpl @@ -33,6 +33,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] diff --git a/templates/ecs.tmpl b/templates/ecs.tmpl index d66dbb623..6c485e612 100644 --- a/templates/ecs.tmpl +++ b/templates/ecs.tmpl @@ -32,6 +32,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $serviceName }}".healthCheck.headers] diff --git a/templates/kv.tmpl b/templates/kv.tmpl index d063cec24..1904b16fe 100644 --- a/templates/kv.tmpl +++ b/templates/kv.tmpl @@ -32,6 +32,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."{{ $backendName }}".healthCheck.headers] diff --git a/templates/marathon.tmpl b/templates/marathon.tmpl index 1ecfcc206..c36b20a35 100644 --- a/templates/marathon.tmpl +++ b/templates/marathon.tmpl @@ -35,6 +35,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends.{{ $backendName }}.healthCheck.headers] diff --git a/templates/mesos.tmpl b/templates/mesos.tmpl index b8c9dabcc..04a9cef79 100644 --- a/templates/mesos.tmpl +++ b/templates/mesos.tmpl @@ -35,6 +35,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] diff --git a/templates/rancher.tmpl b/templates/rancher.tmpl index 9d0ef07f0..0749d93e1 100644 --- a/templates/rancher.tmpl +++ b/templates/rancher.tmpl @@ -34,6 +34,7 @@ path = "{{ $healthCheck.Path }}" port = {{ $healthCheck.Port }} interval = "{{ $healthCheck.Interval }}" + timeout = "{{ $healthCheck.Timeout }}" hostname = "{{ $healthCheck.Hostname }}" {{if $healthCheck.Headers }} [backends."backend-{{ $backendName }}".healthCheck.headers] diff --git a/types/types.go b/types/types.go index c8158c893..77cf04413 100644 --- a/types/types.go +++ b/types/types.go @@ -74,6 +74,7 @@ type HealthCheck struct { Path string `json:"path,omitempty"` Port int `json:"port,omitempty"` Interval string `json:"interval,omitempty"` + Timeout string `json:"timeout,omitempty"` Hostname string `json:"hostname,omitempty"` Headers map[string]string `json:"headers,omitempty"` } diff --git a/webui/src/app/components/providers/providers.component.html b/webui/src/app/components/providers/providers.component.html index 72fa96973..358b82a33 100644 --- a/webui/src/app/components/providers/providers.component.html +++ b/webui/src/app/components/providers/providers.component.html @@ -632,6 +632,12 @@ {{ p.healthCheck.interval }} +
+
+ Timeout + {{ p.healthCheck.timeout }} +
+
Port