Skip to content

Commit

Permalink
Add internal provider
Browse files Browse the repository at this point in the history
Co-authored-by: Julien Salleyron <julien.salleyron@gmail.com>
  • Loading branch information
2 people authored and traefiker committed Nov 14, 2019
1 parent 2ee2e29 commit 424e2a9
Show file tree
Hide file tree
Showing 71 changed files with 2,522 additions and 1,468 deletions.
192 changes: 153 additions & 39 deletions cmd/traefik/traefik.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package main
import (
"context"
"encoding/json"
"fmt"
stdlog "log"
"net/http"
"os"
Expand All @@ -20,12 +19,17 @@ import (
"github.com/containous/traefik/v2/pkg/config/dynamic"
"github.com/containous/traefik/v2/pkg/config/static"
"github.com/containous/traefik/v2/pkg/log"
"github.com/containous/traefik/v2/pkg/metrics"
"github.com/containous/traefik/v2/pkg/middlewares/accesslog"
"github.com/containous/traefik/v2/pkg/provider/acme"
"github.com/containous/traefik/v2/pkg/provider/aggregator"
"github.com/containous/traefik/v2/pkg/provider/traefik"
"github.com/containous/traefik/v2/pkg/safe"
"github.com/containous/traefik/v2/pkg/server"
"github.com/containous/traefik/v2/pkg/server/router"
"github.com/containous/traefik/v2/pkg/server/middleware"
"github.com/containous/traefik/v2/pkg/server/service"
traefiktls "github.com/containous/traefik/v2/pkg/tls"
"github.com/containous/traefik/v2/pkg/types"
"github.com/containous/traefik/v2/pkg/version"
"github.com/coreos/go-systemd/daemon"
assetfs "github.com/elazarl/go-bindata-assetfs"
Expand Down Expand Up @@ -77,7 +81,7 @@ func runCmd(staticConfiguration *static.Configuration) error {
http.DefaultTransport.(*http.Transport).Proxy = http.ProxyFromEnvironment

if err := roundrobin.SetDefaultWeight(0); err != nil {
log.WithoutContext().Errorf("Could not set roundrobin default weight: %v", err)
log.WithoutContext().Errorf("Could not set round robin default weight: %v", err)
}

staticConfiguration.SetEffectiveConfiguration()
Expand Down Expand Up @@ -105,43 +109,11 @@ func runCmd(staticConfiguration *static.Configuration) error {

stats(staticConfiguration)

providerAggregator := aggregator.NewProviderAggregator(*staticConfiguration.Providers)

tlsManager := traefiktls.NewManager()

acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager)

serverEntryPointsTCP := make(server.TCPEntryPoints)
for entryPointName, config := range staticConfiguration.EntryPoints {
ctx := log.With(context.Background(), log.Str(log.EntryPointName, entryPointName))
serverEntryPointsTCP[entryPointName], err = server.NewTCPEntryPoint(ctx, config)
if err != nil {
return fmt.Errorf("error while building entryPoint %s: %v", entryPointName, err)
}
serverEntryPointsTCP[entryPointName].RouteAppenderFactory = router.NewRouteAppenderFactory(*staticConfiguration, entryPointName, acmeProviders)
}

svr := server.NewServer(*staticConfiguration, providerAggregator, serverEntryPointsTCP, tlsManager)

resolverNames := map[string]struct{}{}

for _, p := range acmeProviders {
resolverNames[p.ResolverName] = struct{}{}
svr.AddListener(p.ListenConfiguration)
svr, err := setupServer(staticConfiguration)
if err != nil {
return err
}

svr.AddListener(func(config dynamic.Configuration) {
for rtName, rt := range config.HTTP.Routers {
if rt.TLS == nil || rt.TLS.CertResolver == "" {
continue
}

if _, ok := resolverNames[rt.TLS.CertResolver]; !ok {
log.WithoutContext().Errorf("the router %s uses a non-existent resolver: %s", rtName, rt.TLS.CertResolver)
}
}
})

ctx := cmd.ContextWithSignal(context.Background())

if staticConfiguration.Ping != nil {
Expand All @@ -168,7 +140,7 @@ func runCmd(staticConfiguration *static.Configuration) error {
for range tick {
resp, errHealthCheck := healthcheck.Do(*staticConfiguration)
if resp != nil {
resp.Body.Close()
_ = resp.Body.Close()
}

if staticConfiguration.Ping == nil || errHealthCheck == nil {
Expand All @@ -188,6 +160,94 @@ func runCmd(staticConfiguration *static.Configuration) error {
return nil
}

func setupServer(staticConfiguration *static.Configuration) (*server.Server, error) {
providerAggregator := aggregator.NewProviderAggregator(*staticConfiguration.Providers)

// adds internal provider
err := providerAggregator.AddProvider(traefik.New(*staticConfiguration))
if err != nil {
return nil, err
}

tlsManager := traefiktls.NewManager()

acmeProviders := initACMEProvider(staticConfiguration, &providerAggregator, tlsManager)

serverEntryPointsTCP, err := server.NewTCPEntryPoints(*staticConfiguration)
if err != nil {
return nil, err
}

ctx := context.Background()
routinesPool := safe.NewPool(ctx)

metricsRegistry := registerMetricClients(staticConfiguration.Metrics)
accessLog := setupAccessLog(staticConfiguration.AccessLog)
chainBuilder := middleware.NewChainBuilder(*staticConfiguration, metricsRegistry, accessLog)
managerFactory := service.NewManagerFactory(*staticConfiguration, routinesPool, metricsRegistry)
tcpRouterFactory := server.NewTCPRouterFactory(*staticConfiguration, managerFactory, tlsManager, chainBuilder)

watcher := server.NewConfigurationWatcher(routinesPool, providerAggregator, time.Duration(staticConfiguration.Providers.ProvidersThrottleDuration))

watcher.AddListener(func(conf dynamic.Configuration) {
ctx := context.Background()
tlsManager.UpdateConfigs(ctx, conf.TLS.Stores, conf.TLS.Options, conf.TLS.Certificates)
})

watcher.AddListener(func(_ dynamic.Configuration) {
metricsRegistry.ConfigReloadsCounter().Add(1)
metricsRegistry.LastConfigReloadSuccessGauge().Set(float64(time.Now().Unix()))
})

watcher.AddListener(switchRouter(tcpRouterFactory, acmeProviders, serverEntryPointsTCP))

watcher.AddListener(func(conf dynamic.Configuration) {
if metricsRegistry.IsEpEnabled() || metricsRegistry.IsSvcEnabled() {
var eps []string
for key := range serverEntryPointsTCP {
eps = append(eps, key)
}

metrics.OnConfigurationUpdate(conf, eps)
}
})

resolverNames := map[string]struct{}{}
for _, p := range acmeProviders {
resolverNames[p.ResolverName] = struct{}{}
watcher.AddListener(p.ListenConfiguration)
}

watcher.AddListener(func(config dynamic.Configuration) {
for rtName, rt := range config.HTTP.Routers {
if rt.TLS == nil || rt.TLS.CertResolver == "" {
continue
}

if _, ok := resolverNames[rt.TLS.CertResolver]; !ok {
log.WithoutContext().Errorf("the router %s uses a non-existent resolver: %s", rtName, rt.TLS.CertResolver)
}
}
})

return server.NewServer(routinesPool, serverEntryPointsTCP, watcher, chainBuilder, accessLog), nil
}

func switchRouter(tcpRouterFactory *server.TCPRouterFactory, acmeProviders []*acme.Provider, serverEntryPointsTCP server.TCPEntryPoints) func(conf dynamic.Configuration) {
return func(conf dynamic.Configuration) {
routers := tcpRouterFactory.CreateTCPRouters(conf)
for entryPointName, rt := range routers {
for _, p := range acmeProviders {
if p != nil && p.HTTPChallenge != nil && p.HTTPChallenge.EntryPoint == entryPointName {
rt.HTTPHandler(p.CreateHandler(rt.GetHTTPHandler()))
break
}
}
}
serverEntryPointsTCP.Switch(routers)
}
}

// initACMEProvider creates an acme provider from the ACME part of globalConfiguration
func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.ProviderAggregator, tlsManager *traefiktls.Manager) []*acme.Provider {
challengeStore := acme.NewLocalChallengeStore()
Expand Down Expand Up @@ -222,6 +282,60 @@ func initACMEProvider(c *static.Configuration, providerAggregator *aggregator.Pr
return resolvers
}

func registerMetricClients(metricsConfig *types.Metrics) metrics.Registry {
if metricsConfig == nil {
return metrics.NewVoidRegistry()
}

var registries []metrics.Registry

if metricsConfig.Prometheus != nil {
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "prometheus"))
prometheusRegister := metrics.RegisterPrometheus(ctx, metricsConfig.Prometheus)
if prometheusRegister != nil {
registries = append(registries, prometheusRegister)
log.FromContext(ctx).Debug("Configured Prometheus metrics")
}
}

if metricsConfig.Datadog != nil {
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "datadog"))
registries = append(registries, metrics.RegisterDatadog(ctx, metricsConfig.Datadog))
log.FromContext(ctx).Debugf("Configured Datadog metrics: pushing to %s once every %s",
metricsConfig.Datadog.Address, metricsConfig.Datadog.PushInterval)
}

if metricsConfig.StatsD != nil {
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "statsd"))
registries = append(registries, metrics.RegisterStatsd(ctx, metricsConfig.StatsD))
log.FromContext(ctx).Debugf("Configured StatsD metrics: pushing to %s once every %s",
metricsConfig.StatsD.Address, metricsConfig.StatsD.PushInterval)
}

if metricsConfig.InfluxDB != nil {
ctx := log.With(context.Background(), log.Str(log.MetricsProviderName, "influxdb"))
registries = append(registries, metrics.RegisterInfluxDB(ctx, metricsConfig.InfluxDB))
log.FromContext(ctx).Debugf("Configured InfluxDB metrics: pushing to %s once every %s",
metricsConfig.InfluxDB.Address, metricsConfig.InfluxDB.PushInterval)
}

return metrics.NewMultiRegistry(registries)
}

func setupAccessLog(conf *types.AccessLog) *accesslog.Handler {
if conf == nil {
return nil
}

accessLoggerMiddleware, err := accesslog.NewHandler(conf)
if err != nil {
log.WithoutContext().Warnf("Unable to create access logger : %v", err)
return nil
}

return accessLoggerMiddleware
}

func configureLogging(staticConfiguration *static.Configuration) {
// configure default log flags
stdlog.SetFlags(stdlog.Lshortfile | stdlog.LstdFlags)
Expand Down
22 changes: 22 additions & 0 deletions docs/content/observability/metrics/prometheus.md
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,25 @@ metrics:
--entryPoints.metrics.address=":8082"
--metrics.prometheus.entryPoint="metrics"
```

#### `manualRouting`

_Optional, Default=false_

If `manualRouting` is `true`, it disables the default internal router in order to allow one to create a custom router for the `prometheus@internal` service.

```toml tab="File (TOML)"
[metrics]
[metrics.prometheus]
manualRouting = true
```

```yaml tab="File (YAML)"
metrics:
prometheus:
manualRouting: true
```

```bash tab="CLI"
--metrics.prometheus.manualrouting=true
```
20 changes: 20 additions & 0 deletions docs/content/operations/ping.md
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,23 @@ ping:
--entryPoints.ping.address=":8082"
--ping.entryPoint="ping"
```

#### `manualRouting`

_Optional, Default=false_

If `manualRouting` is `true`, it disables the default internal router in order to allow one to create a custom router for the `ping@internal` service.

```toml tab="File (TOML)"
[ping]
manualRouting = true
```

```yaml tab="File (YAML)"
ping:
manualRouting: true
```

```bash tab="CLI"
--ping.manualrouting=true
```
6 changes: 6 additions & 0 deletions docs/content/reference/static-configuration/cli-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000
`--metrics.prometheus.entrypoint`:
EntryPoint (Default: ```traefik```)

`--metrics.prometheus.manualrouting`:
Manual routing (Default: ```false```)

`--metrics.statsd`:
StatsD metrics exporter type. (Default: ```false```)

Expand All @@ -237,6 +240,9 @@ Enable ping. (Default: ```false```)
`--ping.entrypoint`:
EntryPoint (Default: ```traefik```)

`--ping.manualrouting`:
Manual routing (Default: ```false```)

`--providers.consulcatalog.cache`:
Use local agent caching for catalog reads. (Default: ```false```)

Expand Down
6 changes: 6 additions & 0 deletions docs/content/reference/static-configuration/env-ref.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,9 @@ Buckets for latency metrics. (Default: ```0.100000, 0.300000, 1.200000, 5.000000
`TRAEFIK_METRICS_PROMETHEUS_ENTRYPOINT`:
EntryPoint (Default: ```traefik```)

`TRAEFIK_METRICS_PROMETHEUS_MANUALROUTING`:
Manual routing (Default: ```false```)

`TRAEFIK_METRICS_STATSD`:
StatsD metrics exporter type. (Default: ```false```)

Expand All @@ -237,6 +240,9 @@ Enable ping. (Default: ```false```)
`TRAEFIK_PING_ENTRYPOINT`:
EntryPoint (Default: ```traefik```)

`TRAEFIK_PING_MANUALROUTING`:
Manual routing (Default: ```false```)

`TRAEFIK_PROVIDERS_CONSULCATALOG_CACHE`:
Use local agent caching for catalog reads. (Default: ```false```)

Expand Down
2 changes: 2 additions & 0 deletions docs/content/reference/static-configuration/file.toml
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,7 @@
addEntryPointsLabels = true
addServicesLabels = true
entryPoint = "foobar"
manualRouting = true
[metrics.datadog]
address = "foobar"
pushInterval = "10s"
Expand All @@ -165,6 +166,7 @@

[ping]
entryPoint = "foobar"
manualRouting = true

[log]
level = "foobar"
Expand Down
2 changes: 2 additions & 0 deletions docs/content/reference/static-configuration/file.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -148,6 +148,7 @@ metrics:
addEntryPointsLabels: true
addServicesLabels: true
entryPoint: foobar
manualRouting: true
datadog:
address: foobar
pushInterval: 42
Expand All @@ -171,6 +172,7 @@ metrics:
addServicesLabels: true
ping:
entryPoint: foobar
manualRouting: true
log:
level: foobar
filePath: foobar
Expand Down

0 comments on commit 424e2a9

Please sign in to comment.