Compare commits

...

13 Commits

Author SHA1 Message Date
Kevin Pollet
52b6b057f0 Prepare release v2.9.0-rc4 2022-09-23 16:01:00 +02:00
Fernandez Ludovic
7b3faef4b3 Merge branch v2.8 into v2.9 2022-09-23 15:28:57 +02:00
Kevin Pollet
7758880f3f Prepare release v2.8.6 2022-09-23 15:24:15 +02:00
Ludovic Fernandez
d04903edb2 fix: query parameter matching with equal 2022-09-23 15:12:29 +02:00
Douglas De Toni Machado
a63d5c95a8 Rework metrics overview page 2022-09-23 11:06:09 +02:00
Ludovic Fernandez
bb66950197 fix: acme panic 2022-09-23 10:42:09 +02:00
Fernandez Ludovic
c4cc30ccc6 Merge branch v2.8 into v2.9 2022-09-23 09:07:13 +02:00
Julien Salleyron
9cd54baca4 Optimize websocket headers handling
Co-authored-by: Kevin Pollet <pollet.kevin@gmail.com>
2022-09-22 10:00:09 +02:00
Ludovic Fernandez
7ac687a0a9 providers: simplify AddServer algorithms 2022-09-21 14:54:08 +02:00
t3hchipmunk
83ae1021f6 fix: UDP loadbalancer tags not being used with Consul Catalog 2022-09-21 14:30:09 +02:00
Romain
67e3bc6380 Add documentation for ECS constraints option 2022-09-20 12:22:08 +02:00
Fernandez Ludovic
4b291b2cf8 Merge branch v2.8 into v2.9 2022-09-19 11:53:00 +02:00
Ludovic Fernandez
89870ad539 docs: fix link to RouteNamespaces 2022-09-19 11:26:08 +02:00
17 changed files with 428 additions and 680 deletions

View File

@@ -1,3 +1,33 @@
## [v2.9.0-rc4](https://github.com/traefik/traefik/tree/v2.9.0-rc4) (2022-09-23)
[All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc3...v2.9.0-rc4)
**Bug fixes:**
- **[acme]** Fix ACME panic ([#9365](https://github.com/traefik/traefik/pull/9365) by [ldez](https://github.com/ldez))
**Documentation:**
- **[metrics]** Rework metrics overview page ([#9366](https://github.com/traefik/traefik/pull/9366) by [ddtmachado](https://github.com/ddtmachado))
**Misc:**
- Merge current v2.8 into v2.9 ([#9371](https://github.com/traefik/traefik/pull/9371) by [ldez](https://github.com/ldez))
- Merge current v2.8 into v2.9 ([#9367](https://github.com/traefik/traefik/pull/9367) by [ldez](https://github.com/ldez))
- Merge current v2.8 into v2.9 ([#9350](https://github.com/traefik/traefik/pull/9350) by [ldez](https://github.com/ldez))
## [v2.8.6](https://github.com/traefik/traefik/tree/v2.8.6) (2022-09-23)
[All Commits](https://github.com/traefik/traefik/compare/v2.8.5...v2.8.6)
**Bug fixes:**
- **[consulcatalog]** Fix UDP loadbalancer tags not being used with Consul Catalog ([#9357](https://github.com/traefik/traefik/pull/9357) by [t3hchipmunk](https://github.com/t3hchipmunk))
- **[docker,rancher,ecs,provider]** Simplify AddServer algorithm ([#9358](https://github.com/traefik/traefik/pull/9358) by [ldez](https://github.com/ldez))
- **[plugins]** Allow empty plugin configuration ([#9338](https://github.com/traefik/traefik/pull/9338) by [ldez](https://github.com/ldez))
- **[rules]** Fix query parameter matching with equal ([#9369](https://github.com/traefik/traefik/pull/9369) by [ldez](https://github.com/ldez))
- **[server]** Optimize websocket headers handling ([#9360](https://github.com/traefik/traefik/pull/9360) by [juliens](https://github.com/juliens))
**Documentation:**
- **[ecs]** Add documentation for ECS constraints option ([#9354](https://github.com/traefik/traefik/pull/9354) by [rtribotte](https://github.com/rtribotte))
- **[k8s/gatewayapi]** Fix link to RouteNamespaces ([#9349](https://github.com/traefik/traefik/pull/9349) by [ldez](https://github.com/ldez))
- Add documentation for json schema usage to validate config in the FAQ ([#9340](https://github.com/traefik/traefik/pull/9340) by [rtribotte](https://github.com/rtribotte))
- Add a note on case insensitive regex matching ([#9322](https://github.com/traefik/traefik/pull/9322) by [NEwa-05](https://github.com/NEwa-05))
## [v2.9.0-rc3](https://github.com/traefik/traefik/tree/v2.9.0-rc3) (2022-09-16)
[All Commits](https://github.com/traefik/traefik/compare/v2.9.0-rc2...v2.9.0-rc3)

View File

@@ -445,7 +445,7 @@ To enable HTTP/3 on an EntryPoint, please check out the [HTTP/3 configuration](.
### Kubernetes Gateway API Provider
In `v2.6`, the [Kubernetes Gateway API provider](../providers/kubernetes-gateway.md) now only supports the version [v1alpha2](https://gateway-api.sigs.k8s.io/v1alpha2/guides/getting-started/) of the specification and
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1alpha2.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
[route namespaces](https://gateway-api.sigs.k8s.io/v1alpha2/references/spec/#gateway.networking.k8s.io/v1beta1.RouteNamespaces) selectors, which requires Traefik to fetch and watch the cluster namespaces.
Therefore, the [RBAC](../reference/dynamic-configuration/kubernetes-gateway.md#rbac) and [CRD](../reference/dynamic-configuration/kubernetes-gateway.md#definitions) definitions must be updated.
## v2.6.0 to v2.6.1

View File

@@ -1,11 +1,11 @@
---
title: "Traefik Metrics Overview"
description: "Traefik Proxy supports four metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started."
description: "Traefik Proxy supports these metrics backend systems: Datadog, InfluxDB, Prometheus, and StatsD. Read the full documentation to get started."
---
# Metrics
Traefik supports 4 metrics backends:
Traefik supports these metrics backends:
- [Datadog](./datadog.md)
- [InfluxDB](./influxdb.md)
@@ -15,569 +15,188 @@ Traefik supports 4 metrics backends:
## Global Metrics
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|-------------------------------------------------------------------------|---------|----------------------|------------|--------|
| [Configuration reloads](#configuration-reloads) | ✓ | ✓ | ✓ | ✓ |
| [Last Configuration Reload Success](#last-configuration-reload-success) | ✓ | ✓ | ✓ | ✓ |
| [TLS certificates expiration](#tls-certificates-expiration) | ✓ | ✓ | ✓ | ✓ |
| Metric | Type | Description |
|---------------------------------------------|---------|---------------------------------------------------------|
| Config reload total | Count | The total count of configuration reloads. |
| Config reload last success | Gauge | The timestamp of the last configuration reload success. |
| TLS certificates not after | Gauge | The expiration date of certificates. |
### Configuration Reloads
The total count of configuration reloads.
```prom tab="Prometheus"
traefik_config_reloads_total
traefik_config_last_reload_success
traefik_tls_certs_not_after
```
```dd tab="Datadog"
config.reload.total
config.reload.lastSuccessTimestamp
tls.certs.notAfterTimestamp
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.config.reload.total
```
```prom tab="Prometheus"
traefik_config_reloads_total
traefik.config.reload.lastSuccessTimestamp
traefik.tls.certs.notAfterTimestamp
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.config.reload.total
```
### Last Configuration Reload Success
The timestamp of the last configuration reload success.
```dd tab="Datadog"
config.reload.lastSuccessTimestamp
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.config.reload.lastSuccessTimestamp
```
```prom tab="Prometheus"
traefik_config_last_reload_success
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.config.reload.lastSuccessTimestamp
```
### TLS certificates expiration
The expiration date of certificates.
[Labels](#labels): `cn`, `sans`, `serial`.
```dd tab="Datadog"
tls.certs.notAfterTimestamp
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.tls.certs.notAfterTimestamp
```
```prom tab="Prometheus"
traefik_tls_certs_not_after
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.tls.certs.notAfterTimestamp
```
## EntryPoint Metrics
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|-----------------------------------------------------------|---------|----------------------|------------|--------|
| [HTTP Requests Count](#http-requests-count) | | ✓ | ✓ | ✓ |
| [HTTPS Requests Count](#https-requests-count) | | ✓ | ✓ | ✓ |
| [Request Duration Histogram](#request-duration-histogram) | ✓ | ✓ | ✓ | ✓ |
| [Open Connections Count](#open-connections-count) | | ✓ | ✓ | ✓ |
| [Requests Bytes Count](#requests-bytes-count) | ✓ | ✓ | ✓ | ✓ |
| [Responses Bytes Count](#responses-bytes-count) | ✓ | ✓ | ✓ | ✓ |
| Metric | Type | [Labels](#labels) | Description |
|-----------------------|-----------|--------------------------------------------|---------------------------------------------------------------------|
| Requests total | Count | `code`, `method`, `protocol`, `entrypoint` | The total count of HTTP requests received by an entrypoint. |
| Requests TLS total | Count | `tls_version`, `tls_cipher`, `entrypoint` | The total count of HTTPS requests received by an entrypoint. |
| Request duration | Histogram | `code`, `method`, `protocol`, `entrypoint` | Request processing duration histogram on an entrypoint. |
| Open connections | Count | `method`, `protocol`, `entrypoint` | The current count of open connections on an entrypoint. |
| Requests bytes total | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP requests in bytes handled by an entrypoint. |
| Responses bytes total | Count | `code`, `method`, `protocol`, `entrypoint` | The total size of HTTP responses in bytes handled by an entrypoint. |
### HTTP Requests Count
The total count of HTTP requests received by an entrypoint.
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
```prom tab="Prometheus"
traefik_entrypoint_requests_total
traefik_entrypoint_requests_tls_total
traefik_entrypoint_request_duration_seconds
traefik_entrypoint_open_connections
traefik_entrypoint_requests_bytes_total
traefik_entrypoint_responses_bytes_total
```
```dd tab="Datadog"
entrypoint.request.total
entrypoint.request.tls.total
entrypoint.request.duration
entrypoint.connections.open
entrypoint.requests.bytes.total
entrypoint.responses.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.entrypoint.requests.total
```
```prom tab="Prometheus"
traefik_entrypoint_requests_total
traefik.entrypoint.requests.tls.total
traefik.entrypoint.request.duration
traefik.entrypoint.connections.open
traefik.entrypoint.requests.bytes.total
traefik.entrypoint.responses.bytes.total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.entrypoint.request.total
```
### HTTPS Requests Count
The total count of HTTPS requests received by an entrypoint.
[Labels](#labels): `tls_version`, `tls_cipher`, `entrypoint`.
```dd tab="Datadog"
entrypoint.request.tls.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.entrypoint.requests.tls.total
```
```prom tab="Prometheus"
traefik_entrypoint_requests_tls_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.entrypoint.request.tls.total
```
### Request Duration Histogram
Request processing duration histogram on an entrypoint.
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
```dd tab="Datadog"
entrypoint.request.duration
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.entrypoint.request.duration
```
```prom tab="Prometheus"
traefik_entrypoint_request_duration_seconds
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.entrypoint.request.duration
```
### Open Connections Count
The current count of open connections on an entrypoint.
[Labels](#labels): `method`, `protocol`, `entrypoint`.
```dd tab="Datadog"
entrypoint.connections.open
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.entrypoint.connections.open
```
```prom tab="Prometheus"
traefik_entrypoint_open_connections
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.entrypoint.connections.open
```
### Requests Bytes Count
The total size of HTTP requests in bytes handled by an entrypoint.
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
```dd tab="Datadog"
entrypoint.requests.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.entrypoint.requests.bytes.total
```
```prom tab="Prometheus"
traefik_entrypoint_requests_bytes_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.entrypoint.requests.bytes.total
```
### Responses Bytes Count
The total size of HTTP responses in bytes handled by an entrypoint.
[Labels](#labels): `code`, `method`, `protocol`, `entrypoint`.
```dd tab="Datadog"
entrypoint.responses.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.entrypoint.responses.bytes.total
```
```prom tab="Prometheus"
traefik_entrypoint_responses_bytes_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.entrypoint.responses.bytes.total
```
## Router Metrics
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|-------------------------------------------------------------|---------|----------------------|------------|--------|
| [HTTP Requests Count](#http-requests-count_1) | | ✓ | ✓ | ✓ |
| [HTTPS Requests Count](#https-requests-count_1) | | ✓ | ✓ | ✓ |
| [Request Duration Histogram](#request-duration-histogram_1) | ✓ | ✓ | ✓ | ✓ |
| [Open Connections Count](#open-connections-count_1) | ✓ | ✓ | ✓ | ✓ |
| [Requests Bytes Count](#requests-bytes-count_1) | ✓ | ✓ | ✓ | ✓ |
| [Responses Bytes Count](#responses-bytes-count_1) | ✓ | ✓ | ✓ | ✓ |
| Metric | Type | [Labels](#labels) | Description |
|-----------------------|-----------|---------------------------------------------------|----------------------------------------------------------------|
| Requests total | Count | `code`, `method`, `protocol`, `router`, `service` | The total count of HTTP requests handled by a router. |
| Requests TLS total | Count | `tls_version`, `tls_cipher`, `router`, `service` | The total count of HTTPS requests handled by a router. |
| Request duration | Histogram | `code`, `method`, `protocol`, `router`, `service` | Request processing duration histogram on a router. |
| Open connections | Count | `method`, `protocol`, `router`, `service` | The current count of open connections on a router. |
| Requests bytes total | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP requests in bytes handled by a router. |
| Responses bytes total | Count | `code`, `method`, `protocol`, `router`, `service` | The total size of HTTP responses in bytes handled by a router. |
### HTTP Requests Count
The total count of HTTP requests handled by a router.
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
```prom tab="Prometheus"
traefik_router_requests_total
traefik_router_requests_tls_total
traefik_router_request_duration_seconds
traefik_router_open_connections
traefik_router_requests_bytes_total
traefik_router_responses_bytes_total
```
```dd tab="Datadog"
router.request.total
router.request.tls.total
router.request.duration
router.connections.open
router.requests.bytes.total
router.responses.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.router.requests.total
```
```prom tab="Prometheus"
traefik_router_requests_total
traefik.router.requests.tls.total
traefik.router.request.duration
traefik.router.connections.open
traefik.router.requests.bytes.total
traefik.router.responses.bytes.total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.router.request.total
```
### HTTPS Requests Count
The total count of HTTPS requests handled by a router.
[Labels](#labels): `tls_version`, `tls_cipher`, `router`, `service`.
```dd tab="Datadog"
router.request.tls.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.router.requests.tls.total
```
```prom tab="Prometheus"
traefik_router_requests_tls_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.router.request.tls.total
```
### Request Duration Histogram
Request processing duration histogram on a router.
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
```dd tab="Datadog"
router.request.duration
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.router.request.duration
```
```prom tab="Prometheus"
traefik_router_request_duration_seconds
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.router.request.duration
```
### Open Connections Count
The current count of open connections on a router.
[Labels](#labels): `method`, `protocol`, `router`, `service`.
```dd tab="Datadog"
router.connections.open
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.router.connections.open
```
```prom tab="Prometheus"
traefik_router_open_connections
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.router.connections.open
```
### Requests Bytes Count
The total size of HTTP requests in bytes handled by a router.
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
```dd tab="Datadog"
router.requests.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.router.requests.bytes.total
```
```prom tab="Prometheus"
traefik_router_requests_bytes_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.router.requests.bytes.total
```
### Responses Bytes Count
The total size of HTTP responses in bytes handled by a router.
[Labels](#labels): `code`, `method`, `protocol`, `router`, `service`.
```dd tab="Datadog"
router.responses.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.router.responses.bytes.total
```
```prom tab="Prometheus"
traefik_router_responses_bytes_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.router.responses.bytes.total
```
## Service Metrics
| Metric | DataDog | InfluxDB / InfluxDB2 | Prometheus | StatsD |
|-------------------------------------------------------------|---------|----------------------|------------|--------|
| [HTTP Requests Count](#http-requests-count_2) | ✓ | ✓ | ✓ | ✓ |
| [HTTPS Requests Count](#https-requests-count_2) | | ✓ | ✓ | ✓ |
| [Request Duration Histogram](#request-duration-histogram_2) | ✓ | ✓ | ✓ | ✓ |
| [Open Connections Count](#open-connections-count_2) | ✓ | ✓ | ✓ | ✓ |
| [Requests Retries Count](#requests-retries-count) | ✓ | ✓ | ✓ | ✓ |
| [Service Server UP](#service-server-up) | ✓ | ✓ | ✓ | ✓ |
| [Requests Bytes Count](#requests-bytes-count_2) | | ✓ | ✓ | ✓ |
| [Responses outgoing traffic](#responses-bytes-count_2) | ✓ | ✓ | ✓ | ✓ |
| Metric | Type | Labels | Description |
|-----------------------|-----------|-----------------------------------------|-------------------------------------------------------------|
| Requests total | Count | `code`, `method`, `protocol`, `service` | The total count of HTTP requests processed on a service. |
| Requests TLS total | Count | `tls_version`, `tls_cipher`, `service` | The total count of HTTPS requests processed on a service. |
| Request duration | Histogram | `code`, `method`, `protocol`, `service` | Request processing duration histogram on a service. |
| Open connections | Count | `method`, `protocol`, `service` | The current count of open connections on a service. |
| Retries total | Count | `service` | The count of requests retries on a service. |
| Server UP | Gauge | `service`, `url` | Current service's server status, 0 for a down or 1 for up. |
| Requests bytes total | Count | `code`, `method`, `protocol`, `service` | The total size of requests in bytes received by a service. |
| Responses bytes total | Count | `code`, `method`, `protocol`, `service` | The total size of responses in bytes returned by a service. |
### HTTP Requests Count
The total count of HTTP requests processed on a service.
[Labels](#labels): `code`, `method`, `protocol`, `service`.
```prom tab="Prometheus"
traefik_service_requests_total
traefik_service_requests_tls_total
traefik_service_request_duration_seconds
traefik_service_open_connections
traefik_service_retries_total
traefik_service_server_up
traefik_service_requests_bytes_total
traefik_service_responses_bytes_total
```
```dd tab="Datadog"
service.request.total
router.service.tls.total
service.request.duration
service.connections.open
service.retries.total
service.server.up
service.requests.bytes.total
service.responses.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.requests.total
```
```prom tab="Prometheus"
traefik_service_requests_total
traefik.service.requests.tls.total
traefik.service.request.duration
traefik.service.connections.open
traefik.service.retries.total
traefik.service.server.up
traefik.service.requests.bytes.total
traefik.service.responses.bytes.total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.request.total
```
### HTTPS Requests Count
The total count of HTTPS requests processed on a service.
[Labels](#labels): `tls_version`, `tls_cipher`, `service`.
```dd tab="Datadog"
router.service.tls.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.requests.tls.total
```
```prom tab="Prometheus"
traefik_service_requests_tls_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.request.tls.total
```
### Request Duration Histogram
Request processing duration histogram on a service.
[Labels](#labels): `code`, `method`, `protocol`, `service`.
```dd tab="Datadog"
service.request.duration
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.request.duration
```
```prom tab="Prometheus"
traefik_service_request_duration_seconds
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.request.duration
```
### Open Connections Count
The current count of open connections on a service.
[Labels](#labels): `method`, `protocol`, `service`.
```dd tab="Datadog"
service.connections.open
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.connections.open
```
```prom tab="Prometheus"
traefik_service_open_connections
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.connections.open
```
### Requests Retries Count
The count of requests retries on a service.
[Labels](#labels): `service`.
```dd tab="Datadog"
service.retries.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.retries.total
```
```prom tab="Prometheus"
traefik_service_retries_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.retries.total
```
### Service Server UP
Current service's server status, described by a gauge with a value of 0 for a down server or a value of 1 for an up server.
[Labels](#labels): `service`, `url`.
```dd tab="Datadog"
service.server.up
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.server.up
```
```prom tab="Prometheus"
traefik_service_server_up
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.server.up
```
### Requests Bytes Count
The total size of requests in bytes received by a service.
[Labels](#labels): `code`, `method`, `protocol`, `service`.
```dd tab="Datadog"
service.requests.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.requests.bytes.total
```
```prom tab="Prometheus"
traefik_service_requests_bytes_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.requests.bytes.total
```
### Responses Bytes Count
The total size of responses in bytes returned by a service.
[Labels](#labels): `code`, `method`, `protocol`, `service`.
```dd tab="Datadog"
service.responses.bytes.total
```
```influxdb tab="InfluxDB / InfluxDB2"
traefik.service.responses.bytes.total
```
```prom tab="Prometheus"
traefik_service_responses_bytes_total
```
```statsd tab="StatsD"
# Default prefix: "traefik"
{prefix}.service.responses.bytes.total
```

View File

@@ -169,6 +169,70 @@ providers:
# ...
```
### `constraints`
_Optional, Default=""_
The `constraints` option can be set to an expression that Traefik matches against the container labels (task),
to determine whether to create any route for that container.
If none of the container labels match the expression, no route for that container is created.
If the expression is empty, all detected containers are included.
The expression syntax is based on the `Label("key", "value")`, and `LabelRegex("key", "value")` functions,
as well as the usual boolean logic, as shown in examples below.
??? example "Constraints Expression Examples"
```toml
# Includes only containers having a label with key `a.label.name` and value `foo`
constraints = "Label(`a.label.name`, `foo`)"
```
```toml
# Excludes containers having any label with key `a.label.name` and value `foo`
constraints = "!Label(`a.label.name`, `value`)"
```
```toml
# With logical AND.
constraints = "Label(`a.label.name`, `valueA`) && Label(`another.label.name`, `valueB`)"
```
```toml
# With logical OR.
constraints = "Label(`a.label.name`, `valueA`) || Label(`another.label.name`, `valueB`)"
```
```toml
# With logical AND and OR, with precedence set by parentheses.
constraints = "Label(`a.label.name`, `valueA`) && (Label(`another.label.name`, `valueB`) || Label(`yet.another.label.name`, `valueC`))"
```
```toml
# Includes only containers having a label with key `a.label.name` and a value matching the `a.+` regular expression.
constraints = "LabelRegex(`a.label.name`, `a.+`)"
```
For additional information, refer to [Restrict the Scope of Service Discovery](./overview.md#restrict-the-scope-of-service-discovery).
```yaml tab="File (YAML)"
providers:
ecs:
constraints: "Label(`a.label.name`,`foo`)"
# ...
```
```toml tab="File (TOML)"
[providers.ecs]
constraints = "Label(`a.label.name`,`foo`)"
# ...
```
```bash tab="CLI"
--providers.ecs.constraints=Label(`a.label.name`,`foo`)
# ...
```
### `defaultRule`
_Optional, Default=```Host(`{{ normalize .Name }}`)```_

View File

@@ -213,6 +213,7 @@ you can do so in two different ways:
List of providers that support these features:
- [Docker](./docker.md#exposedbydefault)
- [ECS](./ecs.md#exposedbydefault)
- [Consul Catalog](./consul-catalog.md#exposedbydefault)
- [Nomad](./nomad.md#exposedbydefault)
- [Rancher](./rancher.md#exposedbydefault)
@@ -223,6 +224,7 @@ List of providers that support these features:
List of providers that support constraints:
- [Docker](./docker.md#constraints)
- [ECS](./ecs.md#constraints)
- [Consul Catalog](./consul-catalog.md#constraints)
- [Nomad](./nomad.md#constraints)
- [Rancher](./rancher.md#constraints)

View File

@@ -237,7 +237,7 @@ func headersRegexp(route *mux.Route, headers ...string) error {
func query(route *mux.Route, query ...string) error {
var queries []string
for _, elem := range query {
queries = append(queries, strings.Split(elem, "=")...)
queries = append(queries, strings.SplitN(elem, "=", 2)...)
}
route.Queries(queries...)

View File

@@ -252,6 +252,14 @@ func Test_addRoute(t *testing.T) {
"http://localhost/foo?bar=baz": http.StatusNotFound,
},
},
{
desc: "Query with multiple equals",
rule: "Query(`foo=b=ar`)",
expected: map[string]int{
"http://localhost/foo?foo=b=ar": http.StatusOK,
"http://localhost/foo?foo=bar": http.StatusNotFound,
},
},
{
desc: "Rule with simple path",
rule: `Path("/a")`,

View File

@@ -397,7 +397,7 @@ func (p *Provider) resolveDomains(ctx context.Context, domains []string, tlsStor
return
}
err = p.addCertificateForDomain(dom, cert.Certificate, cert.PrivateKey, tlsStore)
err = p.addCertificateForDomain(dom, cert, tlsStore)
if err != nil {
logger.WithError(err).Error("Error adding certificate for domain")
}
@@ -431,7 +431,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
return
}
err = p.addCertificateForDomain(dom, cert.Certificate, cert.PrivateKey, traefiktls.DefaultTLSStoreName)
err = p.addCertificateForDomain(dom, cert, traefiktls.DefaultTLSStoreName)
if err != nil {
logger.WithError(err).Error("Error adding certificate for domain")
}
@@ -468,7 +468,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
return
}
err = p.addCertificateForDomain(dom, cert.Certificate, cert.PrivateKey, traefiktls.DefaultTLSStoreName)
err = p.addCertificateForDomain(dom, cert, traefiktls.DefaultTLSStoreName)
if err != nil {
logger.WithError(err).Error("Error adding certificate for domain")
}
@@ -535,7 +535,7 @@ func (p *Provider) watchNewDomains(ctx context.Context) {
domain.SANs = validDomains[1:]
}
err = p.addCertificateForDomain(domain, cert.Certificate, cert.PrivateKey, traefiktls.DefaultTLSStoreName)
err = p.addCertificateForDomain(domain, cert, traefiktls.DefaultTLSStoreName)
if err != nil {
logger.WithError(err).Error("Error adding certificate for domain")
}
@@ -660,11 +660,15 @@ func (p *Provider) removeResolvingDomains(resolvingDomains []string) {
}
}
func (p *Provider) addCertificateForDomain(domain types.Domain, certificate, key []byte, tlsStore string) error {
func (p *Provider) addCertificateForDomain(domain types.Domain, crt *certificate.Resource, tlsStore string) error {
if crt == nil {
return nil
}
p.certificatesMu.Lock()
defer p.certificatesMu.Unlock()
cert := Certificate{Certificate: certificate, Key: key, Domain: domain}
cert := Certificate{Certificate: crt.Certificate, Key: crt.PrivateKey, Domain: domain}
certUpdated := false
for _, domainsCertificate := range p.certificates {
@@ -828,7 +832,7 @@ func (p *Provider) renewCertificates(ctx context.Context, renewPeriod time.Durat
continue
}
err = p.addCertificateForDomain(cert.Domain, renewedCert.Certificate, renewedCert.PrivateKey, cert.Store)
err = p.addCertificateForDomain(cert.Domain, renewedCert, cert.Store)
if err != nil {
logger.WithError(err).Error("Error adding certificate for domain")
}

View File

@@ -195,29 +195,27 @@ func (p *Provider) addServerTCP(item itemData, loadBalancer *dynamic.TCPServersL
return errors.New("load-balancer is not defined")
}
var port string
if len(loadBalancer.Servers) > 0 {
port = loadBalancer.Servers[0].Port
}
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.TCPServer{{}}
}
if item.Port != "" && port == "" {
port = item.Port
}
loadBalancer.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if item.Address == "" {
return errors.New("address is missing")
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = item.Port
}
if port == "" {
return errors.New("port is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port)
return nil
}
@@ -230,21 +228,23 @@ func (p *Provider) addServerUDP(item itemData, loadBalancer *dynamic.UDPServersL
loadBalancer.Servers = []dynamic.UDPServer{{}}
}
var port string
if item.Port != "" {
if item.Address == "" {
return errors.New("address is missing")
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = item.Port
loadBalancer.Servers[0].Port = ""
}
if port == "" {
return errors.New("port is missing")
}
if item.Address == "" {
return errors.New("address is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(item.Address, port)
return nil
}
@@ -253,11 +253,6 @@ func (p *Provider) addServer(item itemData, loadBalancer *dynamic.ServersLoadBal
return errors.New("load-balancer is not defined")
}
var port string
if len(loadBalancer.Servers) > 0 {
port = loadBalancer.Servers[0].Port
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{}
server.SetDefaults()
@@ -265,17 +260,19 @@ func (p *Provider) addServer(item itemData, loadBalancer *dynamic.ServersLoadBal
loadBalancer.Servers = []dynamic.Server{server}
}
if item.Port != "" && port == "" {
port = item.Port
if item.Address == "" {
return errors.New("address is missing")
}
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
port = item.Port
}
if item.Address == "" {
return errors.New("address is missing")
if port == "" {
return errors.New("port is missing")
}
scheme := loadBalancer.Servers[0].Scheme

View File

@@ -2220,7 +2220,7 @@ func Test_buildConfiguration(t *testing.T) {
Labels: map[string]string{
"traefik.tcp.routers.foo.rule": "HostSNI(`foo.bar`)",
"traefik.tcp.routers.foo.tls.options": "foo",
"traefik.tcp.services.foo.loadbalancer.server.port": "80",
"traefik.tcp.services.foo.loadbalancer.server.port": "8080",
},
Address: "127.0.0.1",
Port: "80",
@@ -2244,7 +2244,7 @@ func Test_buildConfiguration(t *testing.T) {
LoadBalancer: &dynamic.TCPServersLoadBalancer{
Servers: []dynamic.TCPServer{
{
Address: "127.0.0.1:80",
Address: "127.0.0.1:8080",
},
},
TerminationDelay: Int(100),
@@ -2858,6 +2858,57 @@ func Test_buildConfiguration(t *testing.T) {
},
},
},
{
desc: "UDP service with labels only",
ConnectAware: true,
items: []itemData{
{
ID: "1",
Node: "Node1",
Datacenter: "dc1",
Name: "Test",
Namespace: "ns",
Labels: map[string]string{
"traefik.udp.routers.test-udp-label.service": "test-udp-label-service",
"traefik.udp.routers.test-udp-label.entryPoints": "udp",
"traefik.udp.services.test-udp-label-service.loadBalancer.server.port": "21116",
},
Address: "127.0.0.1",
Port: "80",
Status: api.HealthPassing,
},
},
expected: &dynamic.Configuration{
TCP: &dynamic.TCPConfiguration{
Routers: map[string]*dynamic.TCPRouter{},
Middlewares: map[string]*dynamic.TCPMiddleware{},
Services: map[string]*dynamic.TCPService{},
},
UDP: &dynamic.UDPConfiguration{
Routers: map[string]*dynamic.UDPRouter{
"test-udp-label": {
EntryPoints: []string{"udp"},
Service: "test-udp-label-service",
},
},
Services: map[string]*dynamic.UDPService{
"test-udp-label-service": {
LoadBalancer: &dynamic.UDPServersLoadBalancer{
Servers: []dynamic.UDPServer{
{Address: "127.0.0.1:21116"},
},
},
},
},
},
HTTP: &dynamic.HTTPConfiguration{
Routers: map[string]*dynamic.Router{},
Middlewares: map[string]*dynamic.Middleware{},
Services: map[string]*dynamic.Service{},
ServersTransports: map[string]*dynamic.ServersTransport{},
},
},
},
}
for _, test := range testCases {

View File

@@ -196,28 +196,24 @@ func (p *Provider) addServerTCP(ctx context.Context, container dockerData, loadB
return errors.New("load-balancer is not defined")
}
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.TCPServer{{}}
}
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.TCPServer{}
loadBalancer.Servers = []dynamic.TCPServer{server}
}
if port == "" {
return errors.New("port is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil
}
@@ -226,28 +222,24 @@ func (p *Provider) addServerUDP(ctx context.Context, container dockerData, loadB
return errors.New("load-balancer is not defined")
}
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.UDPServer{{}}
}
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.UDPServer{}
loadBalancer.Servers = []dynamic.UDPServer{server}
}
if port == "" {
return errors.New("port is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil
}
@@ -256,17 +248,6 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala
return errors.New("load-balancer is not defined")
}
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
}
ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{}
server.SetDefaults()
@@ -274,6 +255,14 @@ func (p *Provider) addServer(ctx context.Context, container dockerData, loadBala
loadBalancer.Servers = []dynamic.Server{server}
}
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(ctx, container, serverPort)
if err != nil {
return err
}
if port == "" {
return errors.New("port is missing")
}

View File

@@ -185,7 +185,7 @@ func (p *Provider) filterInstance(ctx context.Context, instance ecsInstance) boo
matches, err := constraints.MatchLabels(instance.Labels, p.Constraints)
if err != nil {
logger.Errorf("Error matching constraints expression: %v", err)
logger.Errorf("Error matching constraint expression: %v", err)
return false
}
if !matches {
@@ -201,28 +201,24 @@ func (p *Provider) addServerTCP(instance ecsInstance, loadBalancer *dynamic.TCPS
return errors.New("load-balancer is not defined")
}
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.TCPServer{{}}
}
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(instance, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.TCPServer{}
loadBalancer.Servers = []dynamic.TCPServer{server}
}
if port == "" {
return errors.New("port is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil
}
@@ -231,28 +227,24 @@ func (p *Provider) addServerUDP(instance ecsInstance, loadBalancer *dynamic.UDPS
return errors.New("load-balancer is not defined")
}
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if len(loadBalancer.Servers) == 0 {
loadBalancer.Servers = []dynamic.UDPServer{{}}
}
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(instance, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.UDPServer{}
loadBalancer.Servers = []dynamic.UDPServer{server}
}
if port == "" {
return errors.New("port is missing")
}
loadBalancer.Servers[0].Address = net.JoinHostPort(ip, port)
return nil
}
@@ -261,17 +253,6 @@ func (p *Provider) addServer(instance ecsInstance, loadBalancer *dynamic.Servers
return errors.New("load-balancer is not defined")
}
var serverPort string
if len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
}
ip, port, err := p.getIPPort(instance, serverPort)
if err != nil {
return err
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{}
server.SetDefaults()
@@ -279,6 +260,14 @@ func (p *Provider) addServer(instance ecsInstance, loadBalancer *dynamic.Servers
loadBalancer.Servers = []dynamic.Server{server}
}
serverPort := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
ip, port, err := p.getIPPort(instance, serverPort)
if err != nil {
return err
}
if port == "" {
return errors.New("port is missing")
}

View File

@@ -175,29 +175,27 @@ func (p *Provider) addServerTCP(i item, lb *dynamic.TCPServersLoadBalancer) erro
return errors.New("load-balancer is missing")
}
var port string
if len(lb.Servers) > 0 {
port = lb.Servers[0].Port
}
if len(lb.Servers) == 0 {
lb.Servers = []dynamic.TCPServer{{}}
}
if i.Port != 0 && port == "" {
port = strconv.Itoa(i.Port)
}
lb.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if i.Address == "" {
return errors.New("address is missing")
}
port := lb.Servers[0].Port
lb.Servers[0].Port = ""
if port == "" && i.Port > 0 {
port = strconv.Itoa(i.Port)
}
if port == "" {
return errors.New("port is missing")
}
lb.Servers[0].Address = net.JoinHostPort(i.Address, port)
return nil
}
@@ -206,29 +204,27 @@ func (p *Provider) addServerUDP(i item, lb *dynamic.UDPServersLoadBalancer) erro
return errors.New("load-balancer is missing")
}
var port string
if len(lb.Servers) > 0 {
port = lb.Servers[0].Port
}
if len(lb.Servers) == 0 {
lb.Servers = []dynamic.UDPServer{{}}
}
if i.Port != 0 && port == "" {
port = strconv.Itoa(i.Port)
}
lb.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if i.Address == "" {
return errors.New("address is missing")
}
port := lb.Servers[0].Port
lb.Servers[0].Port = ""
if port == "" && i.Port > 0 {
port = strconv.Itoa(i.Port)
}
if port == "" {
return errors.New("port is missing")
}
lb.Servers[0].Address = net.JoinHostPort(i.Address, port)
return nil
}
@@ -237,11 +233,6 @@ func (p *Provider) addServer(i item, lb *dynamic.ServersLoadBalancer) error {
return errors.New("load-balancer is missing")
}
var port string
if len(lb.Servers) > 0 {
port = lb.Servers[0].Port
}
if len(lb.Servers) == 0 {
server := dynamic.Server{}
server.SetDefaults()
@@ -249,19 +240,21 @@ func (p *Provider) addServer(i item, lb *dynamic.ServersLoadBalancer) error {
lb.Servers = []dynamic.Server{server}
}
if i.Port != 0 && port == "" {
if i.Address == "" {
return errors.New("address is missing")
}
port := lb.Servers[0].Port
lb.Servers[0].Port = ""
if port == "" && i.Port > 0 {
port = strconv.Itoa(i.Port)
}
lb.Servers[0].Port = ""
if port == "" {
return errors.New("port is missing")
}
if i.Address == "" {
return errors.New("address is missing")
}
scheme := lb.Servers[0].Scheme
lb.Servers[0].Scheme = ""
lb.Servers[0].URL = fmt.Sprintf("%s://%s", scheme, net.JoinHostPort(i.Address, port))

View File

@@ -160,7 +160,7 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
matches, err := constraints.MatchLabels(service.Labels, p.Constraints)
if err != nil {
logger.Errorf("Error matching constraints expression: %v", err)
logger.Errorf("Error matching constraint expression: %v", err)
return false
}
if !matches {
@@ -185,23 +185,19 @@ func (p *Provider) keepService(ctx context.Context, service rancherData) bool {
func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBalancer *dynamic.TCPServersLoadBalancer) error {
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
serverPort := ""
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
if loadBalancer == nil {
return errors.New("load-balancer is not defined")
}
port := getServicePort(service)
if len(loadBalancer.Servers) == 0 {
server := dynamic.TCPServer{}
loadBalancer.Servers = []dynamic.TCPServer{server}
loadBalancer.Servers = []dynamic.TCPServer{{}}
}
if serverPort != "" {
port = serverPort
loadBalancer.Servers[0].Port = ""
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
}
if port == "" {
@@ -216,29 +212,26 @@ func (p *Provider) addServerTCP(ctx context.Context, service rancherData, loadBa
}
loadBalancer.Servers = servers
return nil
}
func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBalancer *dynamic.UDPServersLoadBalancer) error {
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
serverPort := ""
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
serverPort = loadBalancer.Servers[0].Port
if loadBalancer == nil {
return errors.New("load-balancer is not defined")
}
port := getServicePort(service)
if len(loadBalancer.Servers) == 0 {
server := dynamic.UDPServer{}
loadBalancer.Servers = []dynamic.UDPServer{server}
loadBalancer.Servers = []dynamic.UDPServer{{}}
}
if serverPort != "" {
port = serverPort
loadBalancer.Servers[0].Port = ""
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
}
if port == "" {
@@ -253,14 +246,16 @@ func (p *Provider) addServerUDP(ctx context.Context, service rancherData, loadBa
}
loadBalancer.Servers = servers
return nil
}
func (p *Provider) addServers(ctx context.Context, service rancherData, loadBalancer *dynamic.ServersLoadBalancer) error {
log.FromContext(ctx).Debugf("Trying to add servers for service %s \n", service.Name)
serverPort := getLBServerPort(loadBalancer)
port := getServicePort(service)
if loadBalancer == nil {
return errors.New("load-balancer is not defined")
}
if len(loadBalancer.Servers) == 0 {
server := dynamic.Server{}
@@ -269,9 +264,11 @@ func (p *Provider) addServers(ctx context.Context, service rancherData, loadBala
loadBalancer.Servers = []dynamic.Server{server}
}
if serverPort != "" {
port = serverPort
loadBalancer.Servers[0].Port = ""
port := loadBalancer.Servers[0].Port
loadBalancer.Servers[0].Port = ""
if port == "" {
port = getServicePort(service)
}
if port == "" {
@@ -286,14 +283,8 @@ func (p *Provider) addServers(ctx context.Context, service rancherData, loadBala
}
loadBalancer.Servers = servers
return nil
}
func getLBServerPort(loadBalancer *dynamic.ServersLoadBalancer) string {
if loadBalancer != nil && len(loadBalancer.Servers) > 0 {
return loadBalancer.Servers[0].Port
}
return ""
return nil
}
func getServicePort(data rancherData) string {

View File

@@ -15,6 +15,7 @@ import (
ptypes "github.com/traefik/paerser/types"
"github.com/traefik/traefik/v2/pkg/config/dynamic"
"github.com/traefik/traefik/v2/pkg/log"
"golang.org/x/net/http/httpguts"
)
// StatusClientClosedRequest non-standard HTTP status code for client disconnection.
@@ -67,16 +68,18 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
// some servers need Sec-WebSocket-Key, Sec-WebSocket-Extensions, Sec-WebSocket-Accept,
// Sec-WebSocket-Protocol and Sec-WebSocket-Version to be case-sensitive.
// https://tools.ietf.org/html/rfc6455#page-20
outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
outReq.Header["Sec-WebSocket-Extensions"] = outReq.Header["Sec-Websocket-Extensions"]
outReq.Header["Sec-WebSocket-Accept"] = outReq.Header["Sec-Websocket-Accept"]
outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"]
delete(outReq.Header, "Sec-Websocket-Key")
delete(outReq.Header, "Sec-Websocket-Extensions")
delete(outReq.Header, "Sec-Websocket-Accept")
delete(outReq.Header, "Sec-Websocket-Protocol")
delete(outReq.Header, "Sec-Websocket-Version")
if isWebSocketUpgrade(outReq) {
outReq.Header["Sec-WebSocket-Key"] = outReq.Header["Sec-Websocket-Key"]
outReq.Header["Sec-WebSocket-Extensions"] = outReq.Header["Sec-Websocket-Extensions"]
outReq.Header["Sec-WebSocket-Accept"] = outReq.Header["Sec-Websocket-Accept"]
outReq.Header["Sec-WebSocket-Protocol"] = outReq.Header["Sec-Websocket-Protocol"]
outReq.Header["Sec-WebSocket-Version"] = outReq.Header["Sec-Websocket-Version"]
delete(outReq.Header, "Sec-Websocket-Key")
delete(outReq.Header, "Sec-Websocket-Extensions")
delete(outReq.Header, "Sec-Websocket-Accept")
delete(outReq.Header, "Sec-Websocket-Protocol")
delete(outReq.Header, "Sec-Websocket-Version")
}
},
Transport: roundTripper,
FlushInterval: time.Duration(flushInterval),
@@ -112,6 +115,14 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
return proxy, nil
}
func isWebSocketUpgrade(req *http.Request) bool {
if !httpguts.HeaderValuesContainsToken(req.Header["Connection"], "Upgrade") {
return false
}
return strings.EqualFold(req.Header.Get("Upgrade"), "websocket")
}
func statusText(statusCode int) string {
if statusCode == StatusClientClosedRequest {
return StatusClientClosedRequestText

View File

@@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file"
FileName = "traefik_changelog.md"
# example new bugfix v2.8.5
# example new bugfix v2.8.6
CurrentRef = "v2.8"
PreviousRef = "v2.8.4"
PreviousRef = "v2.8.5"
BaseBranch = "v2.8"
FutureCurrentRefName = "v2.8.5"
FutureCurrentRefName = "v2.8.6"
ThresholdPreviousRef = 10
ThresholdCurrentRef = 10

View File

@@ -4,11 +4,11 @@ RepositoryName = "traefik"
OutputType = "file"
FileName = "traefik_changelog.md"
# example RC3 of v2.9.0
# example RC4 of v2.9.0
CurrentRef = "v2.9"
PreviousRef = "v2.9.0-rc2"
PreviousRef = "v2.9.0-rc3"
BaseBranch = "v2.9"
FutureCurrentRefName = "v2.9.0-rc3"
FutureCurrentRefName = "v2.9.0-rc4"
ThresholdPreviousRef = 10
ThresholdCurrentRef = 10