Add global health check interval parameter.
The new parameter allows to set a health check interval valid for all backends. Custom values set per provider may override the global one.
This commit is contained in:
parent
ce492895e2
commit
25345427c3
6 changed files with 71 additions and 12 deletions
21
docs/toml.md
21
docs/toml.md
|
@ -269,6 +269,27 @@ Supported filters:
|
||||||
# attempts = 3
|
# attempts = 3
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Health check configuration
|
||||||
|
```toml
|
||||||
|
# Enable custom health check options.
|
||||||
|
#
|
||||||
|
# Optional
|
||||||
|
#
|
||||||
|
[healthcheck]
|
||||||
|
|
||||||
|
# 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). If no units are provided, the value is parsed assuming
|
||||||
|
# seconds.
|
||||||
|
#
|
||||||
|
# Optional
|
||||||
|
# Default: "30s"
|
||||||
|
#
|
||||||
|
# interval = "30s"
|
||||||
|
```
|
||||||
|
|
||||||
## ACME (Let's Encrypt) configuration
|
## ACME (Let's Encrypt) configuration
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
|
|
|
@ -2,6 +2,7 @@ package healthcheck
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -12,9 +13,6 @@ import (
|
||||||
"github.com/vulcand/oxy/roundrobin"
|
"github.com/vulcand/oxy/roundrobin"
|
||||||
)
|
)
|
||||||
|
|
||||||
// DefaultInterval is the default health check interval.
|
|
||||||
const DefaultInterval = 30 * time.Second
|
|
||||||
|
|
||||||
var singleton *HealthCheck
|
var singleton *HealthCheck
|
||||||
var once sync.Once
|
var once sync.Once
|
||||||
|
|
||||||
|
@ -33,6 +31,10 @@ type Options struct {
|
||||||
LB LoadBalancer
|
LB LoadBalancer
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (opt Options) String() string {
|
||||||
|
return fmt.Sprintf("[Path: %s Interval: %s]", opt.Path, opt.Interval)
|
||||||
|
}
|
||||||
|
|
||||||
// BackendHealthCheck HealthCheck configuration for a backend
|
// BackendHealthCheck HealthCheck configuration for a backend
|
||||||
type BackendHealthCheck struct {
|
type BackendHealthCheck struct {
|
||||||
Options
|
Options
|
||||||
|
|
|
@ -27,6 +27,9 @@ import (
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// DefaultHealthCheckInterval is the default health check interval.
|
||||||
|
const DefaultHealthCheckInterval = 30 * time.Second
|
||||||
|
|
||||||
// TraefikConfiguration holds GlobalConfiguration and other stuff
|
// TraefikConfiguration holds GlobalConfiguration and other stuff
|
||||||
type TraefikConfiguration struct {
|
type TraefikConfiguration struct {
|
||||||
GlobalConfiguration `mapstructure:",squash"`
|
GlobalConfiguration `mapstructure:",squash"`
|
||||||
|
@ -52,6 +55,7 @@ type GlobalConfiguration struct {
|
||||||
IdleTimeout flaeg.Duration `description:"maximum amount of time an idle (keep-alive) connection will remain idle before closing itself."`
|
IdleTimeout flaeg.Duration `description:"maximum amount of time an idle (keep-alive) connection will remain idle before closing itself."`
|
||||||
InsecureSkipVerify bool `description:"Disable SSL certificate verification"`
|
InsecureSkipVerify bool `description:"Disable SSL certificate verification"`
|
||||||
Retry *Retry `description:"Enable retry sending request if network error"`
|
Retry *Retry `description:"Enable retry sending request if network error"`
|
||||||
|
HealthCheck *HealthCheckConfig `description:"Health check parameters"`
|
||||||
Docker *docker.Provider `description:"Enable Docker backend"`
|
Docker *docker.Provider `description:"Enable Docker backend"`
|
||||||
File *file.Provider `description:"Enable File backend"`
|
File *file.Provider `description:"Enable File backend"`
|
||||||
Web *WebProvider `description:"Enable Web backend"`
|
Web *WebProvider `description:"Enable Web backend"`
|
||||||
|
@ -337,6 +341,11 @@ type Retry struct {
|
||||||
Attempts int `description:"Number of attempts"`
|
Attempts int `description:"Number of attempts"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// HealthCheckConfig contains health check configuration parameters.
|
||||||
|
type HealthCheckConfig struct {
|
||||||
|
Interval flaeg.Duration `description:"Default periodicity of enabled health checks"`
|
||||||
|
}
|
||||||
|
|
||||||
// NewTraefikDefaultPointersConfiguration creates a TraefikConfiguration with pointers default values
|
// NewTraefikDefaultPointersConfiguration creates a TraefikConfiguration with pointers default values
|
||||||
func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
|
func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
|
||||||
//default Docker
|
//default Docker
|
||||||
|
@ -461,6 +470,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
|
||||||
Rancher: &defaultRancher,
|
Rancher: &defaultRancher,
|
||||||
DynamoDB: &defaultDynamoDB,
|
DynamoDB: &defaultDynamoDB,
|
||||||
Retry: &Retry{},
|
Retry: &Retry{},
|
||||||
|
HealthCheck: &HealthCheckConfig{},
|
||||||
}
|
}
|
||||||
|
|
||||||
//default Rancher
|
//default Rancher
|
||||||
|
@ -485,7 +495,10 @@ func NewTraefikConfiguration() *TraefikConfiguration {
|
||||||
ProvidersThrottleDuration: flaeg.Duration(2 * time.Second),
|
ProvidersThrottleDuration: flaeg.Duration(2 * time.Second),
|
||||||
MaxIdleConnsPerHost: 200,
|
MaxIdleConnsPerHost: 200,
|
||||||
IdleTimeout: flaeg.Duration(180 * time.Second),
|
IdleTimeout: flaeg.Duration(180 * time.Second),
|
||||||
CheckNewVersion: true,
|
HealthCheck: &HealthCheckConfig{
|
||||||
|
Interval: flaeg.Duration(DefaultHealthCheckInterval),
|
||||||
|
},
|
||||||
|
CheckNewVersion: true,
|
||||||
},
|
},
|
||||||
ConfigFile: "",
|
ConfigFile: "",
|
||||||
}
|
}
|
||||||
|
|
|
@ -659,8 +659,9 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
|
||||||
log.Errorf("Skipping frontend %s...", frontendName)
|
log.Errorf("Skipping frontend %s...", frontendName)
|
||||||
continue frontend
|
continue frontend
|
||||||
}
|
}
|
||||||
hcOpts := parseHealthCheckOptions(rebalancer, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck)
|
hcOpts := parseHealthCheckOptions(rebalancer, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, *globalConfiguration.HealthCheck)
|
||||||
if hcOpts != nil {
|
if hcOpts != nil {
|
||||||
|
log.Debugf("Setting up backend health check %s", *hcOpts)
|
||||||
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -685,8 +686,9 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
|
||||||
continue frontend
|
continue frontend
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
hcOpts := parseHealthCheckOptions(rr, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck)
|
hcOpts := parseHealthCheckOptions(rr, frontend.Backend, configuration.Backends[frontend.Backend].HealthCheck, *globalConfiguration.HealthCheck)
|
||||||
if hcOpts != nil {
|
if hcOpts != nil {
|
||||||
|
log.Debugf("Setting up backend health check %s", *hcOpts)
|
||||||
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -847,12 +849,12 @@ func (server *Server) buildDefaultHTTPRouter() *mux.Router {
|
||||||
return router
|
return router
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseHealthCheckOptions(lb healthcheck.LoadBalancer, backend string, hc *types.HealthCheck) *healthcheck.Options {
|
func parseHealthCheckOptions(lb healthcheck.LoadBalancer, backend string, hc *types.HealthCheck, hcConfig HealthCheckConfig) *healthcheck.Options {
|
||||||
if hc == nil || hc.Path == "" {
|
if hc == nil || hc.Path == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
interval := healthcheck.DefaultInterval
|
interval := time.Duration(hcConfig.Interval)
|
||||||
if hc.Interval != "" {
|
if hc.Interval != "" {
|
||||||
intervalOverride, err := time.ParseDuration(hc.Interval)
|
intervalOverride, err := time.ParseDuration(hc.Interval)
|
||||||
switch {
|
switch {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/containous/flaeg"
|
||||||
"github.com/containous/traefik/healthcheck"
|
"github.com/containous/traefik/healthcheck"
|
||||||
"github.com/containous/traefik/types"
|
"github.com/containous/traefik/types"
|
||||||
"github.com/vulcand/oxy/roundrobin"
|
"github.com/vulcand/oxy/roundrobin"
|
||||||
|
@ -41,6 +42,7 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) {
|
||||||
EntryPoints: EntryPoints{
|
EntryPoints: EntryPoints{
|
||||||
"http": &EntryPoint{},
|
"http": &EntryPoint{},
|
||||||
},
|
},
|
||||||
|
HealthCheck: &HealthCheckConfig{Interval: flaeg.Duration(5 * time.Second)},
|
||||||
}
|
}
|
||||||
|
|
||||||
dynamicConfigs := configs{
|
dynamicConfigs := configs{
|
||||||
|
@ -87,6 +89,7 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) {
|
||||||
|
|
||||||
func TestServerParseHealthCheckOptions(t *testing.T) {
|
func TestServerParseHealthCheckOptions(t *testing.T) {
|
||||||
lb := &testLoadBalancer{}
|
lb := &testLoadBalancer{}
|
||||||
|
globalInterval := 15 * time.Second
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
desc string
|
desc string
|
||||||
|
@ -113,7 +116,7 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
|
||||||
},
|
},
|
||||||
wantOpts: &healthcheck.Options{
|
wantOpts: &healthcheck.Options{
|
||||||
Path: "/path",
|
Path: "/path",
|
||||||
Interval: healthcheck.DefaultInterval,
|
Interval: globalInterval,
|
||||||
LB: lb,
|
LB: lb,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -121,11 +124,11 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
|
||||||
desc: "sub-zero interval",
|
desc: "sub-zero interval",
|
||||||
hc: &types.HealthCheck{
|
hc: &types.HealthCheck{
|
||||||
Path: "/path",
|
Path: "/path",
|
||||||
Interval: "-15s",
|
Interval: "-42s",
|
||||||
},
|
},
|
||||||
wantOpts: &healthcheck.Options{
|
wantOpts: &healthcheck.Options{
|
||||||
Path: "/path",
|
Path: "/path",
|
||||||
Interval: healthcheck.DefaultInterval,
|
Interval: globalInterval,
|
||||||
LB: lb,
|
LB: lb,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
@ -148,7 +151,7 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
|
||||||
t.Run(test.desc, func(t *testing.T) {
|
t.Run(test.desc, func(t *testing.T) {
|
||||||
t.Parallel()
|
t.Parallel()
|
||||||
|
|
||||||
gotOpts := parseHealthCheckOptions(lb, "backend", test.hc)
|
gotOpts := parseHealthCheckOptions(lb, "backend", test.hc, HealthCheckConfig{Interval: flaeg.Duration(globalInterval)})
|
||||||
if !reflect.DeepEqual(gotOpts, test.wantOpts) {
|
if !reflect.DeepEqual(gotOpts, test.wantOpts) {
|
||||||
t.Errorf("got health check options %+v, want %+v", gotOpts, test.wantOpts)
|
t.Errorf("got health check options %+v, want %+v", gotOpts, test.wantOpts)
|
||||||
}
|
}
|
||||||
|
|
|
@ -311,6 +311,24 @@
|
||||||
#
|
#
|
||||||
# attempts = 3
|
# attempts = 3
|
||||||
|
|
||||||
|
# Enable custom health check options.
|
||||||
|
#
|
||||||
|
# Optional
|
||||||
|
#
|
||||||
|
# [healthcheck]
|
||||||
|
|
||||||
|
# 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 Go's time.ParseDuration function or
|
||||||
|
# as raw values (digits). If no units are provided, the value is parsed assuming
|
||||||
|
# seconds.
|
||||||
|
#
|
||||||
|
# Optional
|
||||||
|
# Default: "30s"
|
||||||
|
#
|
||||||
|
# interval = "30s"
|
||||||
|
|
||||||
################################################################
|
################################################################
|
||||||
# Web configuration backend
|
# Web configuration backend
|
||||||
################################################################
|
################################################################
|
||||||
|
|
Loading…
Reference in a new issue