Merge 'v1.5.0-rc2' into master

This commit is contained in:
Fernandez Ludovic 2017-12-06 20:24:46 +01:00
commit 260ee980e0
8 changed files with 119 additions and 40 deletions

View file

@ -1,5 +1,41 @@
# Change Log
## [v1.5.0-rc2](https://github.com/containous/traefik/tree/v1.5.0-rc2) (2017-12-06)
[All Commits](https://github.com/containous/traefik/compare/v1.5.0-rc1...v1.5.0-rc2)
**Bug fixes:**
- **[acme]** Modify the ACME renewing logs level ([#2520](https://github.com/containous/traefik/pull/2520) by [nmengin](https://github.com/nmengin))
- **[api]** Fix pprof route order. ([#2523](https://github.com/containous/traefik/pull/2523) by [timoreimann](https://github.com/timoreimann))
- **[docker,k8s]** Change custom headers separator ([#2509](https://github.com/containous/traefik/pull/2509) by [ldez](https://github.com/ldez))
- **[docker,k8s]** Fix Labels/annotation logs and values. ([#2488](https://github.com/containous/traefik/pull/2488) by [ldez](https://github.com/ldez))
- **[docker]** Quote template strings ([#2496](https://github.com/containous/traefik/pull/2496) by [dtomcej](https://github.com/dtomcej))
- **[docker]** Fix empty IP for backend when dnsrr in Docker swarm mode ([#2490](https://github.com/containous/traefik/pull/2490) by [mmatur](https://github.com/mmatur))
- **[healthcheck]** Fix healthcheck when web is not specified ([#2529](https://github.com/containous/traefik/pull/2529) by [Juliens](https://github.com/Juliens))
- **[k8s]** Reduce logs with new Kubernetes security annotations ([#2506](https://github.com/containous/traefik/pull/2506) by [ldez](https://github.com/ldez))
- **[metrics]** Do not ignore web params when web.metrics.prometheus is set ([#2499](https://github.com/containous/traefik/pull/2499) by [Juliens](https://github.com/Juliens))
- **[metrics]** Fix metrics problem on multiple entrypoints ([#2492](https://github.com/containous/traefik/pull/2492) by [Juliens](https://github.com/Juliens))
- Close ring buffer used in throttling function. ([#2532](https://github.com/containous/traefik/pull/2532) by [timoreimann](https://github.com/timoreimann))
- Fix wrong default entrypoint and non-existing entrypoint issue ([#2501](https://github.com/containous/traefik/pull/2501) by [Juliens](https://github.com/Juliens))
**Documentation:**
- **[consul]** Improve Consul documentation ([#2485](https://github.com/containous/traefik/pull/2485) by [mmatur](https://github.com/mmatur))
- **[docker]** Fix Docker labels documentation render. ([#2505](https://github.com/containous/traefik/pull/2505) by [ldez](https://github.com/ldez))
- **[k8s]** Add note to Kubernetes RBAC docs about RoleBindings and namespaces ([#2498](https://github.com/containous/traefik/pull/2498) by [jmara](https://github.com/jmara))
**Misc:**
- Merge v1.4.5 into v1.5 ([#2530](https://github.com/containous/traefik/pull/2530) by [mmatur](https://github.com/mmatur))
## [v1.4.5](https://github.com/containous/traefik/tree/v1.4.5) (2017-12-05)
[All Commits](https://github.com/containous/traefik/compare/v1.4.4...v1.4.5)
**Bug fixes:**
- **[docker]** Fix empty ip when container is stopped ([#2478](https://github.com/containous/traefik/pull/2478) by [mmatur](https://github.com/mmatur))
- **[k8s]** Fix kubernetes path prefix rule with rewrite-target ([#2461](https://github.com/containous/traefik/pull/2461) by [cheungpat](https://github.com/cheungpat))
**Documentation:**
- **[file]** Emphasize the necessity of enabling file backend ([#2483](https://github.com/containous/traefik/pull/2483) by [mvasin](https://github.com/mvasin))
- Add link to future 1.5 documentation. ([#2477](https://github.com/containous/traefik/pull/2477) by [ldez](https://github.com/ldez))
## [v1.5.0-rc1](https://github.com/containous/traefik/tree/v1.5.0-rc1) (2017-11-28)
[All Commits](https://github.com/containous/traefik/compare/v1.4.0-rc1...v1.5.0-rc1)

View file

@ -394,44 +394,27 @@ func (a *ACME) retrieveCertificates() {
func (a *ACME) renewCertificates() {
a.jobs.In() <- func() {
log.Debug("Testing certificate renew...")
log.Info("Testing certificate renew...")
account := a.store.Get().(*Account)
for _, certificateResource := range account.DomainsCertificate.Certs {
if certificateResource.needRenew() {
log.Debugf("Renewing certificate %+v", certificateResource.Domains)
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
Domain: certificateResource.Certificate.Domain,
CertURL: certificateResource.Certificate.CertURL,
CertStableURL: certificateResource.Certificate.CertStableURL,
PrivateKey: certificateResource.Certificate.PrivateKey,
Certificate: certificateResource.Certificate.Certificate,
}, true, OSCPMustStaple)
log.Infof("Renewing certificate from LE : %+v", certificateResource.Domains)
renewedACMECert, err := a.renewACMECertificate(certificateResource)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
log.Errorf("Error renewing certificate from LE: %v", err)
continue
}
log.Debugf("Renewed certificate %+v", certificateResource.Domains)
renewedACMECert := &Certificate{
Domain: renewedCert.Domain,
CertURL: renewedCert.CertURL,
CertStableURL: renewedCert.CertStableURL,
PrivateKey: renewedCert.PrivateKey,
Certificate: renewedCert.Certificate,
operation := func() error {
return a.storeRenewedCertificate(account, certificateResource, renewedACMECert)
}
transaction, object, err := a.store.Begin()
notify := func(err error, time time.Duration) {
log.Warnf("Renewed certificate storage error: %v, retrying in %s", err, time)
}
ebo := backoff.NewExponentialBackOff()
ebo.MaxElapsedTime = 60 * time.Second
err = backoff.RetryNotify(safe.OperationWithRecover(operation), ebo, notify)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
}
account = object.(*Account)
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
if err != nil {
log.Errorf("Error renewing certificate: %v", err)
continue
}
if err = transaction.Commit(account); err != nil {
log.Errorf("Error Saving ACME account %+v: %s", account, err.Error())
log.Errorf("Datastore cannot sync: %v", err)
continue
}
}
@ -439,6 +422,56 @@ func (a *ACME) renewCertificates() {
}
}
func (a *ACME) renewACMECertificate(certificateResource *DomainsCertificate) (*Certificate, error) {
renewedCert, err := a.client.RenewCertificate(acme.CertificateResource{
Domain: certificateResource.Certificate.Domain,
CertURL: certificateResource.Certificate.CertURL,
CertStableURL: certificateResource.Certificate.CertStableURL,
PrivateKey: certificateResource.Certificate.PrivateKey,
Certificate: certificateResource.Certificate.Certificate,
}, true, OSCPMustStaple)
if err != nil {
return nil, err
}
log.Infof("Renewed certificate from LE: %+v", certificateResource.Domains)
return &Certificate{
Domain: renewedCert.Domain,
CertURL: renewedCert.CertURL,
CertStableURL: renewedCert.CertStableURL,
PrivateKey: renewedCert.PrivateKey,
Certificate: renewedCert.Certificate,
}, nil
}
func (a *ACME) storeRenewedCertificate(account *Account, certificateResource *DomainsCertificate, renewedACMECert *Certificate) error {
transaction, object, err := a.store.Begin()
if err != nil {
return fmt.Errorf("error during transaction initialization for renewing certificate: %v", err)
}
log.Infof("Renewing certificate in data store : %+v ", certificateResource.Domains)
account = object.(*Account)
err = account.DomainsCertificate.renewCertificates(renewedACMECert, certificateResource.Domains)
if err != nil {
return fmt.Errorf("error renewing certificate in datastore: %v ", err)
}
log.Infof("Commit certificate renewed in data store : %+v", certificateResource.Domains)
if err = transaction.Commit(account); err != nil {
return fmt.Errorf("error saving ACME account %+v: %v", account, err)
}
oldAccount := a.store.Get().(*Account)
for _, oldCertificateResource := range oldAccount.DomainsCertificate.Certs {
if oldCertificateResource.Domains.Main == certificateResource.Domains.Main && strings.Join(oldCertificateResource.Domains.SANs, ",") == strings.Join(certificateResource.Domains.SANs, ",") && certificateResource.Certificate != renewedACMECert {
return fmt.Errorf("renewed certificate not stored: %+v", certificateResource.Domains)
}
}
log.Infof("Certificate successfully renewed in data store: %+v", certificateResource.Domains)
return nil
}
func dnsOverrideDelay(delay int) error {
var err error
if delay > 0 {
@ -448,7 +481,7 @@ func dnsOverrideDelay(delay int) error {
return true, nil
}
} else if delay < 0 {
err = fmt.Errorf("Invalid negative DelayDontCheckDNS: %d", delay)
err = fmt.Errorf("invalid negative DelayDontCheckDNS: %d", delay)
}
return err
}

View file

@ -38,9 +38,9 @@ func (g DebugHandler) AddRoutes(router *mux.Router) {
fmt.Fprint(w, "\n}\n")
})
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/cmdline").HandlerFunc(pprof.Cmdline)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/profile").HandlerFunc(pprof.Profile)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/symbol").HandlerFunc(pprof.Symbol)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/trace").HandlerFunc(pprof.Trace)
router.Methods(http.MethodGet).PathPrefix("/debug/pprof/").HandlerFunc(pprof.Index)
}

View file

@ -64,6 +64,9 @@ func healthCheck(globalConfiguration configuration.GlobalConfiguration) (*http.R
}
client.Transport = tr
}
return client.Head(protocol + "://" + pingEntryPoint.Address + globalConfiguration.Web.Path + "ping")
path := "/"
if globalConfiguration.Web != nil {
path = globalConfiguration.Web.Path
}
return client.Head(protocol + "://" + pingEntryPoint.Address + path + "ping")
}

View file

@ -620,7 +620,7 @@ This command allows to check the health of Traefik. Its exit status is `0` if Tr
This can be used with Docker [HEALTHCHECK](https://docs.docker.com/engine/reference/builder/#healthcheck) instruction or any other health check orchestration mechanism.
!!! note
The [`web` provider](/configuration/backends/web) must be enabled to allow `/ping` calls by the `healthcheck` command.
The [`ping`](/configuration/ping) must be enabled to allow the `healthcheck` command to call `/ping`.
```bash
traefik healthcheck

View file

@ -8,6 +8,8 @@ You have three choices:
- [Rules in a Separate File](/configuration/backends/file/#rules-in-a-separate-file)
- [Multiple `.toml` Files](/configuration/backends/file/#multiple-toml-files)
To enable the file backend, you must either pass the `--file` option to the Træfik binary or put the `[file]` section (with or without inner settings) in the configuration file.
The configuration file allows managing both backends/frontends and HTTPS certificates (which are not [Let's Encrypt](https://letsencrypt.org) certificates generated through Træfik).
## Simple
@ -25,8 +27,8 @@ defaultEntryPoints = ["http", "https"]
[entryPoints.https]
address = ":443"
[entryPoints.https.tls]
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.org.cert"
[[entryPoints.https.tls.certificates]]
certFile = "integration/fixtures/https/snitest.org.cert"
keyFile = "integration/fixtures/https/snitest.org.key"
[file]
@ -153,15 +155,16 @@ filename = "rules.toml"
entrypoints = ["http", "https"] # overrides defaultEntryPoints
backend = "backend2"
rule = "Path:/test"
# HTTPS certificate
[[tlsConfiguration]]
entryPoints = ["https"]
entryPoints = ["https"]
[tlsConfiguration.certificate]
certFile = "integration/fixtures/https/snitest.com.cert"
keyFile = "integration/fixtures/https/snitest.com.key"
[[tlsConfiguration]]
entryPoints = ["https"]
entryPoints = ["https"]
[[tlsConfiguration.certificates]]
certFile = "integration/fixtures/https/snitest.org.cert"
keyFile = "integration/fixtures/https/snitest.org.key"

View file

@ -21,6 +21,9 @@ If your cluster is configured with RBAC, you will need to authorize Træfik to u
RoleBindings per namespace enable to restrict granted permissions to the very namespaces only that Træfik is watching over, thereby following the least-privileges principle. This is the preferred approach if Træfik is not supposed to watch all namespaces, and the set of namespaces does not change dynamically. Otherwise, a single ClusterRoleBinding must be employed.
!!! note
RoleBindings per namespace are available in Træfik 1.5 and later. Please use ClusterRoleBindings for older versions.
For the sake of simplicity, this guide will use a ClusterRoleBinding:
```yaml
@ -75,7 +78,7 @@ For namespaced restrictions, one RoleBinding is required per watched namespace a
It is possible to use Træfik with a [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) or a [DaemonSet](https://kubernetes.io/docs/concepts/workloads/controllers/daemonset/) object,
whereas both options have their own pros and cons:
- The scalability is much better when using a Deployment, because you will have a Single-Pod-per-Node model when using the DeaemonSet.
- It is possible to exclusively run a Service on a dedicated set of machines using taints and tolerations with a DaemonSet.
- On the other hand the DaemonSet allows you to access any Node directly on Port 80 and 443, where you have to setup a [Service](https://kubernetes.io/docs/concepts/services-networking/service/) object with a Deployment.

View file

@ -374,6 +374,7 @@ func (s *Server) preLoadConfiguration(configMsg types.ConfigMessage) {
// it will publish the last of the newly received configurations.
func throttleProviderConfigReload(throttle time.Duration, publish chan<- types.ConfigMessage, in <-chan types.ConfigMessage, stop chan bool) {
ring := channels.NewRingChannel(1)
defer ring.Close()
safe.Go(func() {
for {