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:
Timo Reimann 2017-03-24 09:36:33 +01:00
parent ce492895e2
commit 25345427c3
6 changed files with 71 additions and 12 deletions

View file

@ -269,6 +269,27 @@ Supported filters:
# 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
```toml

View file

@ -2,6 +2,7 @@ package healthcheck
import (
"context"
"fmt"
"net/http"
"net/url"
"sync"
@ -12,9 +13,6 @@ import (
"github.com/vulcand/oxy/roundrobin"
)
// DefaultInterval is the default health check interval.
const DefaultInterval = 30 * time.Second
var singleton *HealthCheck
var once sync.Once
@ -33,6 +31,10 @@ type Options struct {
LB LoadBalancer
}
func (opt Options) String() string {
return fmt.Sprintf("[Path: %s Interval: %s]", opt.Path, opt.Interval)
}
// BackendHealthCheck HealthCheck configuration for a backend
type BackendHealthCheck struct {
Options

View file

@ -27,6 +27,9 @@ import (
"github.com/containous/traefik/types"
)
// DefaultHealthCheckInterval is the default health check interval.
const DefaultHealthCheckInterval = 30 * time.Second
// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
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."`
InsecureSkipVerify bool `description:"Disable SSL certificate verification"`
Retry *Retry `description:"Enable retry sending request if network error"`
HealthCheck *HealthCheckConfig `description:"Health check parameters"`
Docker *docker.Provider `description:"Enable Docker backend"`
File *file.Provider `description:"Enable File backend"`
Web *WebProvider `description:"Enable Web backend"`
@ -337,6 +341,11 @@ type Retry struct {
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
func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
//default Docker
@ -461,6 +470,7 @@ func NewTraefikDefaultPointersConfiguration() *TraefikConfiguration {
Rancher: &defaultRancher,
DynamoDB: &defaultDynamoDB,
Retry: &Retry{},
HealthCheck: &HealthCheckConfig{},
}
//default Rancher
@ -485,7 +495,10 @@ func NewTraefikConfiguration() *TraefikConfiguration {
ProvidersThrottleDuration: flaeg.Duration(2 * time.Second),
MaxIdleConnsPerHost: 200,
IdleTimeout: flaeg.Duration(180 * time.Second),
CheckNewVersion: true,
HealthCheck: &HealthCheckConfig{
Interval: flaeg.Duration(DefaultHealthCheckInterval),
},
CheckNewVersion: true,
},
ConfigFile: "",
}

View file

@ -659,8 +659,9 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
log.Errorf("Skipping frontend %s...", frontendName)
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 {
log.Debugf("Setting up backend health check %s", *hcOpts)
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
}
}
@ -685,8 +686,9 @@ func (server *Server) loadConfig(configurations configs, globalConfiguration Glo
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 {
log.Debugf("Setting up backend health check %s", *hcOpts)
backendsHealthcheck[frontend.Backend] = healthcheck.NewBackendHealthCheck(*hcOpts)
}
}
@ -847,12 +849,12 @@ func (server *Server) buildDefaultHTTPRouter() *mux.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 == "" {
return nil
}
interval := healthcheck.DefaultInterval
interval := time.Duration(hcConfig.Interval)
if hc.Interval != "" {
intervalOverride, err := time.ParseDuration(hc.Interval)
switch {

View file

@ -7,6 +7,7 @@ import (
"testing"
"time"
"github.com/containous/flaeg"
"github.com/containous/traefik/healthcheck"
"github.com/containous/traefik/types"
"github.com/vulcand/oxy/roundrobin"
@ -41,6 +42,7 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) {
EntryPoints: EntryPoints{
"http": &EntryPoint{},
},
HealthCheck: &HealthCheckConfig{Interval: flaeg.Duration(5 * time.Second)},
}
dynamicConfigs := configs{
@ -87,6 +89,7 @@ func TestServerLoadConfigHealthCheckOptions(t *testing.T) {
func TestServerParseHealthCheckOptions(t *testing.T) {
lb := &testLoadBalancer{}
globalInterval := 15 * time.Second
tests := []struct {
desc string
@ -113,7 +116,7 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
},
wantOpts: &healthcheck.Options{
Path: "/path",
Interval: healthcheck.DefaultInterval,
Interval: globalInterval,
LB: lb,
},
},
@ -121,11 +124,11 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
desc: "sub-zero interval",
hc: &types.HealthCheck{
Path: "/path",
Interval: "-15s",
Interval: "-42s",
},
wantOpts: &healthcheck.Options{
Path: "/path",
Interval: healthcheck.DefaultInterval,
Interval: globalInterval,
LB: lb,
},
},
@ -148,7 +151,7 @@ func TestServerParseHealthCheckOptions(t *testing.T) {
t.Run(test.desc, func(t *testing.T) {
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) {
t.Errorf("got health check options %+v, want %+v", gotOpts, test.wantOpts)
}

View file

@ -311,6 +311,24 @@
#
# 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
################################################################