Skip to content

Commit

Permalink
Merge pull request #481 from cocap10/global-config-kv
Browse files Browse the repository at this point in the history
Use KvStores as global config sources
  • Loading branch information
vdemeester committed Jul 21, 2016
2 parents 9be0c67 + b153e90 commit 686c23d
Show file tree
Hide file tree
Showing 28 changed files with 1,146 additions and 210 deletions.
45 changes: 43 additions & 2 deletions configuration.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,22 @@
package main

import (
"crypto/tls"
"errors"
"fmt"
"github.com/containous/traefik/acme"
"github.com/containous/traefik/provider"
"github.com/containous/traefik/types"
"os"
"regexp"
"strings"
"time"
)

// TraefikConfiguration holds GlobalConfiguration and other stuff
type TraefikConfiguration struct {
GlobalConfiguration
ConfigFile string `short:"c" description:"Configuration file to use (TOML)."`
GlobalConfiguration `mapstructure:",squash"`
ConfigFile string `short:"c" description:"Configuration file to use (TOML)."`
}

// GlobalConfiguration holds global configuration (with providers, etc.).
Expand Down Expand Up @@ -177,8 +179,46 @@ type TLS struct {
}

// Certificates defines traefik certificates type
// Certs and Keys could be either a file path, or the file content itself
type Certificates []Certificate

//CreateTLSConfig creates a TLS config from Certificate structures
func (certs *Certificates) CreateTLSConfig() (*tls.Config, error) {
config := &tls.Config{}
config.Certificates = []tls.Certificate{}
certsSlice := []Certificate(*certs)
for _, v := range certsSlice {
isAPath := false
_, errCert := os.Stat(v.CertFile)
_, errKey := os.Stat(v.KeyFile)
if errCert == nil {
if errKey == nil {
isAPath = true
} else {
return nil, fmt.Errorf("Bad TLS Certificate KeyFile format. Expected a path.")
}
} else if errKey == nil {
return nil, fmt.Errorf("Bad TLS Certificate KeyFile format. Expected a path.")
}

cert := tls.Certificate{}
var err error
if isAPath {
cert, err = tls.LoadX509KeyPair(v.CertFile, v.KeyFile)
if err != nil {
return nil, err
}
} else {
cert, err = tls.X509KeyPair([]byte(v.CertFile), []byte(v.KeyFile))
if err != nil {
return nil, err
}
}
config.Certificates = append(config.Certificates, cert)
}
return config, nil
}

// String is the method to format the flag's value, part of the flag.Value interface.
// The String method's output will be used in diagnostics.
func (certs *Certificates) String() string {
Expand Down Expand Up @@ -209,6 +249,7 @@ func (certs *Certificates) Type() string {
}

// Certificate holds a SSL cert/key pair
// Certs and Key could be either a file path, or the file content itself
type Certificate struct {
CertFile string
KeyFile string
Expand Down
60 changes: 53 additions & 7 deletions docs/basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -253,9 +253,30 @@ Here is an example of backends and servers definition:
- `backend2` will forward the traffic to two servers: `http://172.17.0.4:80"` with weight `1` and `http://172.17.0.5:80` with weight `2` using `drr` load-balancing strategy.
- a circuit breaker is added on `backend1` using the expression `NetworkErrorRatio() > 0.5`: watch error ratio over 10 second sliding window

# Launch
# Configuration

Træfɪk's configuration has two parts:

- The [static Træfɪk configuration](/basics#static-trfk-configuration) which is loaded only at the begining.
- The [dynamic Træfɪk configuration](/basics#dynamic-trfk-configuration) which can be hot-reloaded (no need to restart the process).


## Static Træfɪk configuration

The static configuration is the global configuration which setting up connections to configuration backends and entrypoints.

Træfɪk can be configured using many configuration sources with the following precedence order.
Each item takes precedence over the item below it:

- [Key-value Store](/basics/#key-value-stores)
- [Arguments](/basics/#arguments)
- [Configuration file](/basics/#configuration-file)
- Default

It means that arguments overrides configuration file, and Key-value Store overrides arguments.

### Configuration file

Træfɪk can be configured using a TOML file configuration, arguments, or both.
By default, Træfɪk will try to find a `traefik.toml` in the following places:

- `/etc/traefik/`
Expand All @@ -268,15 +289,40 @@ You can override this by setting a `configFile` argument:
$ traefik --configFile=foo/bar/myconfigfile.toml
```

Træfɪk uses the following precedence order. Each item takes precedence over the item below it:
Please refer to the [global configuration](/toml/#global-configuration) section to get documentation on it.

- arguments
- configuration file
- default
### Arguments

It means that arguments overrides configuration file.
Each argument is described in the help section:

```bash
$ traefik --help
```

Note that all default values will be displayed as well.

### Key-value stores

Træfɪk supports several Key-value stores:

- [Consul](https://consul.io)
- [etcd](https://coreos.com/etcd/)
- [ZooKeeper](https://zookeeper.apache.org/)
- [boltdb](https://github.com/boltdb/bolt)

Please refer to the [User Guide Key-value store configuration](/user-guide/kv-config/) section to get documentation on it.

## Dynamic Træfɪk configuration

The dynamic configuration concerns :

- [Frontends](/basics/#frontends)
- [Backends](/basics/#backends)
- [Servers](/basics/#servers)

Træfɪk can hot-reload those rules which could be provided by [multiple configuration backends](/toml/#configuration-backends).

We only need to enable `watch` option to make Træfɪk watch configuration backend changes and generate its configuration automatically.
Routes to services will be created and updated instantly at any changes.

Please refer to the [configuration backends](/toml/#configuration-backends) section to get documentation on it.
89 changes: 4 additions & 85 deletions docs/toml.md
Original file line number Diff line number Diff line change
Expand Up @@ -756,7 +756,7 @@ prefix = "traefik"
# insecureskipverify = true
```

Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure.
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.

## Consul catalog backend

Expand Down Expand Up @@ -857,7 +857,7 @@ prefix = "/traefik"
# insecureskipverify = true
```

Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure.
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.


## Zookeeper backend
Expand Down Expand Up @@ -900,7 +900,7 @@ prefix = "/traefik"
# filename = "zookeeper.tmpl"
```

Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure.
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.

## BoltDB backend

Expand Down Expand Up @@ -942,85 +942,4 @@ prefix = "/traefik"
# filename = "boltdb.tmpl"
```

Please refer to the [Key Value storage structure](#key-value-storage-structure) section to get documentation en traefik KV structure.

## Key-value storage structure

The Keys-Values structure should look (using `prefix = "/traefik"`):

- backend 1

| Key | Value |
|--------------------------------------------------------|-----------------------------|
| `/traefik/backends/backend1/circuitbreaker/expression` | `NetworkErrorRatio() > 0.5` |
| `/traefik/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik/backends/backend1/servers/server1/weight` | `10` |
| `/traefik/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` |
| `/traefik/backends/backend1/servers/server2/weight` | `1` |

- backend 2

| Key | Value |
|-----------------------------------------------------|------------------------|
| `/traefik/backends/backend2/maxconn/amount` | `10` |
| `/traefik/backends/backend2/maxconn/extractorfunc` | `request.host` |
| `/traefik/backends/backend2/loadbalancer/method` | `drr` |
| `/traefik/backends/backend2/servers/server1/url` | `http://172.17.0.4:80` |
| `/traefik/backends/backend2/servers/server1/weight` | `1` |
| `/traefik/backends/backend2/servers/server2/url` | `http://172.17.0.5:80` |
| `/traefik/backends/backend2/servers/server2/weight` | `2` |

- frontend 1

| Key | Value |
|---------------------------------------------------|-----------------------|
| `/traefik/frontends/frontend1/backend` | `backend2` |
| `/traefik/frontends/frontend1/routes/test_1/rule` | `Host:test.localhost` |

- frontend 2

| Key | Value |
|----------------------------------------------------|--------------------|
| `/traefik/frontends/frontend2/backend` | `backend1` |
| `/traefik/frontends/frontend2/passHostHeader` | `true` |
| `/traefik/frontends/frontend2/priority` | `10` |
| `/traefik/frontends/frontend2/entrypoints` | `http,https` |
| `/traefik/frontends/frontend2/routes/test_2/rule` | `PathPrefix:/test` |

## Atomic configuration changes

The [Etcd](https://github.com/coreos/etcd/issues/860) and [Consul](https://github.com/hashicorp/consul/issues/886) backends do not support updating multiple keys atomically. As a result, it may be possible for Træfɪk to read an intermediate configuration state despite judicious use of the `--providersThrottleDuration` flag. To solve this problem, Træfɪk supports a special key called `/traefik/alias`. If set, Træfɪk use the value as an alternative key prefix.

Given the key structure below, Træfɪk will use the `http://172.17.0.2:80` as its only backend (frontend keys have been omitted for brevity).

| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
| `/traefik/alias` | `/traefik_configurations/1` |
| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` |

When an atomic configuration change is required, you may write a new configuration at an alternative prefix. Here, although the `/traefik_configurations/2/...` keys have been set, the old configuration is still active because the `/traefik/alias` key still points to `/traefik_configurations/1`:

| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
| `/traefik/alias` | `/traefik_configurations/1` |
| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` |
| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` |
| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.3:80` |
| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` |

Once the `/traefik/alias` key is updated, the new `/traefik_configurations/2` configuration becomes active atomically. Here, we have a 50% balance between the `http://172.17.0.3:80` and the `http://172.17.0.4:80` hosts while no traffic is sent to the `172.17.0.2:80` host:

| Key | Value |
|-------------------------------------------------------------------------|-----------------------------|
| `/traefik/alias` | `/traefik_configurations/2` |
| `/traefik_configurations/1/backends/backend1/servers/server1/url` | `http://172.17.0.2:80` |
| `/traefik_configurations/1/backends/backend1/servers/server1/weight` | `10` |
| `/traefik_configurations/2/backends/backend1/servers/server1/url` | `http://172.17.0.3:80` |
| `/traefik_configurations/2/backends/backend1/servers/server1/weight` | `5` |
| `/traefik_configurations/2/backends/backend1/servers/server2/url` | `http://172.17.0.4:80` |
| `/traefik_configurations/2/backends/backend1/servers/server2/weight` | `5` |

Note that Træfɪk *will not watch for key changes in the `/traefik_configurations` prefix*. It will only watch for changes in the `/traefik` prefix. Further, if the `/traefik/alias` key is set, all other sibling keys with the `/traefik` prefix are ignored.
Please refer to the [Key Value storage structure](/user-guide/kv-config/#key-value-storage-structure) section to get documentation on traefik KV structure.
1 change: 1 addition & 0 deletions docs/user-guide/examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ defaultEntryPoints = ["http", "https"]
CertFile = "integration/fixtures/https/snitest.org.cert"
KeyFile = "integration/fixtures/https/snitest.org.key"
```
Note that we can either give path to certificate file or directly the file content itself ([like in this TOML example](/user-guide/kv-config/#upload-the-configuration-in-the-key-value-store)).

## HTTP redirect on HTTPS

Expand Down

0 comments on commit 686c23d

Please sign in to comment.