mirror of
https://github.com/containous/traefik.git
synced 2025-09-24 21:44:26 +03:00
Compare commits
29 Commits
v2.8.0-rc1
...
v2.8.1
Author | SHA1 | Date | |
---|---|---|---|
|
c9520480c2 | ||
|
05c3486347 | ||
|
0231db05b4 | ||
|
8f6463ba7a | ||
|
28da781194 | ||
|
51a02caea3 | ||
|
839bc7b3a8 | ||
|
9c79fafeeb | ||
|
9c4b336f3b | ||
|
aa8fda5eae | ||
|
8b22101236 | ||
|
03598d395b | ||
|
9d61cb64a2 | ||
|
62e17c659e | ||
|
41748c3ae4 | ||
|
65a317010b | ||
|
a887794313 | ||
|
77e1ce2877 | ||
|
470a4f6e5f | ||
|
94141233f0 | ||
|
ff17ac53df | ||
|
55ba4356f2 | ||
|
804b0ff2f2 | ||
|
818541d4d7 | ||
|
1b199730d2 | ||
|
6e535f8cef | ||
|
23340c46e6 | ||
|
5c15f5fe04 | ||
|
ba7e9ed788 |
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
4
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -3,11 +3,11 @@ PLEASE READ THIS MESSAGE.
|
||||
|
||||
Documentation fixes or enhancements:
|
||||
- for Traefik v1: use branch v1.7
|
||||
- for Traefik v2: use branch v2.7
|
||||
- for Traefik v2: use branch v2.8
|
||||
|
||||
Bug fixes:
|
||||
- for Traefik v1: use branch v1.7
|
||||
- for Traefik v2: use branch v2.7
|
||||
- for Traefik v2: use branch v2.8
|
||||
|
||||
Enhancements:
|
||||
- for Traefik v1: we only accept bug fixes
|
||||
|
83
CHANGELOG.md
83
CHANGELOG.md
@@ -1,3 +1,86 @@
|
||||
## [v2.8.1](https://github.com/traefik/traefik/tree/v2.8.1) (2022-07-11)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.0...v2.8.1)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[kv]** Upgrade valkeyrie to v0.4.1 ([#9161](https://github.com/traefik/traefik/pull/9161) by [moutoum](https://github.com/moutoum))
|
||||
- **[middleware,metrics]** Improve performances when Prometheus metrics are enabled ([#9168](https://github.com/traefik/traefik/pull/9168) by [juliens](https://github.com/juliens))
|
||||
- **[middleware]** Support forwarded websocket protocol in RedirectScheme ([#9159](https://github.com/traefik/traefik/pull/9159) by [moutoum](https://github.com/moutoum))
|
||||
|
||||
**Documentation:**
|
||||
- Update the language for advocating page ([#9169](https://github.com/traefik/traefik/pull/9169) by [tfny](https://github.com/tfny))
|
||||
- Add callout for anyone using Traefik to manage commercial applications ([#9152](https://github.com/traefik/traefik/pull/9152) by [tomatokoolaid](https://github.com/tomatokoolaid))
|
||||
- Update deprecation notices ([#9149](https://github.com/traefik/traefik/pull/9149) by [ddtmachado](https://github.com/ddtmachado))
|
||||
|
||||
## [v2.8.0](https://github.com/traefik/traefik/tree/v2.8.0) (2022-06-29)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.0-rc1...v2.8.0)
|
||||
|
||||
**Enhancements:**
|
||||
- **[consul,consulcatalog]** Support multiple namespaces for Consul and ConsulCatalog providers ([#8979](https://github.com/traefik/traefik/pull/8979) by [rtribotte](https://github.com/rtribotte))
|
||||
- **[http3]** Upgrade quic-go to v0.27.0 ([#8922](https://github.com/traefik/traefik/pull/8922) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[http3]** Upgrade quic-go to v0.26.0 ([#8874](https://github.com/traefik/traefik/pull/8874) by [sylr](https://github.com/sylr))
|
||||
- **[logs]** Add destination address to debug log ([#9032](https://github.com/traefik/traefik/pull/9032) by [qmloong](https://github.com/qmloong))
|
||||
- **[middleware,provider,tls]** Deprecate caOptional option in client TLS configuration ([#8960](https://github.com/traefik/traefik/pull/8960) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[middleware]** Support URL replacement in errors middleware ([#8956](https://github.com/traefik/traefik/pull/8956) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[middleware]** Allow config of additional CircuitBreaker params ([#8907](https://github.com/traefik/traefik/pull/8907) by [aidy](https://github.com/aidy))
|
||||
- **[provider]** Implement Traefik provider for Nomad orchestrator ([#9018](https://github.com/traefik/traefik/pull/9018) by [shoenig](https://github.com/shoenig))
|
||||
- **[server]** Allow HTTP/2 max concurrent stream configuration ([#8781](https://github.com/traefik/traefik/pull/8781) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- **[tls,k8s/crd]** Support certificates configuration in TLSStore CRD ([#8976](https://github.com/traefik/traefik/pull/8976) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[webui,pilot,hub]** Add Traefik Hub button and deprecate Pilot ([#9091](https://github.com/traefik/traefik/pull/9091) by [ldez](https://github.com/ldez))
|
||||
- **[webui,plugins]** Reach the catalog of plugins from the Traefik dashboard ([#9055](https://github.com/traefik/traefik/pull/9055) by [seedy](https://github.com/seedy))
|
||||
|
||||
**Bug fixes:**
|
||||
- **[nomad]** Use configured token in the Nomad client ([#9111](https://github.com/traefik/traefik/pull/9111) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
**Documentation:**
|
||||
- Prepare release v2.8.0-rc2 ([#9134](https://github.com/traefik/traefik/pull/9134) by [rtribotte](https://github.com/rtribotte))
|
||||
- Prepare release v2.8.0-rc1 ([#9097](https://github.com/traefik/traefik/pull/9097) by [rtribotte](https://github.com/rtribotte))
|
||||
|
||||
**Misc:**
|
||||
- Merge current v2.7 into v2.8 ([#9142](https://github.com/traefik/traefik/pull/9142) by [rtribotte](https://github.com/rtribotte))
|
||||
- Merge current v2.7 into v2.8 ([#9133](https://github.com/traefik/traefik/pull/9133) by [rtribotte](https://github.com/rtribotte))
|
||||
- Merge current v2.7 into master ([#9095](https://github.com/traefik/traefik/pull/9095) by [rtribotte](https://github.com/rtribotte))
|
||||
- Merge current v2.7 into master ([#9085](https://github.com/traefik/traefik/pull/9085) by [tomMoulard](https://github.com/tomMoulard))
|
||||
- Merge current v2.7 into master ([#9060](https://github.com/traefik/traefik/pull/9060) by [rtribotte](https://github.com/rtribotte))
|
||||
- Merge current v2.7 into master ([#9052](https://github.com/traefik/traefik/pull/9052) by [rtribotte](https://github.com/rtribotte))
|
||||
- Merge current v2.7 into master ([#8959](https://github.com/traefik/traefik/pull/8959) by [tomMoulard](https://github.com/tomMoulard))
|
||||
|
||||
## [v2.7.3](https://github.com/traefik/traefik/tree/v2.7.3) (2022-06-29)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.7.2...v2.7.3)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[metrics]** Ensure Datadog client is cleanly stopped ([#9137](https://github.com/traefik/traefik/pull/9137) by [jbdoumenjou](https://github.com/jbdoumenjou))
|
||||
|
||||
**Documentation:**
|
||||
- **[middleware,k8s/crd]** Add documentation for main, SANs and plugin CRD fields ([#9136](https://github.com/traefik/traefik/pull/9136) by [mloiseleur](https://github.com/mloiseleur))
|
||||
|
||||
## [v2.8.0-rc2](https://github.com/traefik/traefik/tree/v2.8.0-rc2) (2022-06-27)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.8.0-rc1...v2.8.0-rc2)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[nomad]** Use configured token in the Nomad client ([#9111](https://github.com/traefik/traefik/pull/9111) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
**Misc:**
|
||||
- Merge current v2.7 into v2.8 ([#9133](https://github.com/traefik/traefik/pull/9133) by [rtribotte](https://github.com/rtribotte))
|
||||
|
||||
## [v2.7.2](https://github.com/traefik/traefik/tree/v2.7.2) (2022-06-27)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.7.1...v2.7.2)
|
||||
|
||||
**Bug fixes:**
|
||||
- **[healthcheck,service]** Do not make multiple requests to the same URL for balancer healthcheck ([#8632](https://github.com/traefik/traefik/pull/8632) by [TPXP](https://github.com/TPXP))
|
||||
- **[healthcheck,service]** Add log when missing path in health check ([#9104](https://github.com/traefik/traefik/pull/9104) by [moutoum](https://github.com/moutoum))
|
||||
- **[k8s/gatewayapi]** Allow multiple listeners on same port in Gateway API provider ([#9107](https://github.com/traefik/traefik/pull/9107) by [burner-account](https://github.com/burner-account))
|
||||
- **[middleware]** RedirectScheme redirects based on X-Forwarded-Proto header ([#9121](https://github.com/traefik/traefik/pull/9121) by [moutoum](https://github.com/moutoum))
|
||||
- **[plugins]** Update yaegi to v0.13.0 ([#9118](https://github.com/traefik/traefik/pull/9118) by [kevinpollet](https://github.com/kevinpollet))
|
||||
- **[rules]** Fix HostRegexp and Query muxers ([#9131](https://github.com/traefik/traefik/pull/9131) by [juliens](https://github.com/juliens))
|
||||
- **[tracing]** Update DataDog tracing dependency to v1.38.1 ([#9105](https://github.com/traefik/traefik/pull/9105) by [kevinpollet](https://github.com/kevinpollet))
|
||||
|
||||
**Documentation:**
|
||||
- **[acme,k8s/crd]** Add documentation to Traefik CRD properties ([#9096](https://github.com/traefik/traefik/pull/9096) by [mloiseleur](https://github.com/mloiseleur))
|
||||
- **[middleware]** Add missing info.serialNumber option to PassTLSClientCert middleware ([#9115](https://github.com/traefik/traefik/pull/9115) by [miteshjadia](https://github.com/miteshjadia))
|
||||
- **[tcp]** Add a note on how to handle server first protocols ([#9002](https://github.com/traefik/traefik/pull/9002) by [romantomjak](https://github.com/romantomjak))
|
||||
- Update to improve info section relevance ([#9130](https://github.com/traefik/traefik/pull/9130) by [tomatokoolaid](https://github.com/tomatokoolaid))
|
||||
- Added useful links for commercial applications ([#9129](https://github.com/traefik/traefik/pull/9129) by [tomatokoolaid](https://github.com/tomatokoolaid))
|
||||
|
||||
## [v2.8.0-rc1](https://github.com/traefik/traefik/tree/v2.8.0-rc1) (2022-06-13)
|
||||
[All Commits](https://github.com/traefik/traefik/compare/v2.7.0-rc1...v2.8.0-rc1)
|
||||
|
||||
|
@@ -8,8 +8,24 @@ description: "There are many ways to contribute to Traefik Proxy. If you're talk
|
||||
Spread the Love & Tell Us about It
|
||||
{: .subtitle }
|
||||
|
||||
There are many ways to contribute to the project, and there is one that always spark joy: when we see/read about users talking about how Traefik helps them solve their problems.
|
||||
Traefik Proxy was started by the community for the community.
|
||||
You can contribute to the Traefik community in three main ways:
|
||||
|
||||
If you're talking about Traefik, [let us know](https://traefik.io/submit-my-contribution/) and we'll promote your enthusiasm!
|
||||
**Spread the word!** Guides, videos, blog posts, how-to articles, and showing off your network design all help spread the word about Traefik Proxy
|
||||
and teach others in the community how to best implement it.
|
||||
It always sparks joy when users share how Traefik Proxy helps them solve their problems.
|
||||
If you are talking about Traefik Proxy, [let us know](https://traefik.io/submit-my-contribution/) and we will promote your work and reward your enthusiasm!
|
||||
If you are giving a talk that includes or is about Traefik Proxy, [let us know](https://traefik.io/submit-my-contribution/) and we will send you swag and stickers for your time at the conference.
|
||||
If you have written about Traefik or shared useful information you would like to promote, feel free to add links to the [dedicated wiki page on GitHub](https://github.com/traefik/traefik/wiki/Awesome-Traefik).
|
||||
|
||||
Also, if you've written about Traefik or shared useful information you'd like to promote, feel free to add links in the [dedicated wiki page on Github](https://github.com/traefik/traefik/wiki/Awesome-Traefik).
|
||||
**Help community members!** Everyone needs a place to share their cool innovations or get help with that pesky bug that only a different pair of eyes seems to be able to see.
|
||||
Join our [Community Forum](https://community.traefik.io/) where you can ask questions, help out other users, and share your neat configuration examples or snippets.
|
||||
Top contributors will be asked to join the Ambassador program and get unique swag to celebrate!
|
||||
|
||||
**Build cool solutions!** Traefik Proxy would be so much better if only it had…
|
||||
We love all the wonderful ideas that our users come up with, but we can only build so much.
|
||||
Luckily, as an open source community, our users can help by [building awesome features](https://github.com/orgs/traefik/projects/9/views/7), enhancements, or bug fixes.
|
||||
We are a big community, so we do need to prioritize a bit.
|
||||
That is why we use the tag `contributor/wanted` to let you know which pull requests will make it to the front of the queue for design support and review.
|
||||
Feel free to grab one of these and run with it.
|
||||
Top contributors get unique swag to celebrate.
|
||||
|
@@ -4,9 +4,9 @@ This page is maintained and updated periodically to reflect our roadmap and any
|
||||
|
||||
| Feature | Deprecated | End of Support | Removal |
|
||||
|---------------------------------------------------------------|------------|----------------|---------|
|
||||
| [Pilot Dashboard (Metrics)](#pilot-dashboard-metrics) | 2.7 | 2.8 | 2.9 |
|
||||
| [Pilot Plugins](#pilot-plugins) | 2.7 | 2.8 | 2.9 |
|
||||
| [Consul Enterprise Namespaces](#consul-enterprise-namespaces) | 2.8 | TBD | TBD |
|
||||
| [Pilot Dashboard (Metrics)](#pilot-dashboard-metrics) | 2.7 | 2.8 | 3.0 |
|
||||
| [Pilot Plugins](#pilot-plugins) | 2.7 | 2.8 | 3.0 |
|
||||
| [Consul Enterprise Namespace](#consul-enterprise-namespace) | 2.8 | N/A | 3.0 |
|
||||
|
||||
## Impact
|
||||
|
||||
@@ -20,7 +20,7 @@ In 2.9, the Pilot platform and all Traefik integration code will be permanently
|
||||
Starting on 2.7 the pilot token will not be a requirement anymore.
|
||||
At 2.9, a new plugin catalog home should be available, decoupled from pilot.
|
||||
|
||||
### Consul Enterprise Namespaces
|
||||
### Consul Enterprise Namespace
|
||||
|
||||
Starting on 2.8 the `namespace` option of Consul and Consul Catalog providers is deprecated,
|
||||
please use the `namespaces` options instead.
|
||||
|
@@ -6,7 +6,9 @@ Below is a non-exhaustive list of versions and their maintenance status:
|
||||
|
||||
| Version | Release Date | Active Support | Security Support |
|
||||
|---------|--------------|--------------------|------------------|
|
||||
| 2.6 | Jan 24, 2022 | Yes | Yes |
|
||||
| 2.8 | Jun 29, 2022 | Yes | Yes |
|
||||
| 2.7 | May 24, 2022 | Ended Jun 29, 2022 | No |
|
||||
| 2.6 | Jan 24, 2022 | Ended May 24, 2022 | No |
|
||||
| 2.5 | Aug 17, 2021 | Ended Jan 24, 2022 | No |
|
||||
| 2.4 | Jan 19, 2021 | Ended Aug 17, 2021 | No |
|
||||
| 2.3 | Sep 23, 2020 | Ended Jan 19, 2021 | No |
|
||||
|
@@ -93,3 +93,18 @@ All available environment variables can be found [here](../reference/static-conf
|
||||
All the configuration options are documented in their related section.
|
||||
|
||||
You can browse the available features in the menu, the [providers](../providers/overview.md), or the [routing section](../routing/overview.md) to see them in action.
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -178,3 +178,18 @@ And run it:
|
||||
## Compile your Binary from the Sources
|
||||
|
||||
All the details are available in the [Contributing Guide](../contributing/building-testing.md)
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -113,4 +113,20 @@ IP: 172.27.0.4
|
||||
```
|
||||
|
||||
!!! question "Where to Go Next?"
|
||||
|
||||
Now that you have a basic understanding of how Traefik can automatically create the routes to your services and load balance them, it is time to dive into [the documentation](/) and let Traefik work for you!
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -293,112 +293,112 @@ For example, `CF_API_EMAIL_FILE=/run/secrets/traefik_cf-api-email` could be used
|
||||
|
||||
For complete details, refer to your provider's _Additional configuration_ link.
|
||||
|
||||
| Provider Name | Provider Code | Environment Variables | |
|
||||
|-------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
|
||||
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) |
|
||||
| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) |
|
||||
| [all-inkl](https://all-inkl.com) | `allinkl` | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl) |
|
||||
| [ArvanCloud](https://www.arvancloud.com/en) | `arvancloud` | `ARVANCLOUD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud) |
|
||||
| [Auroradns](https://www.pcextreme.com/dns-health-checks) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) |
|
||||
| [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) |
|
||||
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) |
|
||||
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) |
|
||||
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) |
|
||||
| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) |
|
||||
| [CloudDNS](https://vshosting.eu/) | `clouddns` | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns) |
|
||||
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) |
|
||||
| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) |
|
||||
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) |
|
||||
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) |
|
||||
| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) |
|
||||
| [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) |
|
||||
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) |
|
||||
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) |
|
||||
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) |
|
||||
| [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod) |
|
||||
| [Domain Offensive (do.de)](https://www.do.de/) | `dode` | `DODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/dode) |
|
||||
| [Domeneshop](https://domene.shop) | `domeneshop` | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop) |
|
||||
| [DreamHost](https://www.dreamhost.com/) | `dreamhost` | `DREAMHOST_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost) |
|
||||
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns) |
|
||||
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/dyn) |
|
||||
| [Dynu](https://www.dynu.com) | `dynu` | `DYNU_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dynu) |
|
||||
| [EasyDNS](https://easydns.com/) | `easydns` | `EASYDNS_TOKEN`, `EASYDNS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/easydns) |
|
||||
| [EdgeDNS](https://www.akamai.com/) | `edgedns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) |
|
||||
| [Epik](https://www.epik.com) | `epik` | `EPIK_SIGNATURE` | [Additional configuration](https://go-acme.github.io/lego/dns/epik) |
|
||||
| [Exoscale](https://www.exoscale.com) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale) |
|
||||
| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) |
|
||||
| [Freemyip.com](https://freemyip.com) | `freemyip` | `FREEMYIP_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip) |
|
||||
| [G-Core Lab](https://gcorelabs.com/dns/) | `gcore` | `GCORE_PERMANENT_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/gcore) |
|
||||
| [Gandi v5](https://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5) |
|
||||
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandi) |
|
||||
| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | [Additional configuration](https://go-acme.github.io/lego/dns/glesys) |
|
||||
| [GoDaddy](https://godaddy.com/) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy) |
|
||||
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`] | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud) |
|
||||
| [Hetzner](https://hetzner.com) | `hetzner` | `HETZNER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner) |
|
||||
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) |
|
||||
| [Hosttech](https://www.hosttech.eu) | `hosttech` | `HOSTTECH_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech) |
|
||||
| [Hurricane Electric](https://dns.he.net) | `hurricane` | `HURRICANE_TOKENS` [^6] | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane) |
|
||||
| [HyperOne](https://www.hyperone.com) | `hyperone` | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone) |
|
||||
| [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/) | `ibmcloud` | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud) |
|
||||
| [IIJ DNS Platform Service](https://www.iij.ad.jp) | `iijdpf` | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf) |
|
||||
| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iij) |
|
||||
| [Infoblox](https://www.infoblox.com/) | `infoblox` | `INFOBLOX_USER`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox) |
|
||||
| [Infomaniak](https://www.infomaniak.com) | `infomaniak` | `INFOMANIAK_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak) |
|
||||
| [Internet.bs](https://internetbs.net) | `internetbs` | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs) |
|
||||
| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/inwx) |
|
||||
| [ionos](https://ionos.com/) | `ionos` | `IONOS_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ionos) |
|
||||
| [iwantmyname](https://iwantmyname.com) | `iwantmyname` | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname) |
|
||||
| [Joker.com](https://joker.com) | `joker` | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/joker) |
|
||||
| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail) |
|
||||
| [Linode v4](https://www.linode.com) | `linode` | `LINODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/linode) |
|
||||
| [Liquid Web](https://www.liquidweb.com/) | `liquidweb` | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb) |
|
||||
| [Loopia](https://loopia.com/) | `loopia` | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER` | [Additional configuration](https://go-acme.github.io/lego/dns/loopia) |
|
||||
| [LuaDNS](https://luadns.com) | `luadns` | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/luadns) |
|
||||
| [MyDNS.jp](https://www.mydns.jp/) | `mydnsjp` | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp) |
|
||||
| [Mythic Beasts](https://www.mythic-beasts.com) | `mythicbeasts` | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts) |
|
||||
| [name.com](https://www.name.com/) | `namedotcom` | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom) |
|
||||
| [Namecheap](https://www.namecheap.com) | `namecheap` | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap) |
|
||||
| [Namesilo](https://www.namesilo.com/) | `namesilo` | `NAMESILO_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo) |
|
||||
| [Netcup](https://www.netcup.eu/) | `netcup` | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/netcup) |
|
||||
| [Netlify](https://www.netlify.com) | `netlify` | `NETLIFY_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/netlify) |
|
||||
| [Nicmanager](https://www.nicmanager.com) | `nicmanager` | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager) |
|
||||
| [NIFCloud](https://cloud.nifty.com/service/dns.htm) | `nifcloud` | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud) |
|
||||
| [Njalla](https://njal.la) | `njalla` | `NJALLA_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/njalla) |
|
||||
| [NS1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ns1) |
|
||||
| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/otc) |
|
||||
| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/designate) |
|
||||
| [Oracle Cloud](https://cloud.oracle.com/home) | `oraclecloud` | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud) |
|
||||
| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ovh) |
|
||||
| [Porkbun](https://porkbun.com/) | `porkbun` | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun) |
|
||||
| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/pdns) |
|
||||
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace) |
|
||||
| [reg.ru](https://www.reg.ru) | `regru` | `REGRU_USERNAME`, `REGRU_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/regru) |
|
||||
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) |
|
||||
| [RimuHosting](https://rimuhosting.com) | `rimuhosting` | `RIMUHOSTING_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting) |
|
||||
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) |
|
||||
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud) |
|
||||
| [Scaleway](https://www.scaleway.com) | `scaleway` | `SCALEWAY_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) |
|
||||
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) |
|
||||
| [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) |
|
||||
| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) |
|
||||
| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) |
|
||||
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
||||
| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) |
|
||||
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
||||
| [UKFast SafeDNS](https://www.ukfast.co.uk/dns-hosting.html) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) |
|
||||
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) |
|
||||
| [Vercel](https://vercel.com) | `vercel` | `VERCEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vercel) |
|
||||
| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) |
|
||||
| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) |
|
||||
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) |
|
||||
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) |
|
||||
| [WEDOS](https://www.wedos.com) | `wedos` | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/wedos) |
|
||||
| [Yandex](https://yandex.com) | `yandex` | `YANDEX_PDD_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandex) |
|
||||
| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee) |
|
||||
| [Zonomi](https://zonomi.com) | `zonomi` | `ZONOMI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi) |
|
||||
| External Program | `exec` | `EXEC_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/exec) |
|
||||
| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1] | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq) |
|
||||
| manual | `manual` | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press <kbd>Enter</kbd>. | |
|
||||
| Provider Name | Provider Code | Environment Variables | |
|
||||
|----------------------------------------------------------------------------------------------------|----------------|---------------------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------|
|
||||
| [ACME DNS](https://github.com/joohoi/acme-dns) | `acme-dns` | `ACME_DNS_API_BASE`, `ACME_DNS_STORAGE_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/acme-dns) |
|
||||
| [Alibaba Cloud](https://www.alibabacloud.com) | `alidns` | `ALICLOUD_ACCESS_KEY`, `ALICLOUD_SECRET_KEY`, `ALICLOUD_REGION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/alidns) |
|
||||
| [all-inkl](https://all-inkl.com) | `allinkl` | `ALL_INKL_LOGIN`, `ALL_INKL_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/allinkl) |
|
||||
| [ArvanCloud](https://www.arvancloud.com/en) | `arvancloud` | `ARVANCLOUD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/arvancloud) |
|
||||
| [Auroradns](https://www.pcextreme.com/dns-health-checks) | `auroradns` | `AURORA_USER_ID`, `AURORA_KEY`, `AURORA_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/auroradns) |
|
||||
| [Autodns](https://www.internetx.com/domains/autodns/) | `autodns` | `AUTODNS_API_USER`, `AUTODNS_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/autodns) |
|
||||
| [Azure](https://azure.microsoft.com/services/dns/) | `azure` | `AZURE_CLIENT_ID`, `AZURE_CLIENT_SECRET`, `AZURE_SUBSCRIPTION_ID`, `AZURE_TENANT_ID`, `AZURE_RESOURCE_GROUP`, `[AZURE_METADATA_ENDPOINT]` | [Additional configuration](https://go-acme.github.io/lego/dns/azure) |
|
||||
| [Bindman](https://github.com/labbsr0x/bindman-dns-webhook) | `bindman` | `BINDMAN_MANAGER_ADDRESS` | [Additional configuration](https://go-acme.github.io/lego/dns/bindman) |
|
||||
| [Blue Cat](https://www.bluecatnetworks.com/) | `bluecat` | `BLUECAT_SERVER_URL`, `BLUECAT_USER_NAME`, `BLUECAT_PASSWORD`, `BLUECAT_CONFIG_NAME`, `BLUECAT_DNS_VIEW` | [Additional configuration](https://go-acme.github.io/lego/dns/bluecat) |
|
||||
| [Checkdomain](https://www.checkdomain.de/) | `checkdomain` | `CHECKDOMAIN_TOKEN`, | [Additional configuration](https://go-acme.github.io/lego/dns/checkdomain/) |
|
||||
| [CloudDNS](https://vshosting.eu/) | `clouddns` | `CLOUDDNS_CLIENT_ID`, `CLOUDDNS_EMAIL`, `CLOUDDNS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/clouddns) |
|
||||
| [Cloudflare](https://www.cloudflare.com) | `cloudflare` | `CF_API_EMAIL`, `CF_API_KEY` [^5] or `CF_DNS_API_TOKEN`, `[CF_ZONE_API_TOKEN]` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudflare) |
|
||||
| [ClouDNS](https://www.cloudns.net/) | `cloudns` | `CLOUDNS_AUTH_ID`, `CLOUDNS_AUTH_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudns) |
|
||||
| [CloudXNS](https://www.cloudxns.net) | `cloudxns` | `CLOUDXNS_API_KEY`, `CLOUDXNS_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/cloudxns) |
|
||||
| [ConoHa](https://www.conoha.jp) | `conoha` | `CONOHA_TENANT_ID`, `CONOHA_API_USERNAME`, `CONOHA_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/conoha) |
|
||||
| [Constellix](https://constellix.com) | `constellix` | `CONSTELLIX_API_KEY`, `CONSTELLIX_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/constellix) |
|
||||
| [deSEC](https://desec.io) | `desec` | `DESEC_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/desec) |
|
||||
| [DigitalOcean](https://www.digitalocean.com) | `digitalocean` | `DO_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/digitalocean) |
|
||||
| [DNS Made Easy](https://dnsmadeeasy.com) | `dnsmadeeasy` | `DNSMADEEASY_API_KEY`, `DNSMADEEASY_API_SECRET`, `DNSMADEEASY_SANDBOX` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsmadeeasy) |
|
||||
| [DNSimple](https://dnsimple.com) | `dnsimple` | `DNSIMPLE_OAUTH_TOKEN`, `DNSIMPLE_BASE_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/dnsimple) |
|
||||
| [DNSPod](https://www.dnspod.com/) | `dnspod` | `DNSPOD_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dnspod) |
|
||||
| [Domain Offensive (do.de)](https://www.do.de/) | `dode` | `DODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/dode) |
|
||||
| [Domeneshop](https://domene.shop) | `domeneshop` | `DOMENESHOP_API_TOKEN`, `DOMENESHOP_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/domeneshop) |
|
||||
| [DreamHost](https://www.dreamhost.com/) | `dreamhost` | `DREAMHOST_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dreamhost) |
|
||||
| [Duck DNS](https://www.duckdns.org/) | `duckdns` | `DUCKDNS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/duckdns) |
|
||||
| [Dyn](https://dyn.com) | `dyn` | `DYN_CUSTOMER_NAME`, `DYN_USER_NAME`, `DYN_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/dyn) |
|
||||
| [Dynu](https://www.dynu.com) | `dynu` | `DYNU_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/dynu) |
|
||||
| [EasyDNS](https://easydns.com/) | `easydns` | `EASYDNS_TOKEN`, `EASYDNS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/easydns) |
|
||||
| [EdgeDNS](https://www.akamai.com/) | `edgedns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) |
|
||||
| [Epik](https://www.epik.com) | `epik` | `EPIK_SIGNATURE` | [Additional configuration](https://go-acme.github.io/lego/dns/epik) |
|
||||
| [Exoscale](https://www.exoscale.com) | `exoscale` | `EXOSCALE_API_KEY`, `EXOSCALE_API_SECRET`, `EXOSCALE_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/exoscale) |
|
||||
| [Fast DNS](https://www.akamai.com/) | `fastdns` | `AKAMAI_CLIENT_TOKEN`, `AKAMAI_CLIENT_SECRET`, `AKAMAI_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/edgedns) |
|
||||
| [Freemyip.com](https://freemyip.com) | `freemyip` | `FREEMYIP_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/freemyip) |
|
||||
| [G-Core Lab](https://gcorelabs.com/dns/) | `gcore` | `GCORE_PERMANENT_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/gcore) |
|
||||
| [Gandi v5](https://doc.livedns.gandi.net) | `gandiv5` | `GANDIV5_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandiv5) |
|
||||
| [Gandi](https://www.gandi.net) | `gandi` | `GANDI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/gandi) |
|
||||
| [Glesys](https://glesys.com/) | `glesys` | `GLESYS_API_USER`, `GLESYS_API_KEY`, `GLESYS_DOMAIN` | [Additional configuration](https://go-acme.github.io/lego/dns/glesys) |
|
||||
| [GoDaddy](https://godaddy.com/) | `godaddy` | `GODADDY_API_KEY`, `GODADDY_API_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/godaddy) |
|
||||
| [Google Cloud DNS](https://cloud.google.com/dns/docs/) | `gcloud` | `GCE_PROJECT`, Application Default Credentials [^2] [^3], [`GCE_SERVICE_ACCOUNT_FILE`] | [Additional configuration](https://go-acme.github.io/lego/dns/gcloud) |
|
||||
| [Hetzner](https://hetzner.com) | `hetzner` | `HETZNER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hetzner) |
|
||||
| [hosting.de](https://www.hosting.de) | `hostingde` | `HOSTINGDE_API_KEY`, `HOSTINGDE_ZONE_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/hostingde) |
|
||||
| [Hosttech](https://www.hosttech.eu) | `hosttech` | `HOSTTECH_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/hosttech) |
|
||||
| [Hurricane Electric](https://dns.he.net) | `hurricane` | `HURRICANE_TOKENS` [^6] | [Additional configuration](https://go-acme.github.io/lego/dns/hurricane) |
|
||||
| [HyperOne](https://www.hyperone.com) | `hyperone` | `HYPERONE_PASSPORT_LOCATION`, `HYPERONE_LOCATION_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/hyperone) |
|
||||
| [IBM Cloud (SoftLayer)](https://www.ibm.com/cloud/) | `ibmcloud` | `SOFTLAYER_USERNAME`, `SOFTLAYER_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ibmcloud) |
|
||||
| [IIJ DNS Platform Service](https://www.iij.ad.jp) | `iijdpf` | `IIJ_DPF_API_TOKEN` , `IIJ_DPF_DPM_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iijdpf) |
|
||||
| [IIJ](https://www.iij.ad.jp/) | `iij` | `IIJ_API_ACCESS_KEY`, `IIJ_API_SECRET_KEY`, `IIJ_DO_SERVICE_CODE` | [Additional configuration](https://go-acme.github.io/lego/dns/iij) |
|
||||
| [Infoblox](https://www.infoblox.com/) | `infoblox` | `INFOBLOX_USER`, `INFOBLOX_PASSWORD`, `INFOBLOX_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/infoblox) |
|
||||
| [Infomaniak](https://www.infomaniak.com) | `infomaniak` | `INFOMANIAK_ACCESS_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/infomaniak) |
|
||||
| [Internet.bs](https://internetbs.net) | `internetbs` | `INTERNET_BS_API_KEY`, `INTERNET_BS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/internetbs) |
|
||||
| [INWX](https://www.inwx.de/en) | `inwx` | `INWX_USERNAME`, `INWX_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/inwx) |
|
||||
| [ionos](https://ionos.com/) | `ionos` | `IONOS_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ionos) |
|
||||
| [iwantmyname](https://iwantmyname.com) | `iwantmyname` | `IWANTMYNAME_USERNAME` , `IWANTMYNAME_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/iwantmyname) |
|
||||
| [Joker.com](https://joker.com) | `joker` | `JOKER_API_MODE` with `JOKER_API_KEY` or `JOKER_USERNAME`, `JOKER_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/joker) |
|
||||
| [Lightsail](https://aws.amazon.com/lightsail/) | `lightsail` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `DNS_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/lightsail) |
|
||||
| [Linode v4](https://www.linode.com) | `linode` | `LINODE_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/linode) |
|
||||
| [Liquid Web](https://www.liquidweb.com/) | `liquidweb` | `LIQUID_WEB_PASSWORD`, `LIQUID_WEB_USERNAME`, `LIQUID_WEB_ZONE` | [Additional configuration](https://go-acme.github.io/lego/dns/liquidweb) |
|
||||
| [Loopia](https://loopia.com/) | `loopia` | `LOOPIA_API_PASSWORD`, `LOOPIA_API_USER` | [Additional configuration](https://go-acme.github.io/lego/dns/loopia) |
|
||||
| [LuaDNS](https://luadns.com) | `luadns` | `LUADNS_API_USERNAME`, `LUADNS_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/luadns) |
|
||||
| [MyDNS.jp](https://www.mydns.jp/) | `mydnsjp` | `MYDNSJP_MASTER_ID`, `MYDNSJP_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mydnsjp) |
|
||||
| [Mythic Beasts](https://www.mythic-beasts.com) | `mythicbeasts` | `MYTHICBEASTS_USER_NAME`, `MYTHICBEASTS_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/mythicbeasts) |
|
||||
| [name.com](https://www.name.com/) | `namedotcom` | `NAMECOM_USERNAME`, `NAMECOM_API_TOKEN`, `NAMECOM_SERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/namedotcom) |
|
||||
| [Namecheap](https://www.namecheap.com) | `namecheap` | `NAMECHEAP_API_USER`, `NAMECHEAP_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namecheap) |
|
||||
| [Namesilo](https://www.namesilo.com/) | `namesilo` | `NAMESILO_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/namesilo) |
|
||||
| [Netcup](https://www.netcup.eu/) | `netcup` | `NETCUP_CUSTOMER_NUMBER`, `NETCUP_API_KEY`, `NETCUP_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/netcup) |
|
||||
| [Netlify](https://www.netlify.com) | `netlify` | `NETLIFY_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/netlify) |
|
||||
| [Nicmanager](https://www.nicmanager.com) | `nicmanager` | `NICMANAGER_API_EMAIL`, `NICMANAGER_API_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/nicmanager) |
|
||||
| [NIFCloud](https://cloud.nifty.com/service/dns.htm) | `nifcloud` | `NIFCLOUD_ACCESS_KEY_ID`, `NIFCLOUD_SECRET_ACCESS_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/nifcloud) |
|
||||
| [Njalla](https://njal.la) | `njalla` | `NJALLA_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/njalla) |
|
||||
| [NS1](https://ns1.com/) | `ns1` | `NS1_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ns1) |
|
||||
| [Open Telekom Cloud](https://cloud.telekom.de) | `otc` | `OTC_DOMAIN_NAME`, `OTC_USER_NAME`, `OTC_PASSWORD`, `OTC_PROJECT_NAME`, `OTC_IDENTITY_ENDPOINT` | [Additional configuration](https://go-acme.github.io/lego/dns/otc) |
|
||||
| [Openstack Designate](https://docs.openstack.org/designate) | `designate` | `OS_AUTH_URL`, `OS_USERNAME`, `OS_PASSWORD`, `OS_TENANT_NAME`, `OS_REGION_NAME` | [Additional configuration](https://go-acme.github.io/lego/dns/designate) |
|
||||
| [Oracle Cloud](https://cloud.oracle.com/home) | `oraclecloud` | `OCI_COMPARTMENT_OCID`, `OCI_PRIVKEY_FILE`, `OCI_PRIVKEY_PASS`, `OCI_PUBKEY_FINGERPRINT`, `OCI_REGION`, `OCI_TENANCY_OCID`, `OCI_USER_OCID` | [Additional configuration](https://go-acme.github.io/lego/dns/oraclecloud) |
|
||||
| [OVH](https://www.ovh.com) | `ovh` | `OVH_ENDPOINT`, `OVH_APPLICATION_KEY`, `OVH_APPLICATION_SECRET`, `OVH_CONSUMER_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/ovh) |
|
||||
| [Porkbun](https://porkbun.com/) | `porkbun` | `PORKBUN_SECRET_API_KEY`, `PORKBUN_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/porkbun) |
|
||||
| [PowerDNS](https://www.powerdns.com) | `pdns` | `PDNS_API_KEY`, `PDNS_API_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/pdns) |
|
||||
| [Rackspace](https://www.rackspace.com/cloud/dns) | `rackspace` | `RACKSPACE_USER`, `RACKSPACE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rackspace) |
|
||||
| [reg.ru](https://www.reg.ru) | `regru` | `REGRU_USERNAME`, `REGRU_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/regru) |
|
||||
| [RFC2136](https://tools.ietf.org/html/rfc2136) | `rfc2136` | `RFC2136_TSIG_KEY`, `RFC2136_TSIG_SECRET`, `RFC2136_TSIG_ALGORITHM`, `RFC2136_NAMESERVER` | [Additional configuration](https://go-acme.github.io/lego/dns/rfc2136) |
|
||||
| [RimuHosting](https://rimuhosting.com) | `rimuhosting` | `RIMUHOSTING_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/rimuhosting) |
|
||||
| [Route 53](https://aws.amazon.com/route53/) | `route53` | `AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`, `[AWS_REGION]`, `[AWS_HOSTED_ZONE_ID]` or a configured user/instance IAM profile. | [Additional configuration](https://go-acme.github.io/lego/dns/route53) |
|
||||
| [Sakura Cloud](https://cloud.sakura.ad.jp/) | `sakuracloud` | `SAKURACLOUD_ACCESS_TOKEN`, `SAKURACLOUD_ACCESS_TOKEN_SECRET` | [Additional configuration](https://go-acme.github.io/lego/dns/sakuracloud) |
|
||||
| [Scaleway](https://www.scaleway.com) | `scaleway` | `SCALEWAY_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/scaleway) |
|
||||
| [Selectel](https://selectel.ru/en/) | `selectel` | `SELECTEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/selectel) |
|
||||
| [Servercow](https://servercow.de) | `servercow` | `SERVERCOW_USERNAME`, `SERVERCOW_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/servercow) |
|
||||
| [Simply.com](https://www.simply.com/en/domains/) | `simply` | `SIMPLY_ACCOUNT_NAME`, `SIMPLY_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/simply) |
|
||||
| [Sonic](https://www.sonic.com/) | `sonic` | `SONIC_USER_ID`, `SONIC_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/sonic) |
|
||||
| [Stackpath](https://www.stackpath.com/) | `stackpath` | `STACKPATH_CLIENT_ID`, `STACKPATH_CLIENT_SECRET`, `STACKPATH_STACK_ID` | [Additional configuration](https://go-acme.github.io/lego/dns/stackpath) |
|
||||
| [Tencent Cloud DNS](https://cloud.tencent.com/product/cns) | `tencentcloud` | `TENCENTCLOUD_SECRET_ID`, `TENCENTCLOUD_SECRET_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/tencentcloud) |
|
||||
| [TransIP](https://www.transip.nl/) | `transip` | `TRANSIP_ACCOUNT_NAME`, `TRANSIP_PRIVATE_KEY_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/transip) |
|
||||
| [UKFast SafeDNS](https://www.ans.co.uk/cloud-and-infrastructure/dedicated-servers/dns-management/) | `safedns` | `SAFEDNS_AUTH_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/safedns) |
|
||||
| [VegaDNS](https://github.com/shupp/VegaDNS-API) | `vegadns` | `SECRET_VEGADNS_KEY`, `SECRET_VEGADNS_SECRET`, `VEGADNS_URL` | [Additional configuration](https://go-acme.github.io/lego/dns/vegadns) |
|
||||
| [Vercel](https://vercel.com) | `vercel` | `VERCEL_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vercel) |
|
||||
| [Versio](https://www.versio.nl/domeinnamen) | `versio` | `VERSIO_USERNAME`, `VERSIO_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/versio) |
|
||||
| [VinylDNS](https://www.vinyldns.io) | `vinyldns` | `VINYLDNS_ACCESS_KEY`, `VINYLDNS_SECRET_KEY`, `VINYLDNS_HOST` | [Additional configuration](https://go-acme.github.io/lego/dns/vinyldns) |
|
||||
| [Vscale](https://vscale.io/) | `vscale` | `VSCALE_API_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/vscale) |
|
||||
| [VULTR](https://www.vultr.com) | `vultr` | `VULTR_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/vultr) |
|
||||
| [WEDOS](https://www.wedos.com) | `wedos` | `WEDOS_USERNAME`, `WEDOS_WAPI_PASSWORD` | [Additional configuration](https://go-acme.github.io/lego/dns/wedos) |
|
||||
| [Yandex](https://yandex.com) | `yandex` | `YANDEX_PDD_TOKEN` | [Additional configuration](https://go-acme.github.io/lego/dns/yandex) |
|
||||
| [Zone.ee](https://www.zone.ee) | `zoneee` | `ZONEEE_API_USER`, `ZONEEE_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zoneee) |
|
||||
| [Zonomi](https://zonomi.com) | `zonomi` | `ZONOMI_API_KEY` | [Additional configuration](https://go-acme.github.io/lego/dns/zonomi) |
|
||||
| External Program | `exec` | `EXEC_PATH` | [Additional configuration](https://go-acme.github.io/lego/dns/exec) |
|
||||
| HTTP request | `httpreq` | `HTTPREQ_ENDPOINT`, `HTTPREQ_MODE`, `HTTPREQ_USERNAME`, `HTTPREQ_PASSWORD` [^1] | [Additional configuration](https://go-acme.github.io/lego/dns/httpreq) |
|
||||
| manual | `manual` | none, but you need to run Traefik interactively [^4], turn on debug log to see instructions and press <kbd>Enter</kbd>. | |
|
||||
|
||||
[^1]: More information about the HTTP message format can be found [here](https://go-acme.github.io/lego/dns/httpreq/).
|
||||
[^2]: [Providing credentials to your application](https://cloud.google.com/docs/authentication/production).
|
||||
@@ -666,3 +666,18 @@ If Let's Encrypt is not reachable, the following certificates will apply:
|
||||
|
||||
!!! important
|
||||
For new (sub)domains which need Let's Encrypt authentication, the default Traefik certificate will be used until Traefik is restarted.
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -26,7 +26,8 @@ Developing Traefik, our main goal is to make it simple to use, and we're sure yo
|
||||
|
||||
Join our user friendly and active [Community Forum](https://community.traefik.io) to discuss, learn, and connect with the traefik community.
|
||||
|
||||
If you're a business running critical services behind Traefik,
|
||||
know that [Traefik Labs](https://traefik.io), the company that sponsors Traefik's development,
|
||||
can provide [commercial support](https://info.traefik.io/commercial-services)
|
||||
and develops an [Enterprise Edition](https://traefik.io/traefik-enterprise/) of Traefik.
|
||||
Using Traefik for commercial applications?
|
||||
Consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/) of Traefik as your [Kubernetes Ingress](https://traefik.io/solutions/kubernetes-ingress/),
|
||||
your [Docker Swarm Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/),
|
||||
or your [API gateway](https://traefik.io/solutions/api-gateway/).
|
||||
Get started with a [free 30-day trial](https://info.traefik.io/get-traefik-enterprise-free-for-30-days).
|
||||
|
@@ -153,3 +153,7 @@ http:
|
||||
| [Retry](retry.md) | Automatically retries in case of error | Request lifecycle |
|
||||
| [StripPrefix](stripprefix.md) | Changes the path of the request | Path Modifier |
|
||||
| [StripPrefixRegex](stripprefixregex.md) | Changes the path of the request | Path Modifier |
|
||||
|
||||
## Community Middlewares
|
||||
|
||||
Please take a look at the community-contributed plugins in the [plugin catalog](https://pilot.traefik.io/plugins).
|
||||
|
@@ -445,6 +445,23 @@ Subject="DC=org,DC=cheese,C=FR,C=US,ST=Cheese org state,ST=Cheese com state,L=TO
|
||||
|
||||
If there are more than one certificate, they are separated by a `,`.
|
||||
|
||||
#### `info.serialNumber`
|
||||
|
||||
Set the `info.serialNumber` option to `true` to add the `Serial Number` of the certificate.
|
||||
|
||||
The data is taken from the following certificate part:
|
||||
|
||||
```text
|
||||
Serial Number:
|
||||
6a:2f:20:f8:ce:8d:48:52:ba:d9:bb:be:60:ec:bf:79
|
||||
```
|
||||
|
||||
And it is formatted as follows in the header (decimal representation):
|
||||
|
||||
```text
|
||||
SerialNumber="141142874255168551917600297745052909433"
|
||||
```
|
||||
|
||||
#### `info.notAfter`
|
||||
|
||||
Set the `info.notAfter` option to `true` to add the `Not After` information from the `Validity` part.
|
||||
@@ -452,8 +469,8 @@ Set the `info.notAfter` option to `true` to add the `Not After` information from
|
||||
The data is taken from the following certificate part:
|
||||
|
||||
```text
|
||||
Validity
|
||||
Not After : Dec 5 11:10:16 2020 GMT
|
||||
Validity
|
||||
Not After : Dec 5 11:10:16 2020 GMT
|
||||
```
|
||||
|
||||
And it is formatted as follows in the header:
|
||||
@@ -486,8 +503,8 @@ Set the `info.sans` option to `true` to add the `Subject Alternative Name` infor
|
||||
The data is taken from the following certificate part:
|
||||
|
||||
```text
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:*.example.org, DNS:*.example.net, DNS:*.example.com, IP Address:10.0.1.0, IP Address:10.0.1.2, email:test@example.org, email:test@example.net
|
||||
X509v3 Subject Alternative Name:
|
||||
DNS:*.example.org, DNS:*.example.net, DNS:*.example.com, IP Address:10.0.1.0, IP Address:10.0.1.2, email:test@example.org, email:test@example.net
|
||||
```
|
||||
|
||||
And it is formatted as follows in the header:
|
||||
|
@@ -12,7 +12,16 @@ Redirecting the Client to a Different Scheme/Port
|
||||
TODO: add schema
|
||||
-->
|
||||
|
||||
RedirectScheme redirects requests from a scheme/port to another.
|
||||
The RedirectScheme middleware redirects the request if the request scheme is different from the configured scheme.
|
||||
|
||||
!!! warning "When behind another reverse-proxy"
|
||||
|
||||
When there is at least one other reverse-proxy between the client and Traefik,
|
||||
the other reverse-proxy (i.e. the last hop) needs to be a [trusted](../../routing/entrypoints.md#forwarded-headers) one.
|
||||
|
||||
Otherwise, Traefik would clean up the X-Forwarded headers coming from this last hop,
|
||||
and as the RedirectScheme middleware relies on them to determine the scheme used,
|
||||
it would not function as intended.
|
||||
|
||||
## Configuration Examples
|
||||
|
||||
|
@@ -714,3 +714,18 @@ providers:
|
||||
```bash tab="CLI"
|
||||
--providers.docker.tls.insecureSkipVerify=true
|
||||
```
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -31,15 +31,14 @@ the Traefik engineering team developed a [Custom Resource Definition](https://ku
|
||||
|
||||
For Kubernetes `v1.16+`, please use the Traefik `apiextensions.k8s.io/v1` CRDs instead.
|
||||
|
||||
??? example "Initializing Resource Definition and RBAC"
|
||||
!!! example "Installing Resource Definition and RBAC"
|
||||
|
||||
```yaml tab="Traefik Resource Definition"
|
||||
# All resources definition must be declared
|
||||
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml"
|
||||
```
|
||||
|
||||
```yaml tab="RBAC for Traefik CRD"
|
||||
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-rbac.yml"
|
||||
```bash
|
||||
# Install Traefik Resource Definitions:
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
|
||||
|
||||
# Install RBAC for Traefik:
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml
|
||||
```
|
||||
|
||||
## Resource Configuration
|
||||
|
@@ -501,3 +501,18 @@ providers:
|
||||
|
||||
To learn more about the various aspects of the Ingress specification that Traefik supports,
|
||||
many examples of Ingresses definitions are located in the test [examples](https://github.com/traefik/traefik/tree/v2.8/pkg/provider/kubernetes/ingress/fixtures) of the Traefik repository.
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -158,33 +158,6 @@ providers:
|
||||
# ...
|
||||
```
|
||||
|
||||
#### `datacenter`
|
||||
|
||||
_Optional, Default=""_
|
||||
|
||||
Defines the datacenter to use.
|
||||
If not provided in Traefik, Nomad uses the agent datacenter.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
nomad:
|
||||
endpoint:
|
||||
datacenter: dc1
|
||||
# ...
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.nomad]
|
||||
[providers.nomad.endpoint]
|
||||
datacenter = "dc1"
|
||||
# ...
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.nomad.endpoint.datacenter=dc1
|
||||
# ...
|
||||
```
|
||||
|
||||
#### `token`
|
||||
|
||||
_Optional, Default=""_
|
||||
@@ -238,58 +211,6 @@ providers:
|
||||
# ...
|
||||
```
|
||||
|
||||
#### `httpAuth`
|
||||
|
||||
_Optional_
|
||||
|
||||
Used to authenticate the HTTP client using HTTP Basic Authentication.
|
||||
|
||||
##### `username`
|
||||
|
||||
_Optional, Default=""_
|
||||
|
||||
Username to use for HTTP Basic Authentication.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
nomad:
|
||||
endpoint:
|
||||
httpAuth:
|
||||
username: admin
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.nomad.endpoint.httpAuth]
|
||||
username = "admin"
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.nomad.endpoint.httpauth.username=admin
|
||||
```
|
||||
|
||||
##### `password`
|
||||
|
||||
_Optional, Default=""_
|
||||
|
||||
Password to use for HTTP Basic Authentication.
|
||||
|
||||
```yaml tab="File (YAML)"
|
||||
providers:
|
||||
nomad:
|
||||
endpoint:
|
||||
httpAuth:
|
||||
password: passw0rd
|
||||
```
|
||||
|
||||
```toml tab="File (TOML)"
|
||||
[providers.nomad.endpoint.httpAuth]
|
||||
password = "passw0rd"
|
||||
```
|
||||
|
||||
```bash tab="CLI"
|
||||
--providers.nomad.endpoint.httpauth.password=passw0rd
|
||||
```
|
||||
|
||||
#### `tls`
|
||||
|
||||
_Optional_
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -8,13 +8,19 @@ description: "Learn about the definitions, resources, and RBAC of dynamic config
|
||||
Dynamic configuration with Kubernetes Custom Resource
|
||||
{: .subtitle }
|
||||
|
||||
!!! warning "Deprecated apiextensions.k8s.io/v1beta1 CRD"
|
||||
|
||||
The `apiextensions.k8s.io/v1beta1` CustomResourceDefinition is deprecated in Kubernetes `v1.16+` and will be removed in `v1.22+`.
|
||||
|
||||
For Kubernetes `v1.16+`, please use the Traefik `apiextensions.k8s.io/v1` CRDs instead.
|
||||
|
||||
## Definitions
|
||||
|
||||
```yaml tab="apiextensions.k8s.io/v1"
|
||||
```yaml tab="apiextensions.k8s.io/v1 (Kubernetes v1.16+)"
|
||||
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml"
|
||||
```
|
||||
|
||||
```yaml tab="apiextensions.k8s.io/v1beta1"
|
||||
```yaml tab="apiextensions.k8s.io/v1beta1 (Deprecated)"
|
||||
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-definition-v1beta1.yml"
|
||||
```
|
||||
|
||||
|
@@ -19,7 +19,7 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: IngressRoute is an Ingress CRD specification.
|
||||
description: IngressRoute is the CRD implementation of a Traefik HTTP Router.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,96 +34,151 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: IngressRouteSpec is a specification for a IngressRouteSpec
|
||||
resource.
|
||||
description: IngressRouteSpec defines the desired state of IngressRoute.
|
||||
properties:
|
||||
entryPoints:
|
||||
description: 'EntryPoints defines the list of entry point names to
|
||||
bind to. Entry points have to be configured in the static configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/entrypoints/
|
||||
Default: all.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
routes:
|
||||
description: Routes defines the list of routes.
|
||||
items:
|
||||
description: Route contains the set of routes.
|
||||
description: Route holds the HTTP route configuration.
|
||||
properties:
|
||||
kind:
|
||||
description: Kind defines the kind of the route. Rule is the
|
||||
only supported kind.
|
||||
enum:
|
||||
- Rule
|
||||
type: string
|
||||
match:
|
||||
description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#rule'
|
||||
type: string
|
||||
middlewares:
|
||||
description: 'Middlewares defines the list of references to
|
||||
Middleware resources. More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-middleware'
|
||||
items:
|
||||
description: MiddlewareRef is a ref to the Middleware resources.
|
||||
description: MiddlewareRef is a reference to a Middleware
|
||||
resource.
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Middleware
|
||||
resource.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Middleware resource.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
priority:
|
||||
description: 'Priority defines the router''s priority. More
|
||||
info: https://doc.traefik.io/traefik/v2.8/routing/routers/#priority'
|
||||
type: integer
|
||||
services:
|
||||
description: Services defines the list of Service. It can contain
|
||||
any combination of TraefikService and/or reference to a Kubernetes
|
||||
Service.
|
||||
items:
|
||||
description: Service defines an upstream to proxy traffic.
|
||||
description: Service defines an upstream HTTP service to proxy
|
||||
traffic to.
|
||||
properties:
|
||||
kind:
|
||||
description: Kind defines the kind of the Service.
|
||||
enum:
|
||||
- Service
|
||||
- TraefikService
|
||||
type: string
|
||||
name:
|
||||
description: Name is a reference to a Kubernetes Service
|
||||
object (for a load-balancer of servers), or to a TraefikService
|
||||
object (service load-balancer, mirroring, etc). The
|
||||
differentiation between the two is specified in the
|
||||
Kind field.
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service or TraefikService. The differentiation between
|
||||
the two is specified in the Kind field.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service or TraefikService.
|
||||
type: string
|
||||
passHostHeader:
|
||||
description: PassHostHeader defines whether the client
|
||||
Host header is forwarded to the upstream Kubernetes
|
||||
Service. By default, passHostHeader is true.
|
||||
type: boolean
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service.
|
||||
This can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
responseForwarding:
|
||||
description: ResponseForwarding holds configuration for
|
||||
the forward of the response.
|
||||
description: ResponseForwarding defines how Traefik forwards
|
||||
the response from the upstream Kubernetes Service to
|
||||
the client.
|
||||
properties:
|
||||
flushInterval:
|
||||
description: 'FlushInterval defines the interval,
|
||||
in milliseconds, in between flushes to the client
|
||||
while copying the response body. A negative value
|
||||
means to flush immediately after each write to the
|
||||
client. This configuration is ignored when ReverseProxy
|
||||
recognizes a response as a streaming response; for
|
||||
such responses, writes are flushed to the client
|
||||
immediately. Default: 100ms'
|
||||
type: string
|
||||
type: object
|
||||
scheme:
|
||||
description: Scheme defines the scheme to use for the
|
||||
request to the upstream Kubernetes Service. It defaults
|
||||
to https when Kubernetes Service port is 443, http otherwise.
|
||||
type: string
|
||||
serversTransport:
|
||||
description: ServersTransport defines the name of ServersTransport
|
||||
resource to use. It allows to configure the transport
|
||||
between Traefik and your servers. Can only be used on
|
||||
a Kubernetes Service.
|
||||
type: string
|
||||
sticky:
|
||||
description: Sticky holds the sticky configuration.
|
||||
description: 'Sticky defines the sticky sessions configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/services/#sticky-sessions'
|
||||
properties:
|
||||
cookie:
|
||||
description: Cookie holds the sticky configuration
|
||||
based on cookie.
|
||||
description: Cookie defines the sticky cookie configuration.
|
||||
properties:
|
||||
httpOnly:
|
||||
description: HTTPOnly defines whether the cookie
|
||||
can be accessed by client-side APIs, such as
|
||||
JavaScript.
|
||||
type: boolean
|
||||
name:
|
||||
description: Name defines the Cookie name.
|
||||
type: string
|
||||
sameSite:
|
||||
description: 'SameSite defines the same site policy.
|
||||
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite'
|
||||
type: string
|
||||
secure:
|
||||
description: Secure defines whether the cookie
|
||||
can only be transmitted over an encrypted connection
|
||||
(i.e. HTTPS).
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
strategy:
|
||||
description: Strategy defines the load balancing strategy
|
||||
between the servers. RoundRobin is the only supported
|
||||
value at the moment.
|
||||
type: string
|
||||
weight:
|
||||
description: Weight should only be specified when Name
|
||||
references a TraefikService object (and to be precise,
|
||||
one that embeds a Weighted Round Robin).
|
||||
description: Weight defines the weight and should only
|
||||
be specified when Name references a TraefikService object
|
||||
(and to be precise, one that embeds a Weighted Round
|
||||
Robin).
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
@@ -135,32 +190,42 @@ spec:
|
||||
type: object
|
||||
type: array
|
||||
tls:
|
||||
description: "TLS contains the TLS certificates configuration of the
|
||||
routes. To enable Let's Encrypt, use an empty TLS struct, e.g. in
|
||||
YAML: \n \t tls: {} # inline format \n \t tls: \t secretName:
|
||||
# block format"
|
||||
description: 'TLS defines the TLS configuration. More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#tls'
|
||||
properties:
|
||||
certResolver:
|
||||
description: 'CertResolver defines the name of the certificate
|
||||
resolver to use. Cert resolvers have to be configured in the
|
||||
static configuration. More info: https://doc.traefik.io/traefik/v2.8/https/acme/#certificate-resolvers'
|
||||
type: string
|
||||
domains:
|
||||
description: 'Domains defines the list of domains that will be
|
||||
used to issue certificates. More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#domains'
|
||||
items:
|
||||
description: Domain holds a domain name with SANs.
|
||||
properties:
|
||||
main:
|
||||
description: Main defines the main domain name.
|
||||
type: string
|
||||
sans:
|
||||
description: SANs defines the subject alternative domain
|
||||
names.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
options:
|
||||
description: Options is a reference to a TLSOption, that specifies
|
||||
the parameters of the TLS connection.
|
||||
description: 'Options defines the reference to a TLSOption, that
|
||||
specifies the parameters of the TLS connection. If not defined,
|
||||
the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.8/https/tls/#tls-options'
|
||||
properties:
|
||||
name:
|
||||
description: 'Name defines the name of the referenced TLSOption.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsoption'
|
||||
type: string
|
||||
namespace:
|
||||
description: 'Namespace defines the namespace of the referenced
|
||||
TLSOption. More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsoption'
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
@@ -170,12 +235,17 @@ spec:
|
||||
Secret to specify the certificate details.
|
||||
type: string
|
||||
store:
|
||||
description: Store is a reference to a TLSStore, that specifies
|
||||
the parameters of the TLS store.
|
||||
description: Store defines the reference to the TLSStore, that
|
||||
will be used to store certificates. Please note that only `default`
|
||||
TLSStore can be used.
|
||||
properties:
|
||||
name:
|
||||
description: 'Name defines the name of the referenced TLSStore.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsstore'
|
||||
type: string
|
||||
namespace:
|
||||
description: 'Namespace defines the namespace of the referenced
|
||||
TLSStore. More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsstore'
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
|
@@ -19,7 +19,7 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: IngressRouteTCP is an Ingress CRD specification.
|
||||
description: IngressRouteTCP is the CRD implementation of a Traefik TCP Router.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,58 +34,89 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: IngressRouteTCPSpec is a specification for a IngressRouteTCPSpec
|
||||
resource.
|
||||
description: IngressRouteTCPSpec defines the desired state of IngressRouteTCP.
|
||||
properties:
|
||||
entryPoints:
|
||||
description: 'EntryPoints defines the list of entry point names to
|
||||
bind to. Entry points have to be configured in the static configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/entrypoints/
|
||||
Default: all.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
routes:
|
||||
description: Routes defines the list of routes.
|
||||
items:
|
||||
description: RouteTCP contains the set of routes.
|
||||
description: RouteTCP holds the TCP route configuration.
|
||||
properties:
|
||||
match:
|
||||
description: 'Match defines the router''s rule. More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#rule_1'
|
||||
type: string
|
||||
middlewares:
|
||||
description: Middlewares contains references to MiddlewareTCP
|
||||
description: Middlewares defines the list of references to MiddlewareTCP
|
||||
resources.
|
||||
items:
|
||||
description: ObjectReference is a generic reference to a Traefik
|
||||
resource.
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Traefik
|
||||
resource.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Traefik resource.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
priority:
|
||||
description: 'Priority defines the router''s priority. More
|
||||
info: https://doc.traefik.io/traefik/v2.8/routing/routers/#priority_1'
|
||||
type: integer
|
||||
services:
|
||||
description: Services defines the list of TCP services.
|
||||
items:
|
||||
description: ServiceTCP defines an upstream to proxy traffic.
|
||||
description: ServiceTCP defines an upstream TCP service to
|
||||
proxy traffic to.
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service.
|
||||
type: string
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service.
|
||||
This can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
proxyProtocol:
|
||||
description: ProxyProtocol holds the ProxyProtocol configuration.
|
||||
description: 'ProxyProtocol defines the PROXY protocol
|
||||
configuration. More info: https://doc.traefik.io/traefik/v2.8/routing/services/#proxy-protocol'
|
||||
properties:
|
||||
version:
|
||||
description: Version defines the PROXY Protocol version
|
||||
to use.
|
||||
type: integer
|
||||
type: object
|
||||
terminationDelay:
|
||||
description: TerminationDelay defines the deadline that
|
||||
the proxy sets, after one of its connected peers indicates
|
||||
it has closed the writing capability of its connection,
|
||||
to close the reading capability as well, hence fully
|
||||
terminating the connection. It is a duration in milliseconds,
|
||||
defaulting to 100. A negative value means an infinite
|
||||
deadline (i.e. the reading capability is never closed).
|
||||
type: integer
|
||||
weight:
|
||||
description: Weight defines the weight used when balancing
|
||||
requests between multiple Kubernetes Service.
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
@@ -97,49 +128,67 @@ spec:
|
||||
type: object
|
||||
type: array
|
||||
tls:
|
||||
description: "TLSTCP contains the TLS certificates configuration of
|
||||
the routes. To enable Let's Encrypt, use an empty TLS struct, e.g.
|
||||
in YAML: \n \t tls: {} # inline format \n \t tls: \t secretName:
|
||||
# block format"
|
||||
description: 'TLS defines the TLS configuration on a layer 4 / TCP
|
||||
Route. More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#tls_1'
|
||||
properties:
|
||||
certResolver:
|
||||
description: 'CertResolver defines the name of the certificate
|
||||
resolver to use. Cert resolvers have to be configured in the
|
||||
static configuration. More info: https://doc.traefik.io/traefik/v2.8/https/acme/#certificate-resolvers'
|
||||
type: string
|
||||
domains:
|
||||
description: 'Domains defines the list of domains that will be
|
||||
used to issue certificates. More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#domains'
|
||||
items:
|
||||
description: Domain holds a domain name with SANs.
|
||||
properties:
|
||||
main:
|
||||
description: Main defines the main domain name.
|
||||
type: string
|
||||
sans:
|
||||
description: SANs defines the subject alternative domain
|
||||
names.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
type: array
|
||||
options:
|
||||
description: Options is a reference to a TLSOption, that specifies
|
||||
the parameters of the TLS connection.
|
||||
description: 'Options defines the reference to a TLSOption, that
|
||||
specifies the parameters of the TLS connection. If not defined,
|
||||
the `default` TLSOption is used. More info: https://doc.traefik.io/traefik/v2.8/https/tls/#tls-options'
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Traefik
|
||||
resource.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Traefik resource.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
passthrough:
|
||||
description: Passthrough defines whether a TLS router will terminate
|
||||
the TLS connection.
|
||||
type: boolean
|
||||
secretName:
|
||||
description: SecretName is the name of the referenced Kubernetes
|
||||
Secret to specify the certificate details.
|
||||
type: string
|
||||
store:
|
||||
description: Store is a reference to a TLSStore, that specifies
|
||||
the parameters of the TLS store.
|
||||
description: Store defines the reference to the TLSStore, that
|
||||
will be used to store certificates. Please note that only `default`
|
||||
TLSStore can be used.
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Traefik
|
||||
resource.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Traefik resource.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
|
@@ -19,7 +19,7 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: IngressRouteUDP is an Ingress CRD specification.
|
||||
description: IngressRouteUDP is a CRD implementation of a Traefik UDP Router.
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,31 +34,45 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: IngressRouteUDPSpec is a specification for a IngressRouteUDPSpec
|
||||
resource.
|
||||
description: IngressRouteUDPSpec defines the desired state of a IngressRouteUDP.
|
||||
properties:
|
||||
entryPoints:
|
||||
description: 'EntryPoints defines the list of entry point names to
|
||||
bind to. Entry points have to be configured in the static configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/entrypoints/
|
||||
Default: all.'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
routes:
|
||||
description: Routes defines the list of routes.
|
||||
items:
|
||||
description: RouteUDP contains the set of routes.
|
||||
description: RouteUDP holds the UDP route configuration.
|
||||
properties:
|
||||
services:
|
||||
description: Services defines the list of UDP services.
|
||||
items:
|
||||
description: ServiceUDP defines an upstream to proxy traffic.
|
||||
description: ServiceUDP defines an upstream UDP service to
|
||||
proxy traffic to.
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service.
|
||||
type: string
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service.
|
||||
This can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
weight:
|
||||
description: Weight defines the weight used when balancing
|
||||
requests between multiple Kubernetes Service.
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
|
@@ -19,7 +19,8 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: Middleware is a specification for a Middleware resource.
|
||||
description: 'Middleware is the CRD implementation of a Traefik Middleware.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/overview/'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,54 +35,99 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: MiddlewareSpec holds the Middleware configuration.
|
||||
description: MiddlewareSpec defines the desired state of a Middleware.
|
||||
properties:
|
||||
addPrefix:
|
||||
description: AddPrefix holds the AddPrefix configuration.
|
||||
description: 'AddPrefix holds the add prefix middleware configuration.
|
||||
This middleware updates the path of a request before forwarding
|
||||
it. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/addprefix/'
|
||||
properties:
|
||||
prefix:
|
||||
description: Prefix is the string to add before the current path
|
||||
in the requested URL. It should include a leading slash (/).
|
||||
type: string
|
||||
type: object
|
||||
basicAuth:
|
||||
description: BasicAuth holds the HTTP basic authentication configuration.
|
||||
description: 'BasicAuth holds the basic auth middleware configuration.
|
||||
This middleware restricts access to your services to known users.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/'
|
||||
properties:
|
||||
headerField:
|
||||
description: 'HeaderField defines a header field to store the
|
||||
authenticated user. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/#headerfield'
|
||||
type: string
|
||||
realm:
|
||||
description: 'Realm allows the protected resources on a server
|
||||
to be partitioned into a set of protection spaces, each with
|
||||
its own authentication scheme. Default: traefik.'
|
||||
type: string
|
||||
removeHeader:
|
||||
description: 'RemoveHeader sets the removeHeader option to true
|
||||
to remove the authorization header before forwarding the request
|
||||
to your service. Default: false.'
|
||||
type: boolean
|
||||
secret:
|
||||
description: Secret is the name of the referenced Kubernetes Secret
|
||||
containing user credentials.
|
||||
type: string
|
||||
type: object
|
||||
buffering:
|
||||
description: Buffering holds the request/response buffering configuration.
|
||||
description: 'Buffering holds the buffering middleware configuration.
|
||||
This middleware retries or limits the size of requests that can
|
||||
be forwarded to backends. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/buffering/#maxrequestbodybytes'
|
||||
properties:
|
||||
maxRequestBodyBytes:
|
||||
description: 'MaxRequestBodyBytes defines the maximum allowed
|
||||
body size for the request (in bytes). If the request exceeds
|
||||
the allowed size, it is not forwarded to the service, and the
|
||||
client gets a 413 (Request Entity Too Large) response. Default:
|
||||
0 (no maximum).'
|
||||
format: int64
|
||||
type: integer
|
||||
maxResponseBodyBytes:
|
||||
description: 'MaxResponseBodyBytes defines the maximum allowed
|
||||
response size from the service (in bytes). If the response exceeds
|
||||
the allowed size, it is not forwarded to the client. The client
|
||||
gets a 500 (Internal Server Error) response instead. Default:
|
||||
0 (no maximum).'
|
||||
format: int64
|
||||
type: integer
|
||||
memRequestBodyBytes:
|
||||
description: 'MemRequestBodyBytes defines the threshold (in bytes)
|
||||
from which the request will be buffered on disk instead of in
|
||||
memory. Default: 1048576 (1Mi).'
|
||||
format: int64
|
||||
type: integer
|
||||
memResponseBodyBytes:
|
||||
description: 'MemResponseBodyBytes defines the threshold (in bytes)
|
||||
from which the response will be buffered on disk instead of
|
||||
in memory. Default: 1048576 (1Mi).'
|
||||
format: int64
|
||||
type: integer
|
||||
retryExpression:
|
||||
description: 'RetryExpression defines the retry conditions. It
|
||||
is a logical combination of functions with operators AND (&&)
|
||||
and OR (||). More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/buffering/#retryexpression'
|
||||
type: string
|
||||
type: object
|
||||
chain:
|
||||
description: Chain holds a chain of middlewares.
|
||||
description: 'Chain holds the configuration of the chain middleware.
|
||||
This middleware enables to define reusable combinations of other
|
||||
pieces of middleware. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/chain/'
|
||||
properties:
|
||||
middlewares:
|
||||
description: Middlewares is the list of MiddlewareRef which composes
|
||||
the chain.
|
||||
items:
|
||||
description: MiddlewareRef is a ref to the Middleware resources.
|
||||
description: MiddlewareRef is a reference to a Middleware resource.
|
||||
properties:
|
||||
name:
|
||||
description: Name defines the name of the referenced Middleware
|
||||
resource.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Middleware resource.
|
||||
type: string
|
||||
required:
|
||||
- name
|
||||
@@ -119,159 +165,249 @@ spec:
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
compress:
|
||||
description: Compress holds the compress configuration.
|
||||
description: 'Compress holds the compress middleware configuration.
|
||||
This middleware compresses responses before sending them to the
|
||||
client, using gzip compression. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/compress/'
|
||||
properties:
|
||||
excludedContentTypes:
|
||||
description: ExcludedContentTypes defines the list of content
|
||||
types to compare the Content-Type header of the incoming requests
|
||||
and responses before compressing.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
minResponseBodyBytes:
|
||||
description: 'MinResponseBodyBytes defines the minimum amount
|
||||
of bytes a response body must have to be compressed. Default:
|
||||
1024.'
|
||||
type: integer
|
||||
type: object
|
||||
contentType:
|
||||
description: ContentType middleware - or rather its unique `autoDetect`
|
||||
option - specifies whether to let the `Content-Type` header, if
|
||||
it has not been set by the backend, be automatically set to a value
|
||||
derived from the contents of the response. As a proxy, the default
|
||||
behavior should be to leave the header alone, regardless of what
|
||||
the backend did with it. However, the historic default was to always
|
||||
auto-detect and set the header if it was nil, and it is going to
|
||||
be kept that way in order to support users currently relying on
|
||||
it. This middleware exists to enable the correct behavior until
|
||||
at least the default one can be changed in a future version.
|
||||
description: ContentType holds the content-type middleware configuration.
|
||||
This middleware exists to enable the correct behavior until at least
|
||||
the default one can be changed in a future version.
|
||||
properties:
|
||||
autoDetect:
|
||||
description: AutoDetect specifies whether to let the `Content-Type`
|
||||
header, if it has not been set by the backend, be automatically
|
||||
set to a value derived from the contents of the response. As
|
||||
a proxy, the default behavior should be to leave the header
|
||||
alone, regardless of what the backend did with it. However,
|
||||
the historic default was to always auto-detect and set the header
|
||||
if it was nil, and it is going to be kept that way in order
|
||||
to support users currently relying on it.
|
||||
type: boolean
|
||||
type: object
|
||||
digestAuth:
|
||||
description: DigestAuth holds the Digest HTTP authentication configuration.
|
||||
description: 'DigestAuth holds the digest auth middleware configuration.
|
||||
This middleware restricts access to your services to known users.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/digestauth/'
|
||||
properties:
|
||||
headerField:
|
||||
description: 'HeaderField defines a header field to store the
|
||||
authenticated user. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/#headerfield'
|
||||
type: string
|
||||
realm:
|
||||
description: 'Realm allows the protected resources on a server
|
||||
to be partitioned into a set of protection spaces, each with
|
||||
its own authentication scheme. Default: traefik.'
|
||||
type: string
|
||||
removeHeader:
|
||||
description: RemoveHeader defines whether to remove the authorization
|
||||
header before forwarding the request to the backend.
|
||||
type: boolean
|
||||
secret:
|
||||
description: Secret is the name of the referenced Kubernetes Secret
|
||||
containing user credentials.
|
||||
type: string
|
||||
type: object
|
||||
errors:
|
||||
description: ErrorPage holds the custom error page configuration.
|
||||
description: 'ErrorPage holds the custom error middleware configuration.
|
||||
This middleware returns a custom page in lieu of the default, according
|
||||
to configured ranges of HTTP Status codes. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/errorpages/'
|
||||
properties:
|
||||
query:
|
||||
description: Query defines the URL for the error page (hosted
|
||||
by service). The {status} variable can be used in order to insert
|
||||
the status code in the URL.
|
||||
type: string
|
||||
service:
|
||||
description: Service defines an upstream to proxy traffic.
|
||||
description: 'Service defines the reference to a Kubernetes Service
|
||||
that will serve the error page. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/errorpages/#service'
|
||||
properties:
|
||||
kind:
|
||||
description: Kind defines the kind of the Service.
|
||||
enum:
|
||||
- Service
|
||||
- TraefikService
|
||||
type: string
|
||||
name:
|
||||
description: Name is a reference to a Kubernetes Service object
|
||||
(for a load-balancer of servers), or to a TraefikService
|
||||
object (service load-balancer, mirroring, etc). The differentiation
|
||||
between the two is specified in the Kind field.
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service or TraefikService. The differentiation between the
|
||||
two is specified in the Kind field.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service or TraefikService.
|
||||
type: string
|
||||
passHostHeader:
|
||||
description: PassHostHeader defines whether the client Host
|
||||
header is forwarded to the upstream Kubernetes Service.
|
||||
By default, passHostHeader is true.
|
||||
type: boolean
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service.
|
||||
This can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
responseForwarding:
|
||||
description: ResponseForwarding holds configuration for the
|
||||
forward of the response.
|
||||
description: ResponseForwarding defines how Traefik forwards
|
||||
the response from the upstream Kubernetes Service to the
|
||||
client.
|
||||
properties:
|
||||
flushInterval:
|
||||
description: 'FlushInterval defines the interval, in milliseconds,
|
||||
in between flushes to the client while copying the response
|
||||
body. A negative value means to flush immediately after
|
||||
each write to the client. This configuration is ignored
|
||||
when ReverseProxy recognizes a response as a streaming
|
||||
response; for such responses, writes are flushed to
|
||||
the client immediately. Default: 100ms'
|
||||
type: string
|
||||
type: object
|
||||
scheme:
|
||||
description: Scheme defines the scheme to use for the request
|
||||
to the upstream Kubernetes Service. It defaults to https
|
||||
when Kubernetes Service port is 443, http otherwise.
|
||||
type: string
|
||||
serversTransport:
|
||||
description: ServersTransport defines the name of ServersTransport
|
||||
resource to use. It allows to configure the transport between
|
||||
Traefik and your servers. Can only be used on a Kubernetes
|
||||
Service.
|
||||
type: string
|
||||
sticky:
|
||||
description: Sticky holds the sticky configuration.
|
||||
description: 'Sticky defines the sticky sessions configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/services/#sticky-sessions'
|
||||
properties:
|
||||
cookie:
|
||||
description: Cookie holds the sticky configuration based
|
||||
on cookie.
|
||||
description: Cookie defines the sticky cookie configuration.
|
||||
properties:
|
||||
httpOnly:
|
||||
description: HTTPOnly defines whether the cookie can
|
||||
be accessed by client-side APIs, such as JavaScript.
|
||||
type: boolean
|
||||
name:
|
||||
description: Name defines the Cookie name.
|
||||
type: string
|
||||
sameSite:
|
||||
description: 'SameSite defines the same site policy.
|
||||
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite'
|
||||
type: string
|
||||
secure:
|
||||
description: Secure defines whether the cookie can
|
||||
only be transmitted over an encrypted connection
|
||||
(i.e. HTTPS).
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
strategy:
|
||||
description: Strategy defines the load balancing strategy
|
||||
between the servers. RoundRobin is the only supported value
|
||||
at the moment.
|
||||
type: string
|
||||
weight:
|
||||
description: Weight should only be specified when Name references
|
||||
a TraefikService object (and to be precise, one that embeds
|
||||
a Weighted Round Robin).
|
||||
description: Weight defines the weight and should only be
|
||||
specified when Name references a TraefikService object (and
|
||||
to be precise, one that embeds a Weighted Round Robin).
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
status:
|
||||
description: Status defines which status or range of statuses
|
||||
should result in an error page. It can be either a status code
|
||||
as a number (500), as multiple comma-separated numbers (500,502),
|
||||
as ranges by separating two codes with a dash (500-599), or
|
||||
a combination of the two (404,418,500-599).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
forwardAuth:
|
||||
description: ForwardAuth holds the http forward authentication configuration.
|
||||
description: 'ForwardAuth holds the forward auth middleware configuration.
|
||||
This middleware delegates the request authentication to a Service.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/forwardauth/'
|
||||
properties:
|
||||
address:
|
||||
description: Address defines the authentication server address.
|
||||
type: string
|
||||
authRequestHeaders:
|
||||
description: AuthRequestHeaders defines the list of the headers
|
||||
to copy from the request to the authentication server. If not
|
||||
set or empty then all request headers are passed.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
authResponseHeaders:
|
||||
description: AuthResponseHeaders defines the list of headers to
|
||||
copy from the authentication server response and set on forwarded
|
||||
request, replacing any existing conflicting headers.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
authResponseHeadersRegex:
|
||||
description: 'AuthResponseHeadersRegex defines the regex to match
|
||||
headers to copy from the authentication server response and
|
||||
set on forwarded request, after stripping all headers that match
|
||||
the regex. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/forwardauth/#authresponseheadersregex'
|
||||
type: string
|
||||
tls:
|
||||
description: ClientTLS holds TLS specific configurations as client.
|
||||
description: TLS defines the configuration used to secure the
|
||||
connection to the authentication server.
|
||||
properties:
|
||||
caOptional:
|
||||
type: boolean
|
||||
caSecret:
|
||||
description: CASecret is the name of the referenced Kubernetes
|
||||
Secret containing the CA to validate the server certificate.
|
||||
The CA certificate is extracted from key `tls.ca` or `ca.crt`.
|
||||
type: string
|
||||
certSecret:
|
||||
description: CertSecret is the name of the referenced Kubernetes
|
||||
Secret containing the client certificate. The client certificate
|
||||
is extracted from the keys `tls.crt` and `tls.key`.
|
||||
type: string
|
||||
insecureSkipVerify:
|
||||
description: InsecureSkipVerify defines whether the server
|
||||
certificates should be validated.
|
||||
type: boolean
|
||||
type: object
|
||||
trustForwardHeader:
|
||||
description: 'TrustForwardHeader defines whether to trust (ie:
|
||||
forward) all X-Forwarded-* headers.'
|
||||
type: boolean
|
||||
type: object
|
||||
headers:
|
||||
description: Headers holds the custom header configuration.
|
||||
description: 'Headers holds the headers middleware configuration.
|
||||
This middleware manages the requests and responses headers. More
|
||||
info: https://doc.traefik.io/traefik/v2.8/middlewares/http/headers/#customrequestheaders'
|
||||
properties:
|
||||
accessControlAllowCredentials:
|
||||
description: AccessControlAllowCredentials is only valid if true.
|
||||
false is ignored.
|
||||
description: AccessControlAllowCredentials defines whether the
|
||||
request can include user credentials.
|
||||
type: boolean
|
||||
accessControlAllowHeaders:
|
||||
description: AccessControlAllowHeaders must be used in response
|
||||
to a preflight request with Access-Control-Request-Headers set.
|
||||
description: AccessControlAllowHeaders defines the Access-Control-Request-Headers
|
||||
values sent in preflight response.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
accessControlAllowMethods:
|
||||
description: AccessControlAllowMethods must be used in response
|
||||
to a preflight request with Access-Control-Request-Method set.
|
||||
description: AccessControlAllowMethods defines the Access-Control-Request-Method
|
||||
values sent in preflight response.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
@@ -288,60 +424,96 @@ spec:
|
||||
type: string
|
||||
type: array
|
||||
accessControlExposeHeaders:
|
||||
description: AccessControlExposeHeaders sets valid headers for
|
||||
the response.
|
||||
description: AccessControlExposeHeaders defines the Access-Control-Expose-Headers
|
||||
values sent in preflight response.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
accessControlMaxAge:
|
||||
description: AccessControlMaxAge sets the time that a preflight
|
||||
description: AccessControlMaxAge defines the time that a preflight
|
||||
request may be cached.
|
||||
format: int64
|
||||
type: integer
|
||||
addVaryHeader:
|
||||
description: AddVaryHeader controls if the Vary header is automatically
|
||||
added/updated when the AccessControlAllowOriginList is set.
|
||||
description: AddVaryHeader defines whether the Vary header is
|
||||
automatically added/updated when the AccessControlAllowOriginList
|
||||
is set.
|
||||
type: boolean
|
||||
allowedHosts:
|
||||
description: AllowedHosts defines the fully qualified list of
|
||||
allowed domain names.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
browserXssFilter:
|
||||
description: BrowserXSSFilter defines whether to add the X-XSS-Protection
|
||||
header with the value 1; mode=block.
|
||||
type: boolean
|
||||
contentSecurityPolicy:
|
||||
description: ContentSecurityPolicy defines the Content-Security-Policy
|
||||
header value.
|
||||
type: string
|
||||
contentTypeNosniff:
|
||||
description: ContentTypeNosniff defines whether to add the X-Content-Type-Options
|
||||
header with the nosniff value.
|
||||
type: boolean
|
||||
customBrowserXSSValue:
|
||||
description: CustomBrowserXSSValue defines the X-XSS-Protection
|
||||
header value. This overrides the BrowserXssFilter option.
|
||||
type: string
|
||||
customFrameOptionsValue:
|
||||
description: CustomFrameOptionsValue defines the X-Frame-Options
|
||||
header value. This overrides the FrameDeny option.
|
||||
type: string
|
||||
customRequestHeaders:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: CustomRequestHeaders defines the header names and
|
||||
values to apply to the request.
|
||||
type: object
|
||||
customResponseHeaders:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: CustomResponseHeaders defines the header names and
|
||||
values to apply to the response.
|
||||
type: object
|
||||
featurePolicy:
|
||||
description: 'Deprecated: use PermissionsPolicy instead.'
|
||||
type: string
|
||||
forceSTSHeader:
|
||||
description: ForceSTSHeader defines whether to add the STS header
|
||||
even when the connection is HTTP.
|
||||
type: boolean
|
||||
frameDeny:
|
||||
description: FrameDeny defines whether to add the X-Frame-Options
|
||||
header with the DENY value.
|
||||
type: boolean
|
||||
hostsProxyHeaders:
|
||||
description: HostsProxyHeaders defines the header keys that may
|
||||
hold a proxied hostname value for the request.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
isDevelopment:
|
||||
description: IsDevelopment defines whether to mitigate the unwanted
|
||||
effects of the AllowedHosts, SSL, and STS options when developing.
|
||||
Usually testing takes place using HTTP, not HTTPS, and on localhost,
|
||||
not your production domain. If you would like your development
|
||||
environment to mimic production with complete Host blocking,
|
||||
SSL redirects, and STS headers, leave this as false.
|
||||
type: boolean
|
||||
permissionsPolicy:
|
||||
description: PermissionsPolicy defines the Permissions-Policy
|
||||
header value. This allows sites to control browser features.
|
||||
type: string
|
||||
publicKey:
|
||||
description: PublicKey is the public key that implements HPKP
|
||||
to prevent MITM attacks with forged certificates.
|
||||
type: string
|
||||
referrerPolicy:
|
||||
description: ReferrerPolicy defines the Referrer-Policy header
|
||||
value. This allows sites to control whether browsers forward
|
||||
the Referer header to other sites.
|
||||
type: string
|
||||
sslForceHost:
|
||||
description: 'Deprecated: use RedirectRegex instead.'
|
||||
@@ -352,6 +524,10 @@ spec:
|
||||
sslProxyHeaders:
|
||||
additionalProperties:
|
||||
type: string
|
||||
description: 'SSLProxyHeaders defines the header keys with associated
|
||||
values that would indicate a valid HTTPS request. It can be
|
||||
useful when using other proxies (example: "X-Forwarded-Proto":
|
||||
"https").'
|
||||
type: object
|
||||
sslRedirect:
|
||||
description: 'Deprecated: use EntryPoint redirection or RedirectScheme
|
||||
@@ -362,221 +538,366 @@ spec:
|
||||
instead.'
|
||||
type: boolean
|
||||
stsIncludeSubdomains:
|
||||
description: STSIncludeSubdomains defines whether the includeSubDomains
|
||||
directive is appended to the Strict-Transport-Security header.
|
||||
type: boolean
|
||||
stsPreload:
|
||||
description: STSPreload defines whether the preload flag is appended
|
||||
to the Strict-Transport-Security header.
|
||||
type: boolean
|
||||
stsSeconds:
|
||||
description: STSSeconds defines the max-age of the Strict-Transport-Security
|
||||
header. If set to 0, the header is not set.
|
||||
format: int64
|
||||
type: integer
|
||||
type: object
|
||||
inFlightReq:
|
||||
description: InFlightReq limits the number of requests being processed
|
||||
and served concurrently.
|
||||
description: 'InFlightReq holds the in-flight request middleware configuration.
|
||||
This middleware limits the number of requests being processed and
|
||||
served concurrently. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/inflightreq/'
|
||||
properties:
|
||||
amount:
|
||||
description: Amount defines the maximum amount of allowed simultaneous
|
||||
in-flight request. The middleware responds with HTTP 429 Too
|
||||
Many Requests if there are already amount requests in progress
|
||||
(based on the same sourceCriterion strategy).
|
||||
format: int64
|
||||
type: integer
|
||||
sourceCriterion:
|
||||
description: SourceCriterion defines what criterion is used to
|
||||
group requests as originating from a common source. If none
|
||||
are set, the default is to use the request's remote address
|
||||
field. All fields are mutually exclusive.
|
||||
description: 'SourceCriterion defines what criterion is used to
|
||||
group requests as originating from a common source. If several
|
||||
strategies are defined at the same time, an error will be raised.
|
||||
If none are set, the default is to use the requestHost. More
|
||||
info: https://doc.traefik.io/traefik/v2.8/middlewares/http/inflightreq/#sourcecriterion'
|
||||
properties:
|
||||
ipStrategy:
|
||||
description: IPStrategy holds the ip strategy configuration.
|
||||
description: 'IPStrategy holds the IP strategy configuration
|
||||
used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ipwhitelist/#ipstrategy'
|
||||
properties:
|
||||
depth:
|
||||
description: Depth tells Traefik to use the X-Forwarded-For
|
||||
header and take the IP located at the depth position
|
||||
(starting from the right).
|
||||
type: integer
|
||||
excludedIPs:
|
||||
description: ExcludedIPs configures Traefik to scan the
|
||||
X-Forwarded-For header and select the first IP not in
|
||||
the list.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
requestHeaderName:
|
||||
description: RequestHeaderName defines the name of the header
|
||||
used to group incoming requests.
|
||||
type: string
|
||||
requestHost:
|
||||
description: RequestHost defines whether to consider the request
|
||||
Host as the source.
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
ipWhiteList:
|
||||
description: IPWhiteList holds the ip white list configuration.
|
||||
description: 'IPWhiteList holds the IP whitelist middleware configuration.
|
||||
This middleware accepts / refuses requests based on the client IP.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ipwhitelist/'
|
||||
properties:
|
||||
ipStrategy:
|
||||
description: IPStrategy holds the ip strategy configuration.
|
||||
description: 'IPStrategy holds the IP strategy configuration used
|
||||
by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ipwhitelist/#ipstrategy'
|
||||
properties:
|
||||
depth:
|
||||
description: Depth tells Traefik to use the X-Forwarded-For
|
||||
header and take the IP located at the depth position (starting
|
||||
from the right).
|
||||
type: integer
|
||||
excludedIPs:
|
||||
description: ExcludedIPs configures Traefik to scan the X-Forwarded-For
|
||||
header and select the first IP not in the list.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
sourceRange:
|
||||
description: SourceRange defines the set of allowed IPs (or ranges
|
||||
of allowed IPs by using CIDR notation).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
passTLSClientCert:
|
||||
description: PassTLSClientCert holds the TLS client cert headers configuration.
|
||||
description: 'PassTLSClientCert holds the pass TLS client cert middleware
|
||||
configuration. This middleware adds the selected data from the passed
|
||||
client TLS certificate to a header. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/passtlsclientcert/'
|
||||
properties:
|
||||
info:
|
||||
description: TLSClientCertificateInfo holds the client TLS certificate
|
||||
info configuration.
|
||||
description: Info selects the specific client certificate details
|
||||
you want to add to the X-Forwarded-Tls-Client-Cert-Info header.
|
||||
properties:
|
||||
issuer:
|
||||
description: TLSClientCertificateIssuerDNInfo holds the client
|
||||
TLS certificate distinguished name info configuration. cf
|
||||
https://tools.ietf.org/html/rfc3739
|
||||
description: Issuer defines the client certificate issuer
|
||||
details to add to the X-Forwarded-Tls-Client-Cert-Info header.
|
||||
properties:
|
||||
commonName:
|
||||
description: CommonName defines whether to add the organizationalUnit
|
||||
information into the issuer.
|
||||
type: boolean
|
||||
country:
|
||||
description: Country defines whether to add the country
|
||||
information into the issuer.
|
||||
type: boolean
|
||||
domainComponent:
|
||||
description: DomainComponent defines whether to add the
|
||||
domainComponent information into the issuer.
|
||||
type: boolean
|
||||
locality:
|
||||
description: Locality defines whether to add the locality
|
||||
information into the issuer.
|
||||
type: boolean
|
||||
organization:
|
||||
description: Organization defines whether to add the organization
|
||||
information into the issuer.
|
||||
type: boolean
|
||||
province:
|
||||
description: Province defines whether to add the province
|
||||
information into the issuer.
|
||||
type: boolean
|
||||
serialNumber:
|
||||
description: SerialNumber defines whether to add the serialNumber
|
||||
information into the issuer.
|
||||
type: boolean
|
||||
type: object
|
||||
notAfter:
|
||||
description: NotAfter defines whether to add the Not After
|
||||
information from the Validity part.
|
||||
type: boolean
|
||||
notBefore:
|
||||
description: NotBefore defines whether to add the Not Before
|
||||
information from the Validity part.
|
||||
type: boolean
|
||||
sans:
|
||||
description: Sans defines whether to add the Subject Alternative
|
||||
Name information from the Subject Alternative Name part.
|
||||
type: boolean
|
||||
serialNumber:
|
||||
description: SerialNumber defines whether to add the client
|
||||
serialNumber information.
|
||||
type: boolean
|
||||
subject:
|
||||
description: TLSClientCertificateSubjectDNInfo holds the client
|
||||
TLS certificate distinguished name info configuration. cf
|
||||
https://tools.ietf.org/html/rfc3739
|
||||
description: Subject defines the client certificate subject
|
||||
details to add to the X-Forwarded-Tls-Client-Cert-Info header.
|
||||
properties:
|
||||
commonName:
|
||||
description: CommonName defines whether to add the organizationalUnit
|
||||
information into the subject.
|
||||
type: boolean
|
||||
country:
|
||||
description: Country defines whether to add the country
|
||||
information into the subject.
|
||||
type: boolean
|
||||
domainComponent:
|
||||
description: DomainComponent defines whether to add the
|
||||
domainComponent information into the subject.
|
||||
type: boolean
|
||||
locality:
|
||||
description: Locality defines whether to add the locality
|
||||
information into the subject.
|
||||
type: boolean
|
||||
organization:
|
||||
description: Organization defines whether to add the organization
|
||||
information into the subject.
|
||||
type: boolean
|
||||
organizationalUnit:
|
||||
description: OrganizationalUnit defines whether to add
|
||||
the organizationalUnit information into the subject.
|
||||
type: boolean
|
||||
province:
|
||||
description: Province defines whether to add the province
|
||||
information into the subject.
|
||||
type: boolean
|
||||
serialNumber:
|
||||
description: SerialNumber defines whether to add the serialNumber
|
||||
information into the subject.
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
pem:
|
||||
description: PEM sets the X-Forwarded-Tls-Client-Cert header with
|
||||
the escaped certificate.
|
||||
type: boolean
|
||||
type: object
|
||||
plugin:
|
||||
additionalProperties:
|
||||
x-kubernetes-preserve-unknown-fields: true
|
||||
description: 'Plugin defines the middleware plugin configuration.
|
||||
More info: https://doc.traefik.io/traefik/plugins/'
|
||||
type: object
|
||||
rateLimit:
|
||||
description: RateLimit holds the rate limiting configuration for a
|
||||
given router.
|
||||
description: 'RateLimit holds the rate limit configuration. This middleware
|
||||
ensures that services will receive a fair amount of requests, and
|
||||
allows one to define what fair is. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ratelimit/'
|
||||
properties:
|
||||
average:
|
||||
description: Average is the maximum rate, by default in requests/s,
|
||||
allowed for the given source. It defaults to 0, which means
|
||||
no rate limiting. The rate is actually defined by dividing Average
|
||||
by Period. So for a rate below 1req/s, one needs to define a
|
||||
Period larger than a second.
|
||||
format: int64
|
||||
type: integer
|
||||
burst:
|
||||
description: Burst is the maximum number of requests allowed to
|
||||
arrive in the same arbitrarily small period of time. It defaults
|
||||
to 1.
|
||||
format: int64
|
||||
type: integer
|
||||
period:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: 'Period, in combination with Average, defines the
|
||||
actual maximum rate, such as: r = Average / Period. It defaults
|
||||
to a second.'
|
||||
x-kubernetes-int-or-string: true
|
||||
sourceCriterion:
|
||||
description: SourceCriterion defines what criterion is used to
|
||||
group requests as originating from a common source. If none
|
||||
are set, the default is to use the request's remote address
|
||||
field. All fields are mutually exclusive.
|
||||
group requests as originating from a common source. If several
|
||||
strategies are defined at the same time, an error will be raised.
|
||||
If none are set, the default is to use the request's remote
|
||||
address field (as an ipStrategy).
|
||||
properties:
|
||||
ipStrategy:
|
||||
description: IPStrategy holds the ip strategy configuration.
|
||||
description: 'IPStrategy holds the IP strategy configuration
|
||||
used by Traefik to determine the client IP. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ipwhitelist/#ipstrategy'
|
||||
properties:
|
||||
depth:
|
||||
description: Depth tells Traefik to use the X-Forwarded-For
|
||||
header and take the IP located at the depth position
|
||||
(starting from the right).
|
||||
type: integer
|
||||
excludedIPs:
|
||||
description: ExcludedIPs configures Traefik to scan the
|
||||
X-Forwarded-For header and select the first IP not in
|
||||
the list.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
requestHeaderName:
|
||||
description: RequestHeaderName defines the name of the header
|
||||
used to group incoming requests.
|
||||
type: string
|
||||
requestHost:
|
||||
description: RequestHost defines whether to consider the request
|
||||
Host as the source.
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
redirectRegex:
|
||||
description: RedirectRegex holds the redirection configuration.
|
||||
description: 'RedirectRegex holds the redirect regex middleware configuration.
|
||||
This middleware redirects a request using regex matching and replacement.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/redirectregex/#regex'
|
||||
properties:
|
||||
permanent:
|
||||
description: Permanent defines whether the redirection is permanent
|
||||
(301).
|
||||
type: boolean
|
||||
regex:
|
||||
description: Regex defines the regex used to match and capture
|
||||
elements from the request URL.
|
||||
type: string
|
||||
replacement:
|
||||
description: Replacement defines how to modify the URL to have
|
||||
the new target URL.
|
||||
type: string
|
||||
type: object
|
||||
redirectScheme:
|
||||
description: RedirectScheme holds the scheme redirection configuration.
|
||||
description: 'RedirectScheme holds the redirect scheme middleware
|
||||
configuration. This middleware redirects requests from a scheme/port
|
||||
to another. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/redirectscheme/'
|
||||
properties:
|
||||
permanent:
|
||||
description: Permanent defines whether the redirection is permanent
|
||||
(301).
|
||||
type: boolean
|
||||
port:
|
||||
description: Port defines the port of the new URL.
|
||||
type: string
|
||||
scheme:
|
||||
description: Scheme defines the scheme of the new URL.
|
||||
type: string
|
||||
type: object
|
||||
replacePath:
|
||||
description: ReplacePath holds the ReplacePath configuration.
|
||||
description: 'ReplacePath holds the replace path middleware configuration.
|
||||
This middleware replaces the path of the request URL and store the
|
||||
original path in an X-Replaced-Path header. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/replacepath/'
|
||||
properties:
|
||||
path:
|
||||
description: Path defines the path to use as replacement in the
|
||||
request URL.
|
||||
type: string
|
||||
type: object
|
||||
replacePathRegex:
|
||||
description: ReplacePathRegex holds the ReplacePathRegex configuration.
|
||||
description: 'ReplacePathRegex holds the replace path regex middleware
|
||||
configuration. This middleware replaces the path of a URL using
|
||||
regex matching and replacement. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/replacepathregex/'
|
||||
properties:
|
||||
regex:
|
||||
description: Regex defines the regular expression used to match
|
||||
and capture the path from the request URL.
|
||||
type: string
|
||||
replacement:
|
||||
description: Replacement defines the replacement path format,
|
||||
which can include captured variables.
|
||||
type: string
|
||||
type: object
|
||||
retry:
|
||||
description: Retry holds the retry configuration.
|
||||
description: 'Retry holds the retry middleware configuration. This
|
||||
middleware reissues requests a given number of times to a backend
|
||||
server if that server does not reply. As soon as the server answers,
|
||||
the middleware stops retrying, regardless of the response status.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/retry/'
|
||||
properties:
|
||||
attempts:
|
||||
description: Attempts defines how many times the request should
|
||||
be retried.
|
||||
type: integer
|
||||
initialInterval:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: InitialInterval defines the first wait time in the
|
||||
exponential backoff series. The maximum interval is calculated
|
||||
as twice the initialInterval. If unspecified, requests will
|
||||
be retried immediately. The value of initialInterval should
|
||||
be provided in seconds or as a valid duration format, see https://pkg.go.dev/time#ParseDuration.
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
stripPrefix:
|
||||
description: StripPrefix holds the StripPrefix configuration.
|
||||
description: 'StripPrefix holds the strip prefix middleware configuration.
|
||||
This middleware removes the specified prefixes from the URL path.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/stripprefix/'
|
||||
properties:
|
||||
forceSlash:
|
||||
description: 'ForceSlash ensures that the resulting stripped path
|
||||
is not the empty string, by replacing it with / when necessary.
|
||||
Default: true.'
|
||||
type: boolean
|
||||
prefixes:
|
||||
description: Prefixes defines the prefixes to strip from the request
|
||||
URL.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
stripPrefixRegex:
|
||||
description: StripPrefixRegex holds the StripPrefixRegex configuration.
|
||||
description: 'StripPrefixRegex holds the strip prefix regex middleware
|
||||
configuration. This middleware removes the matching prefixes from
|
||||
the URL path. More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/stripprefixregex/'
|
||||
properties:
|
||||
regex:
|
||||
description: Regex defines the regular expression to match the
|
||||
path prefix from the request URL.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@@ -19,7 +19,8 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: MiddlewareTCP is a specification for a MiddlewareTCP resource.
|
||||
description: 'MiddlewareTCP is the CRD implementation of a Traefik TCP middleware.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/middlewares/overview/'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,19 +35,24 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
||||
description: MiddlewareTCPSpec defines the desired state of a MiddlewareTCP.
|
||||
properties:
|
||||
inFlightConn:
|
||||
description: TCPInFlightConn holds the TCP in flight connection configuration.
|
||||
description: InFlightConn defines the InFlightConn middleware configuration.
|
||||
properties:
|
||||
amount:
|
||||
description: Amount defines the maximum amount of allowed simultaneous
|
||||
connections. The middleware closes the connection if there are
|
||||
already amount connections opened.
|
||||
format: int64
|
||||
type: integer
|
||||
type: object
|
||||
ipWhiteList:
|
||||
description: TCPIPWhiteList holds the TCP ip white list configuration.
|
||||
description: IPWhiteList defines the IPWhiteList middleware configuration.
|
||||
properties:
|
||||
sourceRange:
|
||||
description: SourceRange defines the allowed IPs (or ranges of
|
||||
allowed IPs by using CIDR notation).
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
|
@@ -19,7 +19,10 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: ServersTransport is a specification for a ServersTransport resource.
|
||||
description: 'ServersTransport is the CRD implementation of a ServersTransport.
|
||||
If no serversTransport is specified, the default@internal will be used.
|
||||
The default@internal serversTransport is created from the static configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/services/#serverstransport_1'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,27 +37,28 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: ServersTransportSpec options to configure communication between
|
||||
Traefik and the servers.
|
||||
description: ServersTransportSpec defines the desired state of a ServersTransport.
|
||||
properties:
|
||||
certificatesSecrets:
|
||||
description: Certificates for mTLS.
|
||||
description: CertificatesSecrets defines a list of secret storing
|
||||
client certificates for mTLS.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
disableHTTP2:
|
||||
description: Disable HTTP/2 for connections with backend servers.
|
||||
description: DisableHTTP2 disables HTTP/2 for connections with backend
|
||||
servers.
|
||||
type: boolean
|
||||
forwardingTimeouts:
|
||||
description: Timeouts for requests forwarded to the backend servers.
|
||||
description: ForwardingTimeouts defines the timeouts for requests
|
||||
forwarded to the backend servers.
|
||||
properties:
|
||||
dialTimeout:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: DialTimeout is the amount of time to wait until a
|
||||
connection to a backend server can be established. If zero,
|
||||
no timeout exists.
|
||||
connection to a backend server can be established.
|
||||
x-kubernetes-int-or-string: true
|
||||
idleConnTimeout:
|
||||
anyOf:
|
||||
@@ -77,7 +81,7 @@ spec:
|
||||
- type: string
|
||||
description: ReadIdleTimeout is the timeout after which a health
|
||||
check using ping frame will be carried out if no frame is received
|
||||
on the HTTP/2 connection. If zero, no health check is performed.
|
||||
on the HTTP/2 connection.
|
||||
x-kubernetes-int-or-string: true
|
||||
responseHeaderTimeout:
|
||||
anyOf:
|
||||
@@ -85,27 +89,29 @@ spec:
|
||||
- type: string
|
||||
description: ResponseHeaderTimeout is the amount of time to wait
|
||||
for a server's response headers after fully writing the request
|
||||
(including its body, if any). If zero, no timeout exists.
|
||||
(including its body, if any).
|
||||
x-kubernetes-int-or-string: true
|
||||
type: object
|
||||
insecureSkipVerify:
|
||||
description: Disable SSL certificate verification.
|
||||
description: InsecureSkipVerify disables SSL certificate verification.
|
||||
type: boolean
|
||||
maxIdleConnsPerHost:
|
||||
description: If non-zero, controls the maximum idle (keep-alive) to
|
||||
keep per-host. If zero, DefaultMaxIdleConnsPerHost is used.
|
||||
description: MaxIdleConnsPerHost controls the maximum idle (keep-alive)
|
||||
to keep per-host.
|
||||
type: integer
|
||||
peerCertURI:
|
||||
description: URI used to match against SAN URI during the peer certificate
|
||||
verification.
|
||||
description: PeerCertURI defines the peer cert URI used to match against
|
||||
SAN URI during the peer certificate verification.
|
||||
type: string
|
||||
rootCAsSecrets:
|
||||
description: Add cert file for self-signed certificate.
|
||||
description: RootCAsSecrets defines a list of CA secret used to validate
|
||||
self-signed certificate.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
serverName:
|
||||
description: ServerName used to contact the server.
|
||||
description: ServerName defines the server name used to contact the
|
||||
server.
|
||||
type: string
|
||||
type: object
|
||||
required:
|
||||
|
@@ -19,7 +19,9 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: TLSOption is a specification for a TLSOption resource.
|
||||
description: 'TLSOption is the CRD implementation of a Traefik TLS Option,
|
||||
allowing to configure some parameters of the TLS connection. More info:
|
||||
https://doc.traefik.io/traefik/v2.8/https/tls/#tls-options'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,19 +36,24 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: TLSOptionSpec configures TLS for an entry point.
|
||||
description: TLSOptionSpec defines the desired state of a TLSOption.
|
||||
properties:
|
||||
alpnProtocols:
|
||||
description: 'ALPNProtocols defines the list of supported application
|
||||
level protocols for the TLS handshake, in order of preference. More
|
||||
info: https://doc.traefik.io/traefik/v2.8/https/tls/#alpn-protocols'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
cipherSuites:
|
||||
description: 'CipherSuites defines the list of supported cipher suites
|
||||
for TLS versions up to TLS 1.2. More info: https://doc.traefik.io/traefik/v2.8/https/tls/#cipher-suites'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
clientAuth:
|
||||
description: ClientAuth defines the parameters of the client authentication
|
||||
part of the TLS connection, if any.
|
||||
description: ClientAuth defines the server's policy for TLS Client
|
||||
Authentication.
|
||||
properties:
|
||||
clientAuthType:
|
||||
description: ClientAuthType defines the client authentication
|
||||
@@ -59,23 +66,36 @@ spec:
|
||||
- RequireAndVerifyClientCert
|
||||
type: string
|
||||
secretNames:
|
||||
description: SecretName is the name of the referenced Kubernetes
|
||||
Secret to specify the certificate details.
|
||||
description: SecretNames defines the names of the referenced Kubernetes
|
||||
Secret storing certificate details.
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
type: object
|
||||
curvePreferences:
|
||||
description: 'CurvePreferences defines the preferred elliptic curves
|
||||
in a specific order. More info: https://doc.traefik.io/traefik/v2.8/https/tls/#curve-preferences'
|
||||
items:
|
||||
type: string
|
||||
type: array
|
||||
maxVersion:
|
||||
description: 'MaxVersion defines the maximum TLS version that Traefik
|
||||
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
||||
VersionTLS13. Default: None.'
|
||||
type: string
|
||||
minVersion:
|
||||
description: 'MinVersion defines the minimum TLS version that Traefik
|
||||
will accept. Possible values: VersionTLS10, VersionTLS11, VersionTLS12,
|
||||
VersionTLS13. Default: VersionTLS10.'
|
||||
type: string
|
||||
preferServerCipherSuites:
|
||||
description: PreferServerCipherSuites defines whether the server chooses
|
||||
a cipher suite among his own instead of among the client's. It is
|
||||
enabled automatically when minVersion or maxVersion are set.
|
||||
type: boolean
|
||||
sniStrict:
|
||||
description: SniStrict defines whether Traefik allows connections
|
||||
from clients connections that do not specify a server_name extension.
|
||||
type: boolean
|
||||
type: object
|
||||
required:
|
||||
|
@@ -19,7 +19,10 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: TLSStore is a specification for a TLSStore resource.
|
||||
description: 'TLSStore is the CRD implementation of a Traefik TLS Store. For
|
||||
the time being, only the TLSStore named default is supported. This means
|
||||
that you cannot have two stores that are named default in different Kubernetes
|
||||
namespaces. More info: https://doc.traefik.io/traefik/v2.8/https/tls/#certificates-stores'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -34,7 +37,7 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: TLSStoreSpec configures a TLSStore resource.
|
||||
description: TLSStoreSpec defines the desired state of a TLSStore.
|
||||
properties:
|
||||
certificates:
|
||||
description: Certificates is a list of secret names, each secret holding
|
||||
@@ -51,8 +54,7 @@ spec:
|
||||
type: object
|
||||
type: array
|
||||
defaultCertificate:
|
||||
description: DefaultCertificate is the name of the secret holding
|
||||
the default key/certificate pair for the store.
|
||||
description: DefaultCertificate defines the default certificate configuration.
|
||||
properties:
|
||||
secretName:
|
||||
description: SecretName is the name of the referenced Kubernetes
|
||||
|
@@ -19,10 +19,9 @@ spec:
|
||||
- name: v1alpha1
|
||||
schema:
|
||||
openAPIV3Schema:
|
||||
description: TraefikService is the specification for a service (that an IngressRoute
|
||||
refers to) that is usually not a terminal service (i.e. not a pod of servers),
|
||||
as opposed to a Kubernetes Service. That is to say, it usually refers to
|
||||
other (children) services, which themselves can be TraefikServices or Services.
|
||||
description: 'TraefikService is the CRD implementation of a Traefik Service.
|
||||
TraefikService object allows to: - Apply weight to Services on load-balancing -
|
||||
Mirror traffic on services More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-traefikservice'
|
||||
properties:
|
||||
apiVersion:
|
||||
description: 'APIVersion defines the versioned schema of this representation
|
||||
@@ -37,220 +36,332 @@ spec:
|
||||
metadata:
|
||||
type: object
|
||||
spec:
|
||||
description: ServiceSpec defines whether a TraefikService is a load-balancer
|
||||
of services or a mirroring service.
|
||||
description: TraefikServiceSpec defines the desired state of a TraefikService.
|
||||
properties:
|
||||
mirroring:
|
||||
description: Mirroring defines a mirroring service, which is composed
|
||||
of a main load-balancer, and a list of mirrors.
|
||||
description: Mirroring defines the Mirroring service configuration.
|
||||
properties:
|
||||
kind:
|
||||
description: Kind defines the kind of the Service.
|
||||
enum:
|
||||
- Service
|
||||
- TraefikService
|
||||
type: string
|
||||
maxBodySize:
|
||||
description: MaxBodySize defines the maximum size allowed for
|
||||
the body of the request. If the body is larger, the request
|
||||
is not mirrored. Default value is -1, which means unlimited
|
||||
size.
|
||||
format: int64
|
||||
type: integer
|
||||
mirrors:
|
||||
description: Mirrors defines the list of mirrors where Traefik
|
||||
will duplicate the traffic.
|
||||
items:
|
||||
description: MirrorService defines one of the mirrors of a Mirroring
|
||||
service.
|
||||
description: MirrorService holds the mirror configuration.
|
||||
properties:
|
||||
kind:
|
||||
description: Kind defines the kind of the Service.
|
||||
enum:
|
||||
- Service
|
||||
- TraefikService
|
||||
type: string
|
||||
name:
|
||||
description: Name is a reference to a Kubernetes Service
|
||||
object (for a load-balancer of servers), or to a TraefikService
|
||||
object (service load-balancer, mirroring, etc). The differentiation
|
||||
between the two is specified in the Kind field.
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service or TraefikService. The differentiation between
|
||||
the two is specified in the Kind field.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service or TraefikService.
|
||||
type: string
|
||||
passHostHeader:
|
||||
description: PassHostHeader defines whether the client Host
|
||||
header is forwarded to the upstream Kubernetes Service.
|
||||
By default, passHostHeader is true.
|
||||
type: boolean
|
||||
percent:
|
||||
description: 'Percent defines the part of the traffic to
|
||||
mirror. Supported values: 0 to 100.'
|
||||
type: integer
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service.
|
||||
This can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
responseForwarding:
|
||||
description: ResponseForwarding holds configuration for
|
||||
the forward of the response.
|
||||
description: ResponseForwarding defines how Traefik forwards
|
||||
the response from the upstream Kubernetes Service to the
|
||||
client.
|
||||
properties:
|
||||
flushInterval:
|
||||
description: 'FlushInterval defines the interval, in
|
||||
milliseconds, in between flushes to the client while
|
||||
copying the response body. A negative value means
|
||||
to flush immediately after each write to the client.
|
||||
This configuration is ignored when ReverseProxy recognizes
|
||||
a response as a streaming response; for such responses,
|
||||
writes are flushed to the client immediately. Default:
|
||||
100ms'
|
||||
type: string
|
||||
type: object
|
||||
scheme:
|
||||
description: Scheme defines the scheme to use for the request
|
||||
to the upstream Kubernetes Service. It defaults to https
|
||||
when Kubernetes Service port is 443, http otherwise.
|
||||
type: string
|
||||
serversTransport:
|
||||
description: ServersTransport defines the name of ServersTransport
|
||||
resource to use. It allows to configure the transport
|
||||
between Traefik and your servers. Can only be used on
|
||||
a Kubernetes Service.
|
||||
type: string
|
||||
sticky:
|
||||
description: Sticky holds the sticky configuration.
|
||||
description: 'Sticky defines the sticky sessions configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/services/#sticky-sessions'
|
||||
properties:
|
||||
cookie:
|
||||
description: Cookie holds the sticky configuration based
|
||||
on cookie.
|
||||
description: Cookie defines the sticky cookie configuration.
|
||||
properties:
|
||||
httpOnly:
|
||||
description: HTTPOnly defines whether the cookie
|
||||
can be accessed by client-side APIs, such as JavaScript.
|
||||
type: boolean
|
||||
name:
|
||||
description: Name defines the Cookie name.
|
||||
type: string
|
||||
sameSite:
|
||||
description: 'SameSite defines the same site policy.
|
||||
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite'
|
||||
type: string
|
||||
secure:
|
||||
description: Secure defines whether the cookie can
|
||||
only be transmitted over an encrypted connection
|
||||
(i.e. HTTPS).
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
strategy:
|
||||
description: Strategy defines the load balancing strategy
|
||||
between the servers. RoundRobin is the only supported
|
||||
value at the moment.
|
||||
type: string
|
||||
weight:
|
||||
description: Weight should only be specified when Name references
|
||||
a TraefikService object (and to be precise, one that embeds
|
||||
a Weighted Round Robin).
|
||||
description: Weight defines the weight and should only be
|
||||
specified when Name references a TraefikService object
|
||||
(and to be precise, one that embeds a Weighted Round Robin).
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
name:
|
||||
description: Name is a reference to a Kubernetes Service object
|
||||
(for a load-balancer of servers), or to a TraefikService object
|
||||
(service load-balancer, mirroring, etc). The differentiation
|
||||
between the two is specified in the Kind field.
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service or TraefikService. The differentiation between the two
|
||||
is specified in the Kind field.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service or TraefikService.
|
||||
type: string
|
||||
passHostHeader:
|
||||
description: PassHostHeader defines whether the client Host header
|
||||
is forwarded to the upstream Kubernetes Service. By default,
|
||||
passHostHeader is true.
|
||||
type: boolean
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service. This
|
||||
can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
responseForwarding:
|
||||
description: ResponseForwarding holds configuration for the forward
|
||||
of the response.
|
||||
description: ResponseForwarding defines how Traefik forwards the
|
||||
response from the upstream Kubernetes Service to the client.
|
||||
properties:
|
||||
flushInterval:
|
||||
description: 'FlushInterval defines the interval, in milliseconds,
|
||||
in between flushes to the client while copying the response
|
||||
body. A negative value means to flush immediately after
|
||||
each write to the client. This configuration is ignored
|
||||
when ReverseProxy recognizes a response as a streaming response;
|
||||
for such responses, writes are flushed to the client immediately.
|
||||
Default: 100ms'
|
||||
type: string
|
||||
type: object
|
||||
scheme:
|
||||
description: Scheme defines the scheme to use for the request
|
||||
to the upstream Kubernetes Service. It defaults to https when
|
||||
Kubernetes Service port is 443, http otherwise.
|
||||
type: string
|
||||
serversTransport:
|
||||
description: ServersTransport defines the name of ServersTransport
|
||||
resource to use. It allows to configure the transport between
|
||||
Traefik and your servers. Can only be used on a Kubernetes Service.
|
||||
type: string
|
||||
sticky:
|
||||
description: Sticky holds the sticky configuration.
|
||||
description: 'Sticky defines the sticky sessions configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/services/#sticky-sessions'
|
||||
properties:
|
||||
cookie:
|
||||
description: Cookie holds the sticky configuration based on
|
||||
cookie.
|
||||
description: Cookie defines the sticky cookie configuration.
|
||||
properties:
|
||||
httpOnly:
|
||||
description: HTTPOnly defines whether the cookie can be
|
||||
accessed by client-side APIs, such as JavaScript.
|
||||
type: boolean
|
||||
name:
|
||||
description: Name defines the Cookie name.
|
||||
type: string
|
||||
sameSite:
|
||||
description: 'SameSite defines the same site policy. More
|
||||
info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite'
|
||||
type: string
|
||||
secure:
|
||||
description: Secure defines whether the cookie can only
|
||||
be transmitted over an encrypted connection (i.e. HTTPS).
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
strategy:
|
||||
description: Strategy defines the load balancing strategy between
|
||||
the servers. RoundRobin is the only supported value at the moment.
|
||||
type: string
|
||||
weight:
|
||||
description: Weight should only be specified when Name references
|
||||
a TraefikService object (and to be precise, one that embeds
|
||||
a Weighted Round Robin).
|
||||
description: Weight defines the weight and should only be specified
|
||||
when Name references a TraefikService object (and to be precise,
|
||||
one that embeds a Weighted Round Robin).
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
weighted:
|
||||
description: WeightedRoundRobin defines a load-balancer of services.
|
||||
description: Weighted defines the Weighted Round Robin configuration.
|
||||
properties:
|
||||
services:
|
||||
description: Services defines the list of Kubernetes Service and/or
|
||||
TraefikService to load-balance, with weight.
|
||||
items:
|
||||
description: Service defines an upstream to proxy traffic.
|
||||
description: Service defines an upstream HTTP service to proxy
|
||||
traffic to.
|
||||
properties:
|
||||
kind:
|
||||
description: Kind defines the kind of the Service.
|
||||
enum:
|
||||
- Service
|
||||
- TraefikService
|
||||
type: string
|
||||
name:
|
||||
description: Name is a reference to a Kubernetes Service
|
||||
object (for a load-balancer of servers), or to a TraefikService
|
||||
object (service load-balancer, mirroring, etc). The differentiation
|
||||
between the two is specified in the Kind field.
|
||||
description: Name defines the name of the referenced Kubernetes
|
||||
Service or TraefikService. The differentiation between
|
||||
the two is specified in the Kind field.
|
||||
type: string
|
||||
namespace:
|
||||
description: Namespace defines the namespace of the referenced
|
||||
Kubernetes Service or TraefikService.
|
||||
type: string
|
||||
passHostHeader:
|
||||
description: PassHostHeader defines whether the client Host
|
||||
header is forwarded to the upstream Kubernetes Service.
|
||||
By default, passHostHeader is true.
|
||||
type: boolean
|
||||
port:
|
||||
anyOf:
|
||||
- type: integer
|
||||
- type: string
|
||||
description: Port defines the port of a Kubernetes Service.
|
||||
This can be a reference to a named port.
|
||||
x-kubernetes-int-or-string: true
|
||||
responseForwarding:
|
||||
description: ResponseForwarding holds configuration for
|
||||
the forward of the response.
|
||||
description: ResponseForwarding defines how Traefik forwards
|
||||
the response from the upstream Kubernetes Service to the
|
||||
client.
|
||||
properties:
|
||||
flushInterval:
|
||||
description: 'FlushInterval defines the interval, in
|
||||
milliseconds, in between flushes to the client while
|
||||
copying the response body. A negative value means
|
||||
to flush immediately after each write to the client.
|
||||
This configuration is ignored when ReverseProxy recognizes
|
||||
a response as a streaming response; for such responses,
|
||||
writes are flushed to the client immediately. Default:
|
||||
100ms'
|
||||
type: string
|
||||
type: object
|
||||
scheme:
|
||||
description: Scheme defines the scheme to use for the request
|
||||
to the upstream Kubernetes Service. It defaults to https
|
||||
when Kubernetes Service port is 443, http otherwise.
|
||||
type: string
|
||||
serversTransport:
|
||||
description: ServersTransport defines the name of ServersTransport
|
||||
resource to use. It allows to configure the transport
|
||||
between Traefik and your servers. Can only be used on
|
||||
a Kubernetes Service.
|
||||
type: string
|
||||
sticky:
|
||||
description: Sticky holds the sticky configuration.
|
||||
description: 'Sticky defines the sticky sessions configuration.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/services/#sticky-sessions'
|
||||
properties:
|
||||
cookie:
|
||||
description: Cookie holds the sticky configuration based
|
||||
on cookie.
|
||||
description: Cookie defines the sticky cookie configuration.
|
||||
properties:
|
||||
httpOnly:
|
||||
description: HTTPOnly defines whether the cookie
|
||||
can be accessed by client-side APIs, such as JavaScript.
|
||||
type: boolean
|
||||
name:
|
||||
description: Name defines the Cookie name.
|
||||
type: string
|
||||
sameSite:
|
||||
description: 'SameSite defines the same site policy.
|
||||
More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite'
|
||||
type: string
|
||||
secure:
|
||||
description: Secure defines whether the cookie can
|
||||
only be transmitted over an encrypted connection
|
||||
(i.e. HTTPS).
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
strategy:
|
||||
description: Strategy defines the load balancing strategy
|
||||
between the servers. RoundRobin is the only supported
|
||||
value at the moment.
|
||||
type: string
|
||||
weight:
|
||||
description: Weight should only be specified when Name references
|
||||
a TraefikService object (and to be precise, one that embeds
|
||||
a Weighted Round Robin).
|
||||
description: Weight defines the weight and should only be
|
||||
specified when Name references a TraefikService object
|
||||
(and to be precise, one that embeds a Weighted Round Robin).
|
||||
type: integer
|
||||
required:
|
||||
- name
|
||||
type: object
|
||||
type: array
|
||||
sticky:
|
||||
description: Sticky holds the sticky configuration.
|
||||
description: 'Sticky defines whether sticky sessions are enabled.
|
||||
More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#stickiness-and-load-balancing'
|
||||
properties:
|
||||
cookie:
|
||||
description: Cookie holds the sticky configuration based on
|
||||
cookie.
|
||||
description: Cookie defines the sticky cookie configuration.
|
||||
properties:
|
||||
httpOnly:
|
||||
description: HTTPOnly defines whether the cookie can be
|
||||
accessed by client-side APIs, such as JavaScript.
|
||||
type: boolean
|
||||
name:
|
||||
description: Name defines the Cookie name.
|
||||
type: string
|
||||
sameSite:
|
||||
description: 'SameSite defines the same site policy. More
|
||||
info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite'
|
||||
type: string
|
||||
secure:
|
||||
description: Secure defines whether the cookie can only
|
||||
be transmitted over an encrypted connection (i.e. HTTPS).
|
||||
type: boolean
|
||||
type: object
|
||||
type: object
|
||||
|
@@ -967,3 +967,18 @@ entryPoints:
|
||||
entrypoints.foo.address=:8000/udp
|
||||
entrypoints.foo.udp.timeout=10s
|
||||
```
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -298,10 +298,10 @@ You can find an excerpt of the available custom resources in the table below:
|
||||
| Kind | Purpose | Concept Behind |
|
||||
|--------------------------------------------|--------------------------------------------------------------------|----------------------------------------------------------------|
|
||||
| [IngressRoute](#kind-ingressroute) | HTTP Routing | [HTTP router](../routers/index.md#configuring-http-routers) |
|
||||
| [Middleware](#kind-middleware) | Tweaks the HTTP requests before they are sent to your service | [HTTP Middlewares](../../middlewares/http/overview.md) |
|
||||
| [Middleware](#kind-middleware) | Tweaks the HTTP requests before they are sent to your service | [HTTP Middlewares](../../middlewares/http/overview.md) |
|
||||
| [TraefikService](#kind-traefikservice) | Abstraction for HTTP loadbalancing/mirroring | [HTTP service](../services/index.md#configuring-http-services) |
|
||||
| [IngressRouteTCP](#kind-ingressroutetcp) | TCP Routing | [TCP router](../routers/index.md#configuring-tcp-routers) |
|
||||
| [MiddlewareTCP](#kind-middlewaretcp) | Tweaks the TCP requests before they are sent to your service | [TCP Middlewares](../../middlewares/tcp/overview.md) |
|
||||
| [MiddlewareTCP](#kind-middlewaretcp) | Tweaks the TCP requests before they are sent to your service | [TCP Middlewares](../../middlewares/tcp/overview.md) |
|
||||
| [IngressRouteUDP](#kind-ingressrouteudp) | UDP Routing | [UDP router](../routers/index.md#configuring-udp-routers) |
|
||||
| [TLSOptions](#kind-tlsoption) | Allows to configure some parameters of the TLS connection | [TLSOptions](../../https/tls.md#tls-options) |
|
||||
| [TLSStores](#kind-tlsstore) | Allows to configure the default TLS store | [TLSStores](../../https/tls.md#certificates-stores) |
|
||||
@@ -583,6 +583,62 @@ Register the `IngressRoute` [kind](../../reference/dynamic-configuration/kuberne
|
||||
- port: 80
|
||||
```
|
||||
|
||||
#### Load Balancing
|
||||
|
||||
More information in the dedicated server [load balancing](../services/index.md#load-balancing) section.
|
||||
|
||||
!!! info "Declaring and using Kubernetes Service Load Balancing"
|
||||
|
||||
```yaml tab="IngressRoute"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: ingressroutebar
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`example.com`) && PathPrefix(`/foo`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: svc1
|
||||
namespace: default
|
||||
- name: svc2
|
||||
namespace: default
|
||||
```
|
||||
|
||||
```yaml tab="K8s Service"
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: svc1
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
selector:
|
||||
app: traefiklabs
|
||||
task: app1
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: svc2
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
selector:
|
||||
app: traefiklabs
|
||||
task: app2
|
||||
```
|
||||
|
||||
### Kind: `Middleware`
|
||||
|
||||
`Middleware` is the CRD implementation of a [Traefik middleware](../../middlewares/http/overview.md).
|
||||
@@ -642,7 +698,7 @@ More information about available middlewares in the dedicated [middlewares secti
|
||||
Register the `TraefikService` [kind](../../reference/dynamic-configuration/kubernetes-crd.md#definitions) in the Kubernetes cluster before creating `TraefikService` objects,
|
||||
referencing services in the [`IngressRoute`](#kind-ingressroute) objects, or recursively in others `TraefikService` objects.
|
||||
|
||||
!!! info "Disambiguate Traefik and Kubernetes Services "
|
||||
!!! info "Disambiguate Traefik and Kubernetes Services"
|
||||
|
||||
As the field `name` can reference different types of objects, use the field `kind` to avoid any ambiguity.
|
||||
|
||||
@@ -653,65 +709,8 @@ referencing services in the [`IngressRoute`](#kind-ingressroute) objects, or rec
|
||||
|
||||
`TraefikService` object allows to use any (valid) combinations of:
|
||||
|
||||
* servers [load balancing](#server-load-balancing).
|
||||
* services [Weighted Round Robin](#weighted-round-robin) load balancing.
|
||||
* services [mirroring](#mirroring).
|
||||
|
||||
#### Server Load Balancing
|
||||
|
||||
More information in the dedicated server [load balancing](../services/index.md#load-balancing) section.
|
||||
|
||||
??? "Declaring and Using Server Load Balancing"
|
||||
|
||||
```yaml tab="IngressRoute"
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: IngressRoute
|
||||
metadata:
|
||||
name: ingressroutebar
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
entryPoints:
|
||||
- web
|
||||
routes:
|
||||
- match: Host(`example.com`) && PathPrefix(`/foo`)
|
||||
kind: Rule
|
||||
services:
|
||||
- name: svc1
|
||||
namespace: default
|
||||
- name: svc2
|
||||
namespace: default
|
||||
```
|
||||
|
||||
```yaml tab="K8s Service"
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: svc1
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
selector:
|
||||
app: traefiklabs
|
||||
task: app1
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: Service
|
||||
metadata:
|
||||
name: svc2
|
||||
namespace: default
|
||||
|
||||
spec:
|
||||
ports:
|
||||
- name: http
|
||||
port: 80
|
||||
selector:
|
||||
app: traefiklabs
|
||||
task: app2
|
||||
```
|
||||
* [Weighted Round Robin](#weighted-round-robin) load balancing.
|
||||
* [Mirroring](#mirroring).
|
||||
|
||||
#### Weighted Round Robin
|
||||
|
||||
@@ -1074,7 +1073,7 @@ and there is a second level because each whoami service is a `replicaset` and is
|
||||
|
||||
assuming `10.42.0.6` is the IP address of one of the replicas (a pod then) of the `whoami1` service.
|
||||
|
||||
### Kind `IngressRouteTCP`
|
||||
### Kind: `IngressRouteTCP`
|
||||
|
||||
`IngressRouteTCP` is the CRD implementation of a [Traefik TCP router](../routers/index.md#configuring-tcp-routers).
|
||||
|
||||
@@ -1327,7 +1326,7 @@ Register the `MiddlewareTCP` [kind](../../reference/dynamic-configuration/kubern
|
||||
|
||||
More information about available TCP middlewares in the dedicated [middlewares section](../../middlewares/tcp/overview.md).
|
||||
|
||||
### Kind `IngressRouteUDP`
|
||||
### Kind: `IngressRouteUDP`
|
||||
|
||||
`IngressRouteUDP` is the CRD implementation of a [Traefik UDP router](../routers/index.md#configuring-udp-routers).
|
||||
|
||||
@@ -1616,8 +1615,7 @@ or referencing TLS stores in the [`IngressRoute`](#kind-ingressroute) / [`Ingres
|
||||
!!! important "Default TLS Store"
|
||||
|
||||
Traefik currently only uses the [TLS Store named "default"](../../https/tls.md#certificates-stores).
|
||||
This means that if you have two stores that are named default in different kubernetes namespaces,
|
||||
they may be randomly chosen.
|
||||
This means that you cannot have two stores that are named default in different Kubernetes namespaces.
|
||||
For the time being, please only configure one TLSStore named default.
|
||||
|
||||
!!! info "TLSStore Attributes"
|
||||
|
@@ -673,6 +673,21 @@ If no matching route is found for the TCP routers, then the HTTP routers will ta
|
||||
If not specified, TCP routers will accept requests from all defined entry points.
|
||||
If you want to limit the router scope to a set of entry points, set the entry points option.
|
||||
|
||||
??? info "How to handle Server First protocols?"
|
||||
|
||||
To correctly handle a request, Traefik needs to wait for the first
|
||||
few bytes to arrive before it can decide what to do with it.
|
||||
|
||||
For protocols where the server is expected to send first, such
|
||||
as SMTP, if no specific setup is in place, we could end up in
|
||||
a situation where both sides are waiting for data and the
|
||||
connection appears to have hanged.
|
||||
|
||||
The only way that Traefik can deal with such a case, is to make
|
||||
sure that on the concerned entry point, there is no TLS router
|
||||
whatsoever (neither TCP nor HTTP), and there is at least one
|
||||
non-TLS TCP router that leads to the server in question.
|
||||
|
||||
??? example "Listens to Every Entry Point"
|
||||
|
||||
**Dynamic Configuration**
|
||||
@@ -1306,3 +1321,18 @@ There must be one (and only one) UDP [service](../services/index.md) referenced
|
||||
Services are the target for the router.
|
||||
|
||||
!!! important "UDP routers can only target UDP services (and not HTTP or TCP services)."
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
@@ -322,14 +322,14 @@ To propagate status changes (e.g. all servers of this service are down) upwards,
|
||||
|
||||
Below are the available options for the health check mechanism:
|
||||
|
||||
- `path` is appended to the server URL to set the health check endpoint.
|
||||
- `scheme`, if defined, will replace the server URL `scheme` for the health check endpoint
|
||||
- `hostname`, if defined, will apply `Host` header `hostname` to the health check request.
|
||||
- `port`, if defined, will replace the server URL `port` for the health check endpoint.
|
||||
- `interval` defines the frequency of the health check calls.
|
||||
- `timeout` defines the maximum duration Traefik will wait for a health check request before considering the server failed (unhealthy).
|
||||
- `headers` defines custom headers to be sent to the health check endpoint.
|
||||
- `followRedirects` defines whether redirects should be followed during the health check calls (default: true).
|
||||
- `path` (required), defines the server URL path for the health check endpoint .
|
||||
- `scheme` (optional), replaces the server URL `scheme` for the health check endpoint.
|
||||
- `hostname` (optional), sets the value of `hostname` in the `Host` header of the health check request.
|
||||
- `port` (optional), replaces the server URL `port` for the health check endpoint.
|
||||
- `interval` (default: 30s), defines the frequency of the health check calls.
|
||||
- `timeout` (default: 5s), defines the maximum duration Traefik will wait for a health check request before considering the server unhealthy.
|
||||
- `headers` (optional), defines custom headers to be sent to the health check endpoint.
|
||||
- `followRedirects` (default: true), defines whether redirects should be followed during the health check calls.
|
||||
|
||||
!!! info "Interval & Timeout Format"
|
||||
|
||||
@@ -1645,3 +1645,18 @@ udp:
|
||||
[[udp.services.appv2.loadBalancer.servers]]
|
||||
address = "private-ip-server-2:8080/"
|
||||
```
|
||||
|
||||
!!! question "Using Traefik for Business Applications?"
|
||||
|
||||
If you are using Traefik for commercial applications,
|
||||
consider the [Enterprise Edition](https://traefik.io/traefik-enterprise/).
|
||||
You can use it as your:
|
||||
|
||||
- [Kubernetes Ingress Controller](https://traefik.io/solutions/kubernetes-ingress/)
|
||||
- [Load Balancer](https://traefik.io/solutions/docker-swarm-ingress/)
|
||||
- [API Gateway](https://traefik.io/solutions/api-gateway/)
|
||||
|
||||
Traefik Enterprise enables centralized access management,
|
||||
distributed Let's Encrypt,
|
||||
and other advanced capabilities.
|
||||
Learn more in [this 15-minute technical walkthrough](https://info.traefik.io/watch-traefikee-demo).
|
||||
|
17
docs/content/user-guides/crd-acme/05-tlsoption.yml
Normal file
17
docs/content/user-guides/crd-acme/05-tlsoption.yml
Normal file
@@ -0,0 +1,17 @@
|
||||
---
|
||||
apiVersion: traefik.containo.us/v1alpha1
|
||||
kind: TLSOption
|
||||
metadata:
|
||||
name: default
|
||||
namespace: default
|
||||
spec:
|
||||
minVersion: VersionTLS12
|
||||
cipherSuites:
|
||||
- TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 # TLS 1.2
|
||||
- TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305 # TLS 1.2
|
||||
- TLS_AES_256_GCM_SHA384 # TLS 1.3
|
||||
- TLS_CHACHA20_POLY1305_SHA256 # TLS 1.3
|
||||
curvePreferences:
|
||||
- CurveP521
|
||||
- CurveP384
|
||||
sniStrict: true
|
@@ -44,20 +44,25 @@ Let's now have a look (in the order they should be applied, if using `kubectl ap
|
||||
|
||||
### IngressRoute Definition
|
||||
|
||||
First, the definition of the `IngressRoute` and the `Middleware` kinds.
|
||||
Also note the RBAC authorization resources; they'll be referenced through the `serviceAccountName` of the deployment, later on.
|
||||
First, you will need to install Traefik CRDs containing the definition of the `IngressRoute` and the `Middleware` kinds,
|
||||
and the RBAC authorization resources which will be referenced through the `serviceAccountName` of the deployment.
|
||||
|
||||
```yaml
|
||||
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml"
|
||||
```bash
|
||||
# Install Traefik Resource Definitions:
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
|
||||
|
||||
---
|
||||
--8<-- "content/reference/dynamic-configuration/kubernetes-crd-rbac.yml"
|
||||
# Install RBAC for Traefik:
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/reference/dynamic-configuration/kubernetes-crd-rbac.yml
|
||||
```
|
||||
|
||||
### Services
|
||||
|
||||
Then, the services. One for Traefik itself, and one for the app it routes for, i.e. in this case our demo HTTP server: [whoami](https://github.com/traefik/whoami).
|
||||
|
||||
```bash
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/user-guides/crd-acme/02-services.yml
|
||||
```
|
||||
|
||||
```yaml
|
||||
--8<-- "content/user-guides/crd-acme/02-services.yml"
|
||||
```
|
||||
@@ -67,6 +72,10 @@ Then, the services. One for Traefik itself, and one for the app it routes for, i
|
||||
Next, the deployments, i.e. the actual pods behind the services.
|
||||
Again, one pod for Traefik, and one for the whoami app.
|
||||
|
||||
```bash
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/user-guides/crd-acme/03-deployments.yml
|
||||
```
|
||||
|
||||
```yaml
|
||||
--8<-- "content/user-guides/crd-acme/03-deployments.yml"
|
||||
```
|
||||
@@ -91,7 +100,7 @@ Look it up.
|
||||
We can now finally apply the actual ingressRoutes, with:
|
||||
|
||||
```bash
|
||||
kubectl apply -f 04-ingressroutes.yml
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/user-guides/crd-acme/04-ingressroutes.yml
|
||||
```
|
||||
|
||||
```yaml
|
||||
@@ -110,3 +119,16 @@ curl http://your.example.com:8000/notls
|
||||
```
|
||||
|
||||
Note that you'll have to use `-k` as long as you're using the staging server of Let's Encrypt, since it is not an authorized certificate authority on systems where it hasn't been manually added.
|
||||
|
||||
### Force TLS v1.2+
|
||||
|
||||
Nowadays, TLS v1.0 and v1.1 are deprecated.
|
||||
In order to force TLS v1.2 or later on all your IngressRoute, you can define the `default` TLSOption:
|
||||
|
||||
```bash
|
||||
kubectl apply -f https://raw.githubusercontent.com/traefik/traefik/v2.8/docs/content/user-guides/crd-acme/05-tlsoption.yml
|
||||
```
|
||||
|
||||
```yaml
|
||||
--8<-- "content/user-guides/crd-acme/05-tlsoption.yml"
|
||||
```
|
||||
|
64
go.mod
64
go.mod
@@ -28,15 +28,15 @@ require (
|
||||
github.com/gorilla/websocket v1.5.0
|
||||
github.com/hashicorp/consul v1.10.4
|
||||
github.com/hashicorp/consul/api v1.12.0
|
||||
github.com/hashicorp/go-hclog v0.16.1
|
||||
github.com/hashicorp/go-hclog v0.16.2
|
||||
github.com/hashicorp/go-multierror v1.1.1
|
||||
github.com/hashicorp/go-version v1.3.0
|
||||
github.com/hashicorp/nomad/api v0.0.0-20220506174431-b5665129cd1f
|
||||
github.com/influxdata/influxdb-client-go/v2 v2.7.0
|
||||
github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d
|
||||
github.com/instana/go-sensor v1.38.3
|
||||
github.com/klauspost/compress v1.13.0
|
||||
github.com/kvtools/valkeyrie v0.4.0
|
||||
github.com/klauspost/compress v1.14.2
|
||||
github.com/kvtools/valkeyrie v0.4.1
|
||||
github.com/lucas-clemente/quic-go v0.27.0
|
||||
github.com/mailgun/ttlmap v0.0.0-20170619185759-c1c17f74874f
|
||||
github.com/miekg/dns v1.1.47
|
||||
@@ -49,14 +49,14 @@ require (
|
||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||
github.com/pires/go-proxyproto v0.6.1
|
||||
github.com/pmezard/go-difflib v1.0.0
|
||||
github.com/prometheus/client_golang v1.11.0
|
||||
github.com/prometheus/client_golang v1.12.2-0.20220704083116-e8f91604d835
|
||||
github.com/prometheus/client_model v0.2.0
|
||||
github.com/rancher/go-rancher-metadata v0.0.0-20200311180630-7f4c936a06ac
|
||||
github.com/sirupsen/logrus v1.8.1
|
||||
github.com/stretchr/testify v1.7.1
|
||||
github.com/stretchr/testify v1.7.5
|
||||
github.com/stvp/go-udp-testing v0.0.0-20191102171040-06b61409b154
|
||||
github.com/traefik/paerser v0.1.5
|
||||
github.com/traefik/yaegi v0.12.0
|
||||
github.com/traefik/yaegi v0.13.0
|
||||
github.com/uber/jaeger-client-go v2.30.0+incompatible
|
||||
github.com/uber/jaeger-lib v2.2.0+incompatible
|
||||
github.com/unrolled/render v1.0.2
|
||||
@@ -68,12 +68,12 @@ require (
|
||||
go.elastic.co/apm/module/apmot v1.13.1
|
||||
golang.org/x/mod v0.4.2
|
||||
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4
|
||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac
|
||||
golang.org/x/time v0.0.0-20211116232009-f0f3c7e86c11
|
||||
golang.org/x/tools v0.1.6-0.20210726203631-07bc1bf47fb2
|
||||
google.golang.org/grpc v1.38.0
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.19.0
|
||||
gopkg.in/DataDog/dd-trace-go.v1 v1.38.1
|
||||
gopkg.in/fsnotify.v1 v1.4.7
|
||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b
|
||||
gopkg.in/yaml.v3 v3.0.1
|
||||
k8s.io/api v0.22.1
|
||||
k8s.io/apiextensions-apiserver v0.21.3
|
||||
k8s.io/apimachinery v0.22.1
|
||||
@@ -98,11 +98,14 @@ require (
|
||||
github.com/Azure/go-autorest/autorest/validation v0.3.1 // indirect
|
||||
github.com/Azure/go-autorest/logger v0.2.1 // indirect
|
||||
github.com/Azure/go-autorest/tracing v0.6.0 // indirect
|
||||
github.com/DataDog/datadog-go v3.2.0+incompatible // indirect
|
||||
github.com/DataDog/datadog-agent/pkg/obfuscate v0.0.0-20211129110424-6491aa3bf583 // indirect
|
||||
github.com/DataDog/datadog-go v4.8.2+incompatible // indirect
|
||||
github.com/DataDog/datadog-go/v5 v5.0.2 // indirect
|
||||
github.com/DataDog/sketches-go v1.0.0 // indirect
|
||||
github.com/HdrHistogram/hdrhistogram-go v1.1.2 // indirect
|
||||
github.com/Masterminds/goutils v1.1.1 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.1.1 // indirect
|
||||
github.com/Microsoft/go-winio v0.4.17 // indirect
|
||||
github.com/Microsoft/go-winio v0.5.1 // indirect
|
||||
github.com/Microsoft/hcsshim v0.8.23 // indirect
|
||||
github.com/OpenDNS/vegadns2client v0.0.0-20180418235048-a3fa4a771d87 // indirect
|
||||
github.com/Shopify/sarama v1.23.1 // indirect
|
||||
@@ -115,7 +118,7 @@ require (
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc // indirect
|
||||
github.com/buger/goterm v1.0.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.1 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.1.2 // indirect
|
||||
github.com/cheekybits/genny v1.0.0 // indirect
|
||||
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible // indirect
|
||||
github.com/circonus-labs/circonusllhist v0.1.3 // indirect
|
||||
@@ -130,6 +133,7 @@ require (
|
||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
||||
github.com/cpu/goacmedns v0.1.1 // indirect
|
||||
github.com/deepmap/oapi-codegen v1.8.2 // indirect
|
||||
github.com/dgraph-io/ristretto v0.1.0 // indirect
|
||||
github.com/dimchansky/utfbom v1.1.1 // indirect
|
||||
github.com/distribution/distribution/v3 v3.0.0-20210316161203-a01c71e2477e // indirect
|
||||
github.com/dnsimple/dnsimple-go v0.70.1 // indirect
|
||||
@@ -140,6 +144,7 @@ require (
|
||||
github.com/docker/go-metrics v0.0.1 // indirect
|
||||
github.com/docker/go-units v0.4.0 // indirect
|
||||
github.com/donovanhide/eventsource v0.0.0-20170630084216-b8f31a59085e // indirect
|
||||
github.com/dustin/go-humanize v1.0.0 // indirect
|
||||
github.com/elastic/go-licenser v0.3.1 // indirect
|
||||
github.com/elastic/go-sysinfo v1.1.1 // indirect
|
||||
github.com/elastic/go-windows v1.0.0 // indirect
|
||||
@@ -150,18 +155,18 @@ require (
|
||||
github.com/fsnotify/fsnotify v1.5.1 // indirect
|
||||
github.com/fvbommel/sortorder v1.0.1 // indirect
|
||||
github.com/go-errors/errors v1.0.1 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.0 // indirect
|
||||
github.com/go-logfmt/logfmt v0.5.1 // indirect
|
||||
github.com/go-logr/logr v0.4.0 // indirect
|
||||
github.com/go-resty/resty/v2 v2.1.1-0.20191201195748-d7b97669fe48 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20210107165309-348f09dbbbc0 // indirect
|
||||
github.com/go-zookeeper/zk v1.0.2 // indirect
|
||||
github.com/gofrs/flock v0.8.0 // indirect
|
||||
github.com/gofrs/uuid v3.3.0+incompatible // indirect
|
||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
||||
github.com/gogo/googleapis v1.4.0 // indirect
|
||||
github.com/gogo/protobuf v1.3.2 // indirect
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b // indirect
|
||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
||||
github.com/golang/mock v1.6.0 // indirect
|
||||
github.com/golang/snappy v0.0.3 // indirect
|
||||
github.com/google/btree v1.0.1 // indirect
|
||||
github.com/google/go-cmp v0.5.7 // indirect
|
||||
github.com/google/go-querystring v1.1.0 // indirect
|
||||
@@ -172,15 +177,14 @@ require (
|
||||
github.com/googleapis/gnostic v0.5.5 // indirect
|
||||
github.com/gophercloud/gophercloud v0.16.0 // indirect
|
||||
github.com/gophercloud/utils v0.0.0-20210216074907-f6de111f2eae // indirect
|
||||
github.com/gorilla/context v1.1.1 // indirect
|
||||
github.com/gravitational/trace v1.1.16-0.20220114165159-14a9a7dd6aaf // indirect
|
||||
github.com/grpc-ecosystem/go-grpc-middleware v1.2.0 // indirect
|
||||
github.com/grpc-ecosystem/grpc-opentracing v0.0.0-20180507213350-8e809c8a8645 // indirect
|
||||
github.com/hashicorp/consul/sdk v0.8.0 // indirect
|
||||
github.com/hashicorp/cronexpr v1.1.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.0.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.0 // indirect
|
||||
github.com/hashicorp/go-immutable-radix v1.3.1 // indirect
|
||||
github.com/hashicorp/go-msgpack v0.5.5 // indirect
|
||||
github.com/hashicorp/go-retryablehttp v0.7.1 // indirect
|
||||
github.com/hashicorp/go-rootcerts v1.0.2 // indirect
|
||||
@@ -205,6 +209,7 @@ require (
|
||||
github.com/jmespath/go-jmespath v0.4.0 // indirect
|
||||
github.com/joeshaw/multierror v0.0.0-20140124173710-69b34d4ec901 // indirect
|
||||
github.com/jonboulle/clockwork v0.2.2 // indirect
|
||||
github.com/josharian/intern v1.0.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/k0kubun/go-ansi v0.0.0-20180517002512-3bf9e2903213 // indirect
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
|
||||
@@ -219,12 +224,13 @@ require (
|
||||
github.com/mailgun/minheap v0.0.0-20170619185613-3dbe6c6bf55f // indirect
|
||||
github.com/mailgun/multibuf v0.1.2 // indirect
|
||||
github.com/mailgun/timetools v0.0.0-20141028012446-7e6055773c51 // indirect
|
||||
github.com/mailru/easyjson v0.7.7 // indirect
|
||||
github.com/marten-seemann/qpack v0.2.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-16 v0.1.5 // indirect
|
||||
github.com/marten-seemann/qtls-go1-17 v0.1.1 // indirect
|
||||
github.com/marten-seemann/qtls-go1-18 v0.1.1 // indirect
|
||||
github.com/mattn/go-colorable v0.1.8 // indirect
|
||||
github.com/mattn/go-isatty v0.0.12 // indirect
|
||||
github.com/mattn/go-colorable v0.1.11 // indirect
|
||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
||||
github.com/mattn/go-shellwords v1.0.12 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369 // indirect
|
||||
github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b // indirect
|
||||
@@ -257,11 +263,11 @@ require (
|
||||
github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492 // indirect
|
||||
github.com/oracle/oci-go-sdk v24.3.0+incompatible // indirect
|
||||
github.com/ovh/go-ovh v1.1.0 // indirect
|
||||
github.com/philhofer/fwd v1.0.0 // indirect
|
||||
github.com/philhofer/fwd v1.1.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pquerna/otp v1.3.0 // indirect
|
||||
github.com/prometheus/common v0.26.0 // indirect
|
||||
github.com/prometheus/procfs v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.35.0 // indirect
|
||||
github.com/prometheus/procfs v0.7.3 // indirect
|
||||
github.com/sacloud/libsacloud v1.36.2 // indirect
|
||||
github.com/sanathkr/go-yaml v0.0.0-20170819195128-ed9d249f429b // indirect
|
||||
github.com/santhosh-tekuri/jsonschema v1.2.4 // indirect
|
||||
@@ -275,11 +281,11 @@ require (
|
||||
github.com/spf13/cast v1.3.1 // indirect
|
||||
github.com/spf13/cobra v1.2.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/stretchr/objx v0.3.0 // indirect
|
||||
github.com/stretchr/objx v0.4.0 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/common v1.0.287 // indirect
|
||||
github.com/tencentcloud/tencentcloud-sdk-go/tencentcloud/dnspod v1.0.287 // indirect
|
||||
github.com/theupdateframework/notary v0.6.1 // indirect
|
||||
github.com/tinylib/msgp v1.0.2 // indirect
|
||||
github.com/tinylib/msgp v1.1.2 // indirect
|
||||
github.com/tonistiigi/fsutil v0.0.0-20201103201449-0834f99b7b85 // indirect
|
||||
github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea // indirect
|
||||
github.com/transip/gotransip/v6 v6.6.1 // indirect
|
||||
@@ -301,16 +307,16 @@ require (
|
||||
go.uber.org/zap v1.18.1 // indirect
|
||||
golang.org/x/crypto v0.0.0-20220427172511-eb4f295cb31f // indirect
|
||||
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602 // indirect
|
||||
golang.org/x/oauth2 v0.0.0-20220223155221-ee480838109b // indirect
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c // indirect
|
||||
golang.org/x/sys v0.0.0-20220307203707-22a9840ba4d7 // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||
google.golang.org/api v0.44.0 // indirect
|
||||
google.golang.org/appengine v1.6.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c // indirect
|
||||
google.golang.org/protobuf v1.27.1 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
gopkg.in/inf.v0 v0.9.1 // indirect
|
||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
||||
gopkg.in/ns1/ns1-go.v2 v2.6.2 // indirect
|
||||
@@ -329,7 +335,7 @@ require (
|
||||
replace (
|
||||
github.com/abbot/go-http-auth => github.com/containous/go-http-auth v0.4.1-0.20200324110947-a37a7636d23e
|
||||
github.com/go-check/check => github.com/containous/check v0.0.0-20170915194414-ca0bf163426a
|
||||
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220113180107-8ffa4f6d063c
|
||||
github.com/gorilla/mux => github.com/containous/mux v0.0.0-20220627093034-b2dd784e613f
|
||||
github.com/mailgun/minheap => github.com/containous/minheap v0.0.0-20190809180810-6e71eb837595
|
||||
)
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
44
integration/fixtures/simple_muxer.toml
Normal file
44
integration/fixtures/simple_muxer.toml
Normal file
@@ -0,0 +1,44 @@
|
||||
[global]
|
||||
checkNewVersion = false
|
||||
sendAnonymousUsage = false
|
||||
|
||||
[log]
|
||||
level = "DEBUG"
|
||||
|
||||
[entryPoints]
|
||||
[entryPoints.webHost]
|
||||
address = ":8000"
|
||||
[entryPoints.webHostRegexp]
|
||||
address = ":8001"
|
||||
[entryPoints.webQuery]
|
||||
address = ":8002"
|
||||
|
||||
[api]
|
||||
insecure = true
|
||||
|
||||
[providers.file]
|
||||
filename = "{{ .SelfFilename }}"
|
||||
|
||||
## dynamic configuration ##
|
||||
|
||||
[http.routers]
|
||||
[http.routers.router1]
|
||||
entryPoints = ["webHost"]
|
||||
service = "service1"
|
||||
rule = "!Host(`test.localhost`)"
|
||||
|
||||
[http.routers.router2]
|
||||
entryPoints = ["webHostRegexp"]
|
||||
service = "service1"
|
||||
rule = "!HostRegexp(`test.localhost`)"
|
||||
|
||||
[http.routers.router3]
|
||||
entryPoints = ["webQuery"]
|
||||
service = "service1"
|
||||
rule = "!Query(`foo=`)"
|
||||
|
||||
|
||||
[http.services]
|
||||
[http.services.service1.loadBalancer]
|
||||
[[http.services.service1.loadBalancer.servers]]
|
||||
url = "{{ .Server1 }}"
|
@@ -1,6 +1,7 @@
|
||||
package integration
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"crypto/rand"
|
||||
"encoding/json"
|
||||
@@ -1178,3 +1179,124 @@ func (s *SimpleSuite) TestContentTypeDisableAutoDetect(c *check.C) {
|
||||
})
|
||||
c.Assert(err, checker.IsNil)
|
||||
}
|
||||
|
||||
func (s *SimpleSuite) TestMuxer(c *check.C) {
|
||||
s.createComposeProject(c, "base")
|
||||
|
||||
s.composeUp(c)
|
||||
defer s.composeDown(c)
|
||||
|
||||
whoami1URL := "http://" + net.JoinHostPort(s.getComposeServiceIP(c, "whoami1"), "80")
|
||||
|
||||
file := s.adaptFile(c, "fixtures/simple_muxer.toml", struct {
|
||||
Server1 string
|
||||
}{whoami1URL})
|
||||
defer os.Remove(file)
|
||||
|
||||
cmd, output := s.traefikCmd(withConfigFile(file))
|
||||
defer output(c)
|
||||
|
||||
err := cmd.Start()
|
||||
c.Assert(err, checker.IsNil)
|
||||
defer s.killCmd(cmd)
|
||||
|
||||
err = try.GetRequest("http://127.0.0.1:8080/api/rawdata", 1*time.Second, try.BodyContains("!Host"))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
request string
|
||||
target string
|
||||
body string
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
desc: "!Host with absolute-form URL with empty host and host header, no match",
|
||||
request: "GET http://@/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8000",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!Host with absolute-form URL with empty host and host header, match",
|
||||
request: "GET http://@/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8000",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "!Host with absolute-form URL and host header, no match",
|
||||
request: "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8000",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!Host with absolute-form URL and host header, match",
|
||||
request: "GET http://toto.localhost/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8000",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL with empty host and host header, no match",
|
||||
request: "GET http://@/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8001",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL with empty host and host header, match",
|
||||
request: "GET http://@/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8001",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL and host header, no match",
|
||||
request: "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8001",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL and host header, match",
|
||||
request: "GET http://toto.localhost/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8001",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "!Query with semicolon, no match",
|
||||
request: "GET /?foo=; HTTP/1.1\r\nHost: other.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8002",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!Query with semicolon, no match",
|
||||
request: "GET /?foo=titi;bar=toto HTTP/1.1\r\nHost: other.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8002",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!Query with semicolon, match",
|
||||
request: "GET /?bar=toto;boo=titi HTTP/1.1\r\nHost: other.localhost\r\n\r\n",
|
||||
target: "127.0.0.1:8002",
|
||||
expected: http.StatusOK,
|
||||
body: "bar=toto&boo=titi",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
conn, err := net.Dial("tcp", test.target)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
_, err = conn.Write([]byte(test.request))
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
resp, err := http.ReadResponse(bufio.NewReader(conn), nil)
|
||||
c.Assert(err, checker.IsNil)
|
||||
|
||||
if resp.StatusCode != test.expected {
|
||||
c.Errorf("%s failed with %d instead of %d", test.desc, resp.StatusCode, test.expected)
|
||||
}
|
||||
|
||||
if test.body != "" {
|
||||
body, err := io.ReadAll(resp.Body)
|
||||
c.Assert(err, checker.IsNil)
|
||||
c.Assert(string(body), checker.Contains, test.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -124,6 +124,7 @@ func (w *WRRService) SetDefaults() {
|
||||
|
||||
// Sticky holds the sticky configuration.
|
||||
type Sticky struct {
|
||||
// Cookie defines the sticky cookie configuration.
|
||||
Cookie *Cookie `json:"cookie,omitempty" toml:"cookie,omitempty" yaml:"cookie,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
}
|
||||
|
||||
@@ -131,9 +132,14 @@ type Sticky struct {
|
||||
|
||||
// Cookie holds the sticky configuration based on cookie.
|
||||
type Cookie struct {
|
||||
Name string `json:"name,omitempty" toml:"name,omitempty" yaml:"name,omitempty" export:"true"`
|
||||
Secure bool `json:"secure,omitempty" toml:"secure,omitempty" yaml:"secure,omitempty" export:"true"`
|
||||
HTTPOnly bool `json:"httpOnly,omitempty" toml:"httpOnly,omitempty" yaml:"httpOnly,omitempty" export:"true"`
|
||||
// Name defines the Cookie name.
|
||||
Name string `json:"name,omitempty" toml:"name,omitempty" yaml:"name,omitempty" export:"true"`
|
||||
// Secure defines whether the cookie can only be transmitted over an encrypted connection (i.e. HTTPS).
|
||||
Secure bool `json:"secure,omitempty" toml:"secure,omitempty" yaml:"secure,omitempty" export:"true"`
|
||||
// HTTPOnly defines whether the cookie can be accessed by client-side APIs, such as JavaScript.
|
||||
HTTPOnly bool `json:"httpOnly,omitempty" toml:"httpOnly,omitempty" yaml:"httpOnly,omitempty" export:"true"`
|
||||
// SameSite defines the same site policy.
|
||||
// More info: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Set-Cookie/SameSite
|
||||
SameSite string `json:"sameSite,omitempty" toml:"sameSite,omitempty" yaml:"sameSite,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
@@ -178,8 +184,13 @@ func (l *ServersLoadBalancer) SetDefaults() {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ResponseForwarding holds configuration for the forward of the response.
|
||||
// ResponseForwarding holds the response forwarding configuration.
|
||||
type ResponseForwarding struct {
|
||||
// FlushInterval defines the interval, in milliseconds, in between flushes to the client while copying the response body.
|
||||
// A negative value means to flush immediately after each write to the client.
|
||||
// This configuration is ignored when ReverseProxy recognizes a response as a streaming response;
|
||||
// for such responses, writes are flushed to the client immediately.
|
||||
// Default: 100ms
|
||||
FlushInterval string `json:"flushInterval,omitempty" toml:"flushInterval,omitempty" yaml:"flushInterval,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
|
@@ -40,60 +40,93 @@ type Middleware struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ContentType middleware - or rather its unique `autoDetect` option -
|
||||
// specifies whether to let the `Content-Type` header,
|
||||
// if it has not been set by the backend,
|
||||
// be automatically set to a value derived from the contents of the response.
|
||||
// As a proxy, the default behavior should be to leave the header alone,
|
||||
// regardless of what the backend did with it.
|
||||
// However, the historic default was to always auto-detect and set the header if it was nil,
|
||||
// and it is going to be kept that way in order to support users currently relying on it.
|
||||
// ContentType holds the content-type middleware configuration.
|
||||
// This middleware exists to enable the correct behavior until at least the default one can be changed in a future version.
|
||||
type ContentType struct {
|
||||
// AutoDetect specifies whether to let the `Content-Type` header, if it has not been set by the backend,
|
||||
// be automatically set to a value derived from the contents of the response.
|
||||
// As a proxy, the default behavior should be to leave the header alone, regardless of what the backend did with it.
|
||||
// However, the historic default was to always auto-detect and set the header if it was nil,
|
||||
// and it is going to be kept that way in order to support users currently relying on it.
|
||||
AutoDetect bool `json:"autoDetect,omitempty" toml:"autoDetect,omitempty" yaml:"autoDetect,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// AddPrefix holds the AddPrefix configuration.
|
||||
// AddPrefix holds the add prefix middleware configuration.
|
||||
// This middleware updates the path of a request before forwarding it.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/addprefix/
|
||||
type AddPrefix struct {
|
||||
// Prefix is the string to add before the current path in the requested URL.
|
||||
// It should include a leading slash (/).
|
||||
Prefix string `json:"prefix,omitempty" toml:"prefix,omitempty" yaml:"prefix,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// BasicAuth holds the HTTP basic authentication configuration.
|
||||
// BasicAuth holds the basic auth middleware configuration.
|
||||
// This middleware restricts access to your services to known users.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/
|
||||
type BasicAuth struct {
|
||||
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty" loggable:"false"`
|
||||
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
|
||||
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
|
||||
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"`
|
||||
HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"`
|
||||
// Users is an array of authorized users.
|
||||
// Each user must be declared using the name:hashed-password format.
|
||||
// Tip: Use htpasswd to generate the passwords.
|
||||
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty" loggable:"false"`
|
||||
// UsersFile is the path to an external file that contains the authorized users.
|
||||
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
|
||||
// Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme.
|
||||
// Default: traefik.
|
||||
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
|
||||
// RemoveHeader sets the removeHeader option to true to remove the authorization header before forwarding the request to your service.
|
||||
// Default: false.
|
||||
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"`
|
||||
// HeaderField defines a header field to store the authenticated user.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/#headerfield
|
||||
HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Buffering holds the request/response buffering configuration.
|
||||
// Buffering holds the buffering middleware configuration.
|
||||
// This middleware retries or limits the size of requests that can be forwarded to backends.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/buffering/#maxrequestbodybytes
|
||||
type Buffering struct {
|
||||
MaxRequestBodyBytes int64 `json:"maxRequestBodyBytes,omitempty" toml:"maxRequestBodyBytes,omitempty" yaml:"maxRequestBodyBytes,omitempty" export:"true"`
|
||||
MemRequestBodyBytes int64 `json:"memRequestBodyBytes,omitempty" toml:"memRequestBodyBytes,omitempty" yaml:"memRequestBodyBytes,omitempty" export:"true"`
|
||||
MaxResponseBodyBytes int64 `json:"maxResponseBodyBytes,omitempty" toml:"maxResponseBodyBytes,omitempty" yaml:"maxResponseBodyBytes,omitempty" export:"true"`
|
||||
MemResponseBodyBytes int64 `json:"memResponseBodyBytes,omitempty" toml:"memResponseBodyBytes,omitempty" yaml:"memResponseBodyBytes,omitempty" export:"true"`
|
||||
RetryExpression string `json:"retryExpression,omitempty" toml:"retryExpression,omitempty" yaml:"retryExpression,omitempty" export:"true"`
|
||||
// MaxRequestBodyBytes defines the maximum allowed body size for the request (in bytes).
|
||||
// If the request exceeds the allowed size, it is not forwarded to the service, and the client gets a 413 (Request Entity Too Large) response.
|
||||
// Default: 0 (no maximum).
|
||||
MaxRequestBodyBytes int64 `json:"maxRequestBodyBytes,omitempty" toml:"maxRequestBodyBytes,omitempty" yaml:"maxRequestBodyBytes,omitempty" export:"true"`
|
||||
// MemRequestBodyBytes defines the threshold (in bytes) from which the request will be buffered on disk instead of in memory.
|
||||
// Default: 1048576 (1Mi).
|
||||
MemRequestBodyBytes int64 `json:"memRequestBodyBytes,omitempty" toml:"memRequestBodyBytes,omitempty" yaml:"memRequestBodyBytes,omitempty" export:"true"`
|
||||
// MaxResponseBodyBytes defines the maximum allowed response size from the service (in bytes).
|
||||
// If the response exceeds the allowed size, it is not forwarded to the client. The client gets a 500 (Internal Server Error) response instead.
|
||||
// Default: 0 (no maximum).
|
||||
MaxResponseBodyBytes int64 `json:"maxResponseBodyBytes,omitempty" toml:"maxResponseBodyBytes,omitempty" yaml:"maxResponseBodyBytes,omitempty" export:"true"`
|
||||
// MemResponseBodyBytes defines the threshold (in bytes) from which the response will be buffered on disk instead of in memory.
|
||||
// Default: 1048576 (1Mi).
|
||||
MemResponseBodyBytes int64 `json:"memResponseBodyBytes,omitempty" toml:"memResponseBodyBytes,omitempty" yaml:"memResponseBodyBytes,omitempty" export:"true"`
|
||||
// RetryExpression defines the retry conditions.
|
||||
// It is a logical combination of functions with operators AND (&&) and OR (||).
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/buffering/#retryexpression
|
||||
RetryExpression string `json:"retryExpression,omitempty" toml:"retryExpression,omitempty" yaml:"retryExpression,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Chain holds a chain of middlewares.
|
||||
// Chain holds the chain middleware configuration.
|
||||
// This middleware enables to define reusable combinations of other pieces of middleware.
|
||||
type Chain struct {
|
||||
// Middlewares is the list of middleware names which composes the chain.
|
||||
Middlewares []string `json:"middlewares,omitempty" toml:"middlewares,omitempty" yaml:"middlewares,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// CircuitBreaker holds the circuit breaker configuration.
|
||||
// CircuitBreaker holds the circuit breaker middleware configuration.
|
||||
// This middleware protects the system from stacking requests to unhealthy services, resulting in cascading failures.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/circuitbreaker/
|
||||
type CircuitBreaker struct {
|
||||
// Expression is the condition that triggers the tripped state.
|
||||
// Expression defines the expression that, once matched, opens the circuit breaker and applies the fallback mechanism instead of calling the services.
|
||||
Expression string `json:"expression,omitempty" toml:"expression,omitempty" yaml:"expression,omitempty" export:"true"`
|
||||
// CheckPeriod is the interval between successive checks of the circuit breaker condition (when in standby state).
|
||||
CheckPeriod ptypes.Duration `json:"checkPeriod,omitempty" toml:"checkPeriod,omitempty" yaml:"checkPeriod,omitempty" export:"true"`
|
||||
@@ -112,95 +145,158 @@ func (c *CircuitBreaker) SetDefaults() {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Compress holds the compress configuration.
|
||||
// Compress holds the compress middleware configuration.
|
||||
// This middleware compresses responses before sending them to the client, using gzip compression.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/compress/
|
||||
type Compress struct {
|
||||
// ExcludedContentTypes defines the list of content types to compare the Content-Type header of the incoming requests and responses before compressing.
|
||||
ExcludedContentTypes []string `json:"excludedContentTypes,omitempty" toml:"excludedContentTypes,omitempty" yaml:"excludedContentTypes,omitempty" export:"true"`
|
||||
MinResponseBodyBytes int `json:"minResponseBodyBytes,omitempty" toml:"minResponseBodyBytes,omitempty" yaml:"minResponseBodyBytes,omitempty" export:"true"`
|
||||
// MinResponseBodyBytes defines the minimum amount of bytes a response body must have to be compressed.
|
||||
// Default: 1024.
|
||||
MinResponseBodyBytes int `json:"minResponseBodyBytes,omitempty" toml:"minResponseBodyBytes,omitempty" yaml:"minResponseBodyBytes,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// DigestAuth holds the Digest HTTP authentication configuration.
|
||||
// DigestAuth holds the digest auth middleware configuration.
|
||||
// This middleware restricts access to your services to known users.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/digestauth/
|
||||
type DigestAuth struct {
|
||||
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty" loggable:"false"`
|
||||
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
|
||||
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"`
|
||||
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
|
||||
HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"`
|
||||
// Users defines the authorized users.
|
||||
// Each user should be declared using the name:realm:encoded-password format.
|
||||
Users Users `json:"users,omitempty" toml:"users,omitempty" yaml:"users,omitempty" loggable:"false"`
|
||||
// UsersFile is the path to an external file that contains the authorized users for the middleware.
|
||||
UsersFile string `json:"usersFile,omitempty" toml:"usersFile,omitempty" yaml:"usersFile,omitempty"`
|
||||
// RemoveHeader defines whether to remove the authorization header before forwarding the request to the backend.
|
||||
RemoveHeader bool `json:"removeHeader,omitempty" toml:"removeHeader,omitempty" yaml:"removeHeader,omitempty" export:"true"`
|
||||
// Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme.
|
||||
// Default: traefik.
|
||||
Realm string `json:"realm,omitempty" toml:"realm,omitempty" yaml:"realm,omitempty"`
|
||||
// HeaderField defines a header field to store the authenticated user.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/#headerfield
|
||||
HeaderField string `json:"headerField,omitempty" toml:"headerField,omitempty" yaml:"headerField,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ErrorPage holds the custom error page configuration.
|
||||
// ErrorPage holds the custom error middleware configuration.
|
||||
// This middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes.
|
||||
type ErrorPage struct {
|
||||
Status []string `json:"status,omitempty" toml:"status,omitempty" yaml:"status,omitempty" export:"true"`
|
||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty" export:"true"`
|
||||
Query string `json:"query,omitempty" toml:"query,omitempty" yaml:"query,omitempty" export:"true"`
|
||||
// Status defines which status or range of statuses should result in an error page.
|
||||
// It can be either a status code as a number (500),
|
||||
// as multiple comma-separated numbers (500,502),
|
||||
// as ranges by separating two codes with a dash (500-599),
|
||||
// or a combination of the two (404,418,500-599).
|
||||
Status []string `json:"status,omitempty" toml:"status,omitempty" yaml:"status,omitempty" export:"true"`
|
||||
// Service defines the name of the service that will serve the error page.
|
||||
Service string `json:"service,omitempty" toml:"service,omitempty" yaml:"service,omitempty" export:"true"`
|
||||
// Query defines the URL for the error page (hosted by service).
|
||||
// The {status} variable can be used in order to insert the status code in the URL.
|
||||
Query string `json:"query,omitempty" toml:"query,omitempty" yaml:"query,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ForwardAuth holds the http forward authentication configuration.
|
||||
// ForwardAuth holds the forward auth middleware configuration.
|
||||
// This middleware delegates the request authentication to a Service.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/forwardauth/
|
||||
type ForwardAuth struct {
|
||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
||||
TLS *types.ClientTLS `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
|
||||
TrustForwardHeader bool `json:"trustForwardHeader,omitempty" toml:"trustForwardHeader,omitempty" yaml:"trustForwardHeader,omitempty" export:"true"`
|
||||
AuthResponseHeaders []string `json:"authResponseHeaders,omitempty" toml:"authResponseHeaders,omitempty" yaml:"authResponseHeaders,omitempty" export:"true"`
|
||||
AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty" toml:"authResponseHeadersRegex,omitempty" yaml:"authResponseHeadersRegex,omitempty" export:"true"`
|
||||
AuthRequestHeaders []string `json:"authRequestHeaders,omitempty" toml:"authRequestHeaders,omitempty" yaml:"authRequestHeaders,omitempty" export:"true"`
|
||||
// Address defines the authentication server address.
|
||||
Address string `json:"address,omitempty" toml:"address,omitempty" yaml:"address,omitempty"`
|
||||
// TLS defines the configuration used to secure the connection to the authentication server.
|
||||
TLS *types.ClientTLS `json:"tls,omitempty" toml:"tls,omitempty" yaml:"tls,omitempty" export:"true"`
|
||||
// TrustForwardHeader defines whether to trust (ie: forward) all X-Forwarded-* headers.
|
||||
TrustForwardHeader bool `json:"trustForwardHeader,omitempty" toml:"trustForwardHeader,omitempty" yaml:"trustForwardHeader,omitempty" export:"true"`
|
||||
// AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers.
|
||||
AuthResponseHeaders []string `json:"authResponseHeaders,omitempty" toml:"authResponseHeaders,omitempty" yaml:"authResponseHeaders,omitempty" export:"true"`
|
||||
// AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/forwardauth/#authresponseheadersregex
|
||||
AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty" toml:"authResponseHeadersRegex,omitempty" yaml:"authResponseHeadersRegex,omitempty" export:"true"`
|
||||
// AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server.
|
||||
// If not set or empty then all request headers are passed.
|
||||
AuthRequestHeaders []string `json:"authRequestHeaders,omitempty" toml:"authRequestHeaders,omitempty" yaml:"authRequestHeaders,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Headers holds the custom header configuration.
|
||||
// Headers holds the headers middleware configuration.
|
||||
// This middleware manages the requests and responses headers.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/headers/#customrequestheaders
|
||||
type Headers struct {
|
||||
CustomRequestHeaders map[string]string `json:"customRequestHeaders,omitempty" toml:"customRequestHeaders,omitempty" yaml:"customRequestHeaders,omitempty" export:"true"`
|
||||
// CustomRequestHeaders defines the header names and values to apply to the request.
|
||||
CustomRequestHeaders map[string]string `json:"customRequestHeaders,omitempty" toml:"customRequestHeaders,omitempty" yaml:"customRequestHeaders,omitempty" export:"true"`
|
||||
// CustomResponseHeaders defines the header names and values to apply to the response.
|
||||
CustomResponseHeaders map[string]string `json:"customResponseHeaders,omitempty" toml:"customResponseHeaders,omitempty" yaml:"customResponseHeaders,omitempty" export:"true"`
|
||||
|
||||
// AccessControlAllowCredentials is only valid if true. false is ignored.
|
||||
// AccessControlAllowCredentials defines whether the request can include user credentials.
|
||||
AccessControlAllowCredentials bool `json:"accessControlAllowCredentials,omitempty" toml:"accessControlAllowCredentials,omitempty" yaml:"accessControlAllowCredentials,omitempty" export:"true"`
|
||||
// AccessControlAllowHeaders must be used in response to a preflight request with Access-Control-Request-Headers set.
|
||||
// AccessControlAllowHeaders defines the Access-Control-Request-Headers values sent in preflight response.
|
||||
AccessControlAllowHeaders []string `json:"accessControlAllowHeaders,omitempty" toml:"accessControlAllowHeaders,omitempty" yaml:"accessControlAllowHeaders,omitempty" export:"true"`
|
||||
// AccessControlAllowMethods must be used in response to a preflight request with Access-Control-Request-Method set.
|
||||
// AccessControlAllowMethods defines the Access-Control-Request-Method values sent in preflight response.
|
||||
AccessControlAllowMethods []string `json:"accessControlAllowMethods,omitempty" toml:"accessControlAllowMethods,omitempty" yaml:"accessControlAllowMethods,omitempty" export:"true"`
|
||||
// AccessControlAllowOriginList is a list of allowable origins. Can also be a wildcard origin "*".
|
||||
AccessControlAllowOriginList []string `json:"accessControlAllowOriginList,omitempty" toml:"accessControlAllowOriginList,omitempty" yaml:"accessControlAllowOriginList,omitempty"`
|
||||
// AccessControlAllowOriginListRegex is a list of allowable origins written following the Regular Expression syntax (https://golang.org/pkg/regexp/).
|
||||
AccessControlAllowOriginListRegex []string `json:"accessControlAllowOriginListRegex,omitempty" toml:"accessControlAllowOriginListRegex,omitempty" yaml:"accessControlAllowOriginListRegex,omitempty"`
|
||||
// AccessControlExposeHeaders sets valid headers for the response.
|
||||
// AccessControlExposeHeaders defines the Access-Control-Expose-Headers values sent in preflight response.
|
||||
AccessControlExposeHeaders []string `json:"accessControlExposeHeaders,omitempty" toml:"accessControlExposeHeaders,omitempty" yaml:"accessControlExposeHeaders,omitempty" export:"true"`
|
||||
// AccessControlMaxAge sets the time that a preflight request may be cached.
|
||||
// AccessControlMaxAge defines the time that a preflight request may be cached.
|
||||
AccessControlMaxAge int64 `json:"accessControlMaxAge,omitempty" toml:"accessControlMaxAge,omitempty" yaml:"accessControlMaxAge,omitempty" export:"true"`
|
||||
// AddVaryHeader controls if the Vary header is automatically added/updated when the AccessControlAllowOriginList is set.
|
||||
// AddVaryHeader defines whether the Vary header is automatically added/updated when the AccessControlAllowOriginList is set.
|
||||
AddVaryHeader bool `json:"addVaryHeader,omitempty" toml:"addVaryHeader,omitempty" yaml:"addVaryHeader,omitempty" export:"true"`
|
||||
|
||||
AllowedHosts []string `json:"allowedHosts,omitempty" toml:"allowedHosts,omitempty" yaml:"allowedHosts,omitempty"`
|
||||
// AllowedHosts defines the fully qualified list of allowed domain names.
|
||||
AllowedHosts []string `json:"allowedHosts,omitempty" toml:"allowedHosts,omitempty" yaml:"allowedHosts,omitempty"`
|
||||
// HostsProxyHeaders defines the header keys that may hold a proxied hostname value for the request.
|
||||
HostsProxyHeaders []string `json:"hostsProxyHeaders,omitempty" toml:"hostsProxyHeaders,omitempty" yaml:"hostsProxyHeaders,omitempty" export:"true"`
|
||||
// Deprecated: use EntryPoint redirection or RedirectScheme instead.
|
||||
SSLRedirect bool `json:"sslRedirect,omitempty" toml:"sslRedirect,omitempty" yaml:"sslRedirect,omitempty" export:"true"`
|
||||
// Deprecated: use EntryPoint redirection or RedirectScheme instead.
|
||||
SSLTemporaryRedirect bool `json:"sslTemporaryRedirect,omitempty" toml:"sslTemporaryRedirect,omitempty" yaml:"sslTemporaryRedirect,omitempty" export:"true"`
|
||||
// Deprecated: use RedirectRegex instead.
|
||||
SSLHost string `json:"sslHost,omitempty" toml:"sslHost,omitempty" yaml:"sslHost,omitempty"`
|
||||
SSLHost string `json:"sslHost,omitempty" toml:"sslHost,omitempty" yaml:"sslHost,omitempty"`
|
||||
// SSLProxyHeaders defines the header keys with associated values that would indicate a valid HTTPS request.
|
||||
// It can be useful when using other proxies (example: "X-Forwarded-Proto": "https").
|
||||
SSLProxyHeaders map[string]string `json:"sslProxyHeaders,omitempty" toml:"sslProxyHeaders,omitempty" yaml:"sslProxyHeaders,omitempty"`
|
||||
// Deprecated: use RedirectRegex instead.
|
||||
SSLForceHost bool `json:"sslForceHost,omitempty" toml:"sslForceHost,omitempty" yaml:"sslForceHost,omitempty" export:"true"`
|
||||
STSSeconds int64 `json:"stsSeconds,omitempty" toml:"stsSeconds,omitempty" yaml:"stsSeconds,omitempty" export:"true"`
|
||||
STSIncludeSubdomains bool `json:"stsIncludeSubdomains,omitempty" toml:"stsIncludeSubdomains,omitempty" yaml:"stsIncludeSubdomains,omitempty" export:"true"`
|
||||
STSPreload bool `json:"stsPreload,omitempty" toml:"stsPreload,omitempty" yaml:"stsPreload,omitempty" export:"true"`
|
||||
ForceSTSHeader bool `json:"forceSTSHeader,omitempty" toml:"forceSTSHeader,omitempty" yaml:"forceSTSHeader,omitempty" export:"true"`
|
||||
FrameDeny bool `json:"frameDeny,omitempty" toml:"frameDeny,omitempty" yaml:"frameDeny,omitempty" export:"true"`
|
||||
SSLForceHost bool `json:"sslForceHost,omitempty" toml:"sslForceHost,omitempty" yaml:"sslForceHost,omitempty" export:"true"`
|
||||
// STSSeconds defines the max-age of the Strict-Transport-Security header.
|
||||
// If set to 0, the header is not set.
|
||||
STSSeconds int64 `json:"stsSeconds,omitempty" toml:"stsSeconds,omitempty" yaml:"stsSeconds,omitempty" export:"true"`
|
||||
// STSIncludeSubdomains defines whether the includeSubDomains directive is appended to the Strict-Transport-Security header.
|
||||
STSIncludeSubdomains bool `json:"stsIncludeSubdomains,omitempty" toml:"stsIncludeSubdomains,omitempty" yaml:"stsIncludeSubdomains,omitempty" export:"true"`
|
||||
// STSPreload defines whether the preload flag is appended to the Strict-Transport-Security header.
|
||||
STSPreload bool `json:"stsPreload,omitempty" toml:"stsPreload,omitempty" yaml:"stsPreload,omitempty" export:"true"`
|
||||
// ForceSTSHeader defines whether to add the STS header even when the connection is HTTP.
|
||||
ForceSTSHeader bool `json:"forceSTSHeader,omitempty" toml:"forceSTSHeader,omitempty" yaml:"forceSTSHeader,omitempty" export:"true"`
|
||||
// FrameDeny defines whether to add the X-Frame-Options header with the DENY value.
|
||||
FrameDeny bool `json:"frameDeny,omitempty" toml:"frameDeny,omitempty" yaml:"frameDeny,omitempty" export:"true"`
|
||||
// CustomFrameOptionsValue defines the X-Frame-Options header value.
|
||||
// This overrides the FrameDeny option.
|
||||
CustomFrameOptionsValue string `json:"customFrameOptionsValue,omitempty" toml:"customFrameOptionsValue,omitempty" yaml:"customFrameOptionsValue,omitempty"`
|
||||
ContentTypeNosniff bool `json:"contentTypeNosniff,omitempty" toml:"contentTypeNosniff,omitempty" yaml:"contentTypeNosniff,omitempty" export:"true"`
|
||||
BrowserXSSFilter bool `json:"browserXssFilter,omitempty" toml:"browserXssFilter,omitempty" yaml:"browserXssFilter,omitempty" export:"true"`
|
||||
CustomBrowserXSSValue string `json:"customBrowserXSSValue,omitempty" toml:"customBrowserXSSValue,omitempty" yaml:"customBrowserXSSValue,omitempty"`
|
||||
ContentSecurityPolicy string `json:"contentSecurityPolicy,omitempty" toml:"contentSecurityPolicy,omitempty" yaml:"contentSecurityPolicy,omitempty"`
|
||||
PublicKey string `json:"publicKey,omitempty" toml:"publicKey,omitempty" yaml:"publicKey,omitempty"`
|
||||
ReferrerPolicy string `json:"referrerPolicy,omitempty" toml:"referrerPolicy,omitempty" yaml:"referrerPolicy,omitempty" export:"true"`
|
||||
// ContentTypeNosniff defines whether to add the X-Content-Type-Options header with the nosniff value.
|
||||
ContentTypeNosniff bool `json:"contentTypeNosniff,omitempty" toml:"contentTypeNosniff,omitempty" yaml:"contentTypeNosniff,omitempty" export:"true"`
|
||||
// BrowserXSSFilter defines whether to add the X-XSS-Protection header with the value 1; mode=block.
|
||||
BrowserXSSFilter bool `json:"browserXssFilter,omitempty" toml:"browserXssFilter,omitempty" yaml:"browserXssFilter,omitempty" export:"true"`
|
||||
// CustomBrowserXSSValue defines the X-XSS-Protection header value.
|
||||
// This overrides the BrowserXssFilter option.
|
||||
CustomBrowserXSSValue string `json:"customBrowserXSSValue,omitempty" toml:"customBrowserXSSValue,omitempty" yaml:"customBrowserXSSValue,omitempty"`
|
||||
// ContentSecurityPolicy defines the Content-Security-Policy header value.
|
||||
ContentSecurityPolicy string `json:"contentSecurityPolicy,omitempty" toml:"contentSecurityPolicy,omitempty" yaml:"contentSecurityPolicy,omitempty"`
|
||||
// PublicKey is the public key that implements HPKP to prevent MITM attacks with forged certificates.
|
||||
PublicKey string `json:"publicKey,omitempty" toml:"publicKey,omitempty" yaml:"publicKey,omitempty"`
|
||||
// ReferrerPolicy defines the Referrer-Policy header value.
|
||||
// This allows sites to control whether browsers forward the Referer header to other sites.
|
||||
ReferrerPolicy string `json:"referrerPolicy,omitempty" toml:"referrerPolicy,omitempty" yaml:"referrerPolicy,omitempty" export:"true"`
|
||||
// Deprecated: use PermissionsPolicy instead.
|
||||
FeaturePolicy string `json:"featurePolicy,omitempty" toml:"featurePolicy,omitempty" yaml:"featurePolicy,omitempty" export:"true"`
|
||||
FeaturePolicy string `json:"featurePolicy,omitempty" toml:"featurePolicy,omitempty" yaml:"featurePolicy,omitempty" export:"true"`
|
||||
// PermissionsPolicy defines the Permissions-Policy header value.
|
||||
// This allows sites to control browser features.
|
||||
PermissionsPolicy string `json:"permissionsPolicy,omitempty" toml:"permissionsPolicy,omitempty" yaml:"permissionsPolicy,omitempty" export:"true"`
|
||||
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty" export:"true"`
|
||||
// IsDevelopment defines whether to mitigate the unwanted effects of the AllowedHosts, SSL, and STS options when developing.
|
||||
// Usually testing takes place using HTTP, not HTTPS, and on localhost, not your production domain.
|
||||
// If you would like your development environment to mimic production with complete Host blocking, SSL redirects,
|
||||
// and STS headers, leave this as false.
|
||||
IsDevelopment bool `json:"isDevelopment,omitempty" toml:"isDevelopment,omitempty" yaml:"isDevelopment,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// HasCustomHeadersDefined checks to see if any of the custom header elements have been set.
|
||||
@@ -249,9 +345,12 @@ func (h *Headers) HasSecureHeadersDefined() bool {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// IPStrategy holds the ip strategy configuration.
|
||||
// IPStrategy holds the IP strategy configuration used by Traefik to determine the client IP.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ipwhitelist/#ipstrategy
|
||||
type IPStrategy struct {
|
||||
Depth int `json:"depth,omitempty" toml:"depth,omitempty" yaml:"depth,omitempty" export:"true"`
|
||||
// Depth tells Traefik to use the X-Forwarded-For header and take the IP located at the depth position (starting from the right).
|
||||
Depth int `json:"depth,omitempty" toml:"depth,omitempty" yaml:"depth,omitempty" export:"true"`
|
||||
// ExcludedIPs configures Traefik to scan the X-Forwarded-For header and select the first IP not in the list.
|
||||
ExcludedIPs []string `json:"excludedIPs,omitempty" toml:"excludedIPs,omitempty" yaml:"excludedIPs,omitempty"`
|
||||
// TODO(mpl): I think we should make RemoteAddr an explicit field. For one thing, it would yield better documentation.
|
||||
}
|
||||
@@ -286,25 +385,40 @@ func (s *IPStrategy) Get() (ip.Strategy, error) {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// IPWhiteList holds the ip white list configuration.
|
||||
// IPWhiteList holds the IP whitelist middleware configuration.
|
||||
// This middleware accepts / refuses requests based on the client IP.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ipwhitelist/
|
||||
type IPWhiteList struct {
|
||||
// SourceRange defines the set of allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
||||
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" label:"allowEmpty" file:"allowEmpty" kv:"allowEmpty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// InFlightReq limits the number of requests being processed and served concurrently.
|
||||
// InFlightReq holds the in-flight request middleware configuration.
|
||||
// This middleware limits the number of requests being processed and served concurrently.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/inflightreq/
|
||||
type InFlightReq struct {
|
||||
Amount int64 `json:"amount,omitempty" toml:"amount,omitempty" yaml:"amount,omitempty" export:"true"`
|
||||
// Amount defines the maximum amount of allowed simultaneous in-flight request.
|
||||
// The middleware responds with HTTP 429 Too Many Requests if there are already amount requests in progress (based on the same sourceCriterion strategy).
|
||||
Amount int64 `json:"amount,omitempty" toml:"amount,omitempty" yaml:"amount,omitempty" export:"true"`
|
||||
// SourceCriterion defines what criterion is used to group requests as originating from a common source.
|
||||
// If several strategies are defined at the same time, an error will be raised.
|
||||
// If none are set, the default is to use the requestHost.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/inflightreq/#sourcecriterion
|
||||
SourceCriterion *SourceCriterion `json:"sourceCriterion,omitempty" toml:"sourceCriterion,omitempty" yaml:"sourceCriterion,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// PassTLSClientCert holds the TLS client cert headers configuration.
|
||||
// PassTLSClientCert holds the pass TLS client cert middleware configuration.
|
||||
// This middleware adds the selected data from the passed client TLS certificate to a header.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/passtlsclientcert/
|
||||
type PassTLSClientCert struct {
|
||||
PEM bool `json:"pem,omitempty" toml:"pem,omitempty" yaml:"pem,omitempty" export:"true"`
|
||||
// PEM sets the X-Forwarded-Tls-Client-Cert header with the escaped certificate.
|
||||
PEM bool `json:"pem,omitempty" toml:"pem,omitempty" yaml:"pem,omitempty" export:"true"`
|
||||
// Info selects the specific client certificate details you want to add to the X-Forwarded-Tls-Client-Cert-Info header.
|
||||
Info *TLSClientCertificateInfo `json:"info,omitempty" toml:"info,omitempty" yaml:"info,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
@@ -314,14 +428,17 @@ type PassTLSClientCert struct {
|
||||
// If none are set, the default is to use the request's remote address field.
|
||||
// All fields are mutually exclusive.
|
||||
type SourceCriterion struct {
|
||||
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" export:"true"`
|
||||
RequestHeaderName string `json:"requestHeaderName,omitempty" toml:"requestHeaderName,omitempty" yaml:"requestHeaderName,omitempty" export:"true"`
|
||||
RequestHost bool `json:"requestHost,omitempty" toml:"requestHost,omitempty" yaml:"requestHost,omitempty" export:"true"`
|
||||
IPStrategy *IPStrategy `json:"ipStrategy,omitempty" toml:"ipStrategy,omitempty" yaml:"ipStrategy,omitempty" export:"true"`
|
||||
// RequestHeaderName defines the name of the header used to group incoming requests.
|
||||
RequestHeaderName string `json:"requestHeaderName,omitempty" toml:"requestHeaderName,omitempty" yaml:"requestHeaderName,omitempty" export:"true"`
|
||||
// RequestHost defines whether to consider the request Host as the source.
|
||||
RequestHost bool `json:"requestHost,omitempty" toml:"requestHost,omitempty" yaml:"requestHost,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RateLimit holds the rate limiting configuration for a given router.
|
||||
// RateLimit holds the rate limit configuration.
|
||||
// This middleware ensures that services will receive a fair amount of requests, and allows one to define what fair is.
|
||||
type RateLimit struct {
|
||||
// Average is the maximum rate, by default in requests/s, allowed for the given source.
|
||||
// It defaults to 0, which means no rate limiting.
|
||||
@@ -337,6 +454,9 @@ type RateLimit struct {
|
||||
// It defaults to 1.
|
||||
Burst int64 `json:"burst,omitempty" toml:"burst,omitempty" yaml:"burst,omitempty" export:"true"`
|
||||
|
||||
// SourceCriterion defines what criterion is used to group requests as originating from a common source.
|
||||
// If several strategies are defined at the same time, an error will be raised.
|
||||
// If none are set, the default is to use the request's remote address field (as an ipStrategy).
|
||||
SourceCriterion *SourceCriterion `json:"sourceCriterion,omitempty" toml:"sourceCriterion,omitempty" yaml:"sourceCriterion,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
@@ -348,51 +468,82 @@ func (r *RateLimit) SetDefaults() {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RedirectRegex holds the redirection configuration.
|
||||
// RedirectRegex holds the redirect regex middleware configuration.
|
||||
// This middleware redirects a request using regex matching and replacement.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/redirectregex/#regex
|
||||
type RedirectRegex struct {
|
||||
Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty"`
|
||||
// Regex defines the regex used to match and capture elements from the request URL.
|
||||
Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty"`
|
||||
// Replacement defines how to modify the URL to have the new target URL.
|
||||
Replacement string `json:"replacement,omitempty" toml:"replacement,omitempty" yaml:"replacement,omitempty"`
|
||||
Permanent bool `json:"permanent,omitempty" toml:"permanent,omitempty" yaml:"permanent,omitempty" export:"true"`
|
||||
// Permanent defines whether the redirection is permanent (301).
|
||||
Permanent bool `json:"permanent,omitempty" toml:"permanent,omitempty" yaml:"permanent,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RedirectScheme holds the scheme redirection configuration.
|
||||
// RedirectScheme holds the redirect scheme middleware configuration.
|
||||
// This middleware redirects requests from a scheme/port to another.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/redirectscheme/
|
||||
type RedirectScheme struct {
|
||||
Scheme string `json:"scheme,omitempty" toml:"scheme,omitempty" yaml:"scheme,omitempty" export:"true"`
|
||||
Port string `json:"port,omitempty" toml:"port,omitempty" yaml:"port,omitempty" export:"true"`
|
||||
Permanent bool `json:"permanent,omitempty" toml:"permanent,omitempty" yaml:"permanent,omitempty" export:"true"`
|
||||
// Scheme defines the scheme of the new URL.
|
||||
Scheme string `json:"scheme,omitempty" toml:"scheme,omitempty" yaml:"scheme,omitempty" export:"true"`
|
||||
// Port defines the port of the new URL.
|
||||
Port string `json:"port,omitempty" toml:"port,omitempty" yaml:"port,omitempty" export:"true"`
|
||||
// Permanent defines whether the redirection is permanent (301).
|
||||
Permanent bool `json:"permanent,omitempty" toml:"permanent,omitempty" yaml:"permanent,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ReplacePath holds the ReplacePath configuration.
|
||||
// ReplacePath holds the replace path middleware configuration.
|
||||
// This middleware replaces the path of the request URL and store the original path in an X-Replaced-Path header.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/replacepath/
|
||||
type ReplacePath struct {
|
||||
// Path defines the path to use as replacement in the request URL.
|
||||
Path string `json:"path,omitempty" toml:"path,omitempty" yaml:"path,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ReplacePathRegex holds the ReplacePathRegex configuration.
|
||||
// ReplacePathRegex holds the replace path regex middleware configuration.
|
||||
// This middleware replaces the path of a URL using regex matching and replacement.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/replacepathregex/
|
||||
type ReplacePathRegex struct {
|
||||
Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty" export:"true"`
|
||||
// Regex defines the regular expression used to match and capture the path from the request URL.
|
||||
Regex string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty" export:"true"`
|
||||
// Replacement defines the replacement path format, which can include captured variables.
|
||||
Replacement string `json:"replacement,omitempty" toml:"replacement,omitempty" yaml:"replacement,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Retry holds the retry configuration.
|
||||
// Retry holds the retry middleware configuration.
|
||||
// This middleware reissues requests a given number of times to a backend server if that server does not reply.
|
||||
// As soon as the server answers, the middleware stops retrying, regardless of the response status.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/retry/
|
||||
type Retry struct {
|
||||
Attempts int `json:"attempts,omitempty" toml:"attempts,omitempty" yaml:"attempts,omitempty" export:"true"`
|
||||
// Attempts defines how many times the request should be retried.
|
||||
Attempts int `json:"attempts,omitempty" toml:"attempts,omitempty" yaml:"attempts,omitempty" export:"true"`
|
||||
// InitialInterval defines the first wait time in the exponential backoff series.
|
||||
// The maximum interval is calculated as twice the initialInterval.
|
||||
// If unspecified, requests will be retried immediately.
|
||||
// The value of initialInterval should be provided in seconds or as a valid duration format,
|
||||
// see https://pkg.go.dev/time#ParseDuration.
|
||||
InitialInterval ptypes.Duration `json:"initialInterval,omitempty" toml:"initialInterval,omitempty" yaml:"initialInterval,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// StripPrefix holds the StripPrefix configuration.
|
||||
// StripPrefix holds the strip prefix middleware configuration.
|
||||
// This middleware removes the specified prefixes from the URL path.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/stripprefix/
|
||||
type StripPrefix struct {
|
||||
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty" export:"true"`
|
||||
ForceSlash bool `json:"forceSlash,omitempty" toml:"forceSlash,omitempty" yaml:"forceSlash,omitempty" export:"true"` // Deprecated
|
||||
// Prefixes defines the prefixes to strip from the request URL.
|
||||
Prefixes []string `json:"prefixes,omitempty" toml:"prefixes,omitempty" yaml:"prefixes,omitempty" export:"true"`
|
||||
// ForceSlash ensures that the resulting stripped path is not the empty string, by replacing it with / when necessary.
|
||||
// Default: true.
|
||||
ForceSlash bool `json:"forceSlash,omitempty" toml:"forceSlash,omitempty" yaml:"forceSlash,omitempty" export:"true"` // Deprecated
|
||||
}
|
||||
|
||||
// SetDefaults Default values for a StripPrefix.
|
||||
@@ -402,8 +553,11 @@ func (s *StripPrefix) SetDefaults() {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// StripPrefixRegex holds the StripPrefixRegex configuration.
|
||||
// StripPrefixRegex holds the strip prefix regex middleware configuration.
|
||||
// This middleware removes the matching prefixes from the URL path.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/stripprefixregex/
|
||||
type StripPrefixRegex struct {
|
||||
// Regex defines the regular expression to match the path prefix from the request URL.
|
||||
Regex []string `json:"regex,omitempty" toml:"regex,omitempty" yaml:"regex,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
@@ -411,12 +565,18 @@ type StripPrefixRegex struct {
|
||||
|
||||
// TLSClientCertificateInfo holds the client TLS certificate info configuration.
|
||||
type TLSClientCertificateInfo struct {
|
||||
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty" export:"true"`
|
||||
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty" export:"true"`
|
||||
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty" export:"true"`
|
||||
Subject *TLSClientCertificateSubjectDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty" export:"true"`
|
||||
Issuer *TLSClientCertificateIssuerDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty" export:"true"`
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
|
||||
// NotAfter defines whether to add the Not After information from the Validity part.
|
||||
NotAfter bool `json:"notAfter,omitempty" toml:"notAfter,omitempty" yaml:"notAfter,omitempty" export:"true"`
|
||||
// NotBefore defines whether to add the Not Before information from the Validity part.
|
||||
NotBefore bool `json:"notBefore,omitempty" toml:"notBefore,omitempty" yaml:"notBefore,omitempty" export:"true"`
|
||||
// Sans defines whether to add the Subject Alternative Name information from the Subject Alternative Name part.
|
||||
Sans bool `json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty" export:"true"`
|
||||
// SerialNumber defines whether to add the client serialNumber information.
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
|
||||
// Subject defines the client certificate subject details to add to the X-Forwarded-Tls-Client-Cert-Info header.
|
||||
Subject *TLSClientCertificateSubjectDNInfo `json:"subject,omitempty" toml:"subject,omitempty" yaml:"subject,omitempty" export:"true"`
|
||||
// Issuer defines the client certificate issuer details to add to the X-Forwarded-Tls-Client-Cert-Info header.
|
||||
Issuer *TLSClientCertificateIssuerDNInfo `json:"issuer,omitempty" toml:"issuer,omitempty" yaml:"issuer,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
@@ -424,12 +584,19 @@ type TLSClientCertificateInfo struct {
|
||||
// TLSClientCertificateIssuerDNInfo holds the client TLS certificate distinguished name info configuration.
|
||||
// cf https://tools.ietf.org/html/rfc3739
|
||||
type TLSClientCertificateIssuerDNInfo struct {
|
||||
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty" export:"true"`
|
||||
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty" export:"true"`
|
||||
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty" export:"true"`
|
||||
Organization bool `json:"organization,omitempty" toml:"organization,omitempty" yaml:"organization,omitempty" export:"true"`
|
||||
CommonName bool `json:"commonName,omitempty" toml:"commonName,omitempty" yaml:"commonName,omitempty" export:"true"`
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
|
||||
// Country defines whether to add the country information into the issuer.
|
||||
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty" export:"true"`
|
||||
// Province defines whether to add the province information into the issuer.
|
||||
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty" export:"true"`
|
||||
// Locality defines whether to add the locality information into the issuer.
|
||||
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty" export:"true"`
|
||||
// Organization defines whether to add the organization information into the issuer.
|
||||
Organization bool `json:"organization,omitempty" toml:"organization,omitempty" yaml:"organization,omitempty" export:"true"`
|
||||
// CommonName defines whether to add the organizationalUnit information into the issuer.
|
||||
CommonName bool `json:"commonName,omitempty" toml:"commonName,omitempty" yaml:"commonName,omitempty" export:"true"`
|
||||
// SerialNumber defines whether to add the serialNumber information into the issuer.
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
|
||||
// DomainComponent defines whether to add the domainComponent information into the issuer.
|
||||
DomainComponent bool `json:"domainComponent,omitempty" toml:"domainComponent,omitempty" yaml:"domainComponent,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
@@ -438,14 +605,22 @@ type TLSClientCertificateIssuerDNInfo struct {
|
||||
// TLSClientCertificateSubjectDNInfo holds the client TLS certificate distinguished name info configuration.
|
||||
// cf https://tools.ietf.org/html/rfc3739
|
||||
type TLSClientCertificateSubjectDNInfo struct {
|
||||
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty" export:"true"`
|
||||
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty" export:"true"`
|
||||
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty" export:"true"`
|
||||
Organization bool `json:"organization,omitempty" toml:"organization,omitempty" yaml:"organization,omitempty" export:"true"`
|
||||
// Country defines whether to add the country information into the subject.
|
||||
Country bool `json:"country,omitempty" toml:"country,omitempty" yaml:"country,omitempty" export:"true"`
|
||||
// Province defines whether to add the province information into the subject.
|
||||
Province bool `json:"province,omitempty" toml:"province,omitempty" yaml:"province,omitempty" export:"true"`
|
||||
// Locality defines whether to add the locality information into the subject.
|
||||
Locality bool `json:"locality,omitempty" toml:"locality,omitempty" yaml:"locality,omitempty" export:"true"`
|
||||
// Organization defines whether to add the organization information into the subject.
|
||||
Organization bool `json:"organization,omitempty" toml:"organization,omitempty" yaml:"organization,omitempty" export:"true"`
|
||||
// OrganizationalUnit defines whether to add the organizationalUnit information into the subject.
|
||||
OrganizationalUnit bool `json:"organizationalUnit,omitempty" toml:"organizationalUnit,omitempty" yaml:"organizationalUnit,omitempty" export:"true"`
|
||||
CommonName bool `json:"commonName,omitempty" toml:"commonName,omitempty" yaml:"commonName,omitempty" export:"true"`
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
|
||||
DomainComponent bool `json:"domainComponent,omitempty" toml:"domainComponent,omitempty" yaml:"domainComponent,omitempty" export:"true"`
|
||||
// CommonName defines whether to add the organizationalUnit information into the subject.
|
||||
CommonName bool `json:"commonName,omitempty" toml:"commonName,omitempty" yaml:"commonName,omitempty" export:"true"`
|
||||
// SerialNumber defines whether to add the serialNumber information into the subject.
|
||||
SerialNumber bool `json:"serialNumber,omitempty" toml:"serialNumber,omitempty" yaml:"serialNumber,omitempty" export:"true"`
|
||||
// DomainComponent defines whether to add the domainComponent information into the subject.
|
||||
DomainComponent bool `json:"domainComponent,omitempty" toml:"domainComponent,omitempty" yaml:"domainComponent,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
@@ -113,8 +113,10 @@ type TCPServer struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ProxyProtocol holds the ProxyProtocol configuration.
|
||||
// ProxyProtocol holds the PROXY Protocol configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/services/#proxy-protocol
|
||||
type ProxyProtocol struct {
|
||||
// Version defines the PROXY Protocol version to use.
|
||||
Version int `json:"version,omitempty" toml:"version,omitempty" yaml:"version,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
|
@@ -10,14 +10,21 @@ type TCPMiddleware struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPInFlightConn holds the TCP in flight connection configuration.
|
||||
// TCPInFlightConn holds the TCP InFlightConn middleware configuration.
|
||||
// This middleware prevents services from being overwhelmed with high load,
|
||||
// by limiting the number of allowed simultaneous connections for one IP.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/tcp/inflightconn/
|
||||
type TCPInFlightConn struct {
|
||||
// Amount defines the maximum amount of allowed simultaneous connections.
|
||||
// The middleware closes the connection if there are already amount connections opened.
|
||||
Amount int64 `json:"amount,omitempty" toml:"amount,omitempty" yaml:"amount,omitempty" export:"true"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TCPIPWhiteList holds the TCP ip white list configuration.
|
||||
// TCPIPWhiteList holds the TCP IPWhiteList middleware configuration.
|
||||
// This middleware accepts/refuses connections based on the client IP.
|
||||
type TCPIPWhiteList struct {
|
||||
// SourceRange defines the allowed IPs (or ranges of allowed IPs by using CIDR notation).
|
||||
SourceRange []string `json:"sourceRange,omitempty" toml:"sourceRange,omitempty" yaml:"sourceRange,omitempty"`
|
||||
}
|
||||
|
@@ -375,17 +375,31 @@ func (lb *LbStatusUpdater) UpsertServer(u *url.URL, options ...roundrobin.Server
|
||||
// Balancers is a list of Balancers(s) that implements the Balancer interface.
|
||||
type Balancers []Balancer
|
||||
|
||||
// Servers returns the servers url from all the BalancerHandler.
|
||||
// Servers returns the deduplicated server URLs from all the Balancer.
|
||||
// Note that the deduplication is only possible because all the underlying
|
||||
// balancers are of the same kind (the oxy implementation).
|
||||
// The comparison property is the same as the one found at:
|
||||
// https://github.com/vulcand/oxy/blob/fb2728c857b7973a27f8de2f2190729c0f22cf49/roundrobin/rr.go#L347.
|
||||
func (b Balancers) Servers() []*url.URL {
|
||||
seen := make(map[string]struct{})
|
||||
|
||||
var servers []*url.URL
|
||||
for _, lb := range b {
|
||||
servers = append(servers, lb.Servers()...)
|
||||
for _, server := range lb.Servers() {
|
||||
key := serverKey(server)
|
||||
if _, ok := seen[key]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
servers = append(servers, server)
|
||||
seen[key] = struct{}{}
|
||||
}
|
||||
}
|
||||
|
||||
return servers
|
||||
}
|
||||
|
||||
// RemoveServer removes the given server from all the BalancerHandler,
|
||||
// RemoveServer removes the given server from all the Balancer,
|
||||
// and updates the status of the server to "DOWN".
|
||||
func (b Balancers) RemoveServer(u *url.URL) error {
|
||||
for _, lb := range b {
|
||||
@@ -396,7 +410,7 @@ func (b Balancers) RemoveServer(u *url.URL) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
// UpsertServer adds the given server to all the BalancerHandler,
|
||||
// UpsertServer adds the given server to all the Balancer,
|
||||
// and updates the status of the server to "UP".
|
||||
func (b Balancers) UpsertServer(u *url.URL, options ...roundrobin.ServerOption) error {
|
||||
for _, lb := range b {
|
||||
@@ -406,3 +420,7 @@ func (b Balancers) UpsertServer(u *url.URL, options ...roundrobin.ServerOption)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func serverKey(u *url.URL) string {
|
||||
return u.Path + u.Host + u.Scheme
|
||||
}
|
||||
|
@@ -362,6 +362,81 @@ func TestAddHeadersAndHost(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestBalancers_Servers(t *testing.T) {
|
||||
server1, err := url.Parse("http://foo.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
balancer1, err := roundrobin.New(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = balancer1.UpsertServer(server1)
|
||||
require.NoError(t, err)
|
||||
|
||||
server2, err := url.Parse("http://foo.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
balancer2, err := roundrobin.New(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = balancer2.UpsertServer(server2)
|
||||
require.NoError(t, err)
|
||||
|
||||
balancers := Balancers([]Balancer{balancer1, balancer2})
|
||||
|
||||
want, err := url.Parse("http://foo.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 1, len(balancers.Servers()))
|
||||
assert.Equal(t, want, balancers.Servers()[0])
|
||||
}
|
||||
|
||||
func TestBalancers_UpsertServer(t *testing.T) {
|
||||
balancer1, err := roundrobin.New(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
balancer2, err := roundrobin.New(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
want, err := url.Parse("http://foo.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
balancers := Balancers([]Balancer{balancer1, balancer2})
|
||||
|
||||
err = balancers.UpsertServer(want)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 1, len(balancer1.Servers()))
|
||||
assert.Equal(t, want, balancer1.Servers()[0])
|
||||
|
||||
assert.Equal(t, 1, len(balancer2.Servers()))
|
||||
assert.Equal(t, want, balancer2.Servers()[0])
|
||||
}
|
||||
|
||||
func TestBalancers_RemoveServer(t *testing.T) {
|
||||
server, err := url.Parse("http://foo.com")
|
||||
require.NoError(t, err)
|
||||
|
||||
balancer1, err := roundrobin.New(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = balancer1.UpsertServer(server)
|
||||
require.NoError(t, err)
|
||||
|
||||
balancer2, err := roundrobin.New(nil)
|
||||
require.NoError(t, err)
|
||||
|
||||
err = balancer2.UpsertServer(server)
|
||||
require.NoError(t, err)
|
||||
|
||||
balancers := Balancers([]Balancer{balancer1, balancer2})
|
||||
|
||||
err = balancers.RemoveServer(server)
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 0, len(balancer1.Servers()))
|
||||
assert.Equal(t, 0, len(balancer2.Servers()))
|
||||
}
|
||||
|
||||
type testLoadBalancer struct {
|
||||
// RWMutex needed due to parallel test execution: Both the system-under-test
|
||||
// and the test assertions reference the counters.
|
||||
|
@@ -12,8 +12,8 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
datadogClient *dogstatsd.Dogstatsd
|
||||
datadogTicker *time.Ticker
|
||||
datadogClient *dogstatsd.Dogstatsd
|
||||
datadogLoopCancelFunc context.CancelFunc
|
||||
)
|
||||
|
||||
// Metric names consistent with https://github.com/DataDog/integrations-extras/pull/64
|
||||
@@ -44,6 +44,9 @@ const (
|
||||
|
||||
// RegisterDatadog registers the metrics pusher if this didn't happen yet and creates a datadog Registry instance.
|
||||
func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry {
|
||||
// Ensures there is only one DataDog client sending metrics at any given time.
|
||||
StopDatadog()
|
||||
|
||||
// just to be sure there is a prefix defined
|
||||
if config.Prefix == "" {
|
||||
config.Prefix = defaultMetricsPrefix
|
||||
@@ -54,9 +57,7 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry {
|
||||
return nil
|
||||
}))
|
||||
|
||||
if datadogTicker == nil {
|
||||
datadogTicker = initDatadogClient(ctx, config)
|
||||
}
|
||||
initDatadogClient(ctx, config)
|
||||
|
||||
registry := &standardRegistry{
|
||||
configReloadsCounter: datadogClient.NewCounter(ddConfigReloadsName, 1.0),
|
||||
@@ -95,25 +96,26 @@ func RegisterDatadog(ctx context.Context, config *types.Datadog) Registry {
|
||||
return registry
|
||||
}
|
||||
|
||||
func initDatadogClient(ctx context.Context, config *types.Datadog) *time.Ticker {
|
||||
func initDatadogClient(ctx context.Context, config *types.Datadog) {
|
||||
address := config.Address
|
||||
if len(address) == 0 {
|
||||
address = "localhost:8125"
|
||||
}
|
||||
|
||||
report := time.NewTicker(time.Duration(config.PushInterval))
|
||||
ctx, datadogLoopCancelFunc = context.WithCancel(ctx)
|
||||
|
||||
safe.Go(func() {
|
||||
datadogClient.SendLoop(ctx, report.C, "udp", address)
|
||||
ticker := time.NewTicker(time.Duration(config.PushInterval))
|
||||
defer ticker.Stop()
|
||||
|
||||
datadogClient.SendLoop(ctx, ticker.C, "udp", address)
|
||||
})
|
||||
|
||||
return report
|
||||
}
|
||||
|
||||
// StopDatadog stops internal datadogTicker which controls the pushing of metrics to DD Agent and resets it to `nil`.
|
||||
// StopDatadog stops the Datadog metrics pusher.
|
||||
func StopDatadog() {
|
||||
if datadogTicker != nil {
|
||||
datadogTicker.Stop()
|
||||
if datadogLoopCancelFunc != nil {
|
||||
datadogLoopCancelFunc()
|
||||
datadogLoopCancelFunc = nil
|
||||
}
|
||||
datadogTicker = nil
|
||||
}
|
||||
|
@@ -4,8 +4,6 @@ import (
|
||||
"context"
|
||||
"errors"
|
||||
"net/http"
|
||||
"sort"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@@ -15,7 +13,6 @@ import (
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/traefik/traefik/v2/pkg/config/dynamic"
|
||||
"github.com/traefik/traefik/v2/pkg/log"
|
||||
"github.com/traefik/traefik/v2/pkg/safe"
|
||||
"github.com/traefik/traefik/v2/pkg/types"
|
||||
)
|
||||
|
||||
@@ -111,37 +108,33 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||
buckets = config.Buckets
|
||||
}
|
||||
|
||||
safe.Go(func() {
|
||||
promState.ListenValueUpdates()
|
||||
})
|
||||
|
||||
configReloads := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
configReloads := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: configReloadsTotalName,
|
||||
Help: "Config reloads",
|
||||
}, []string{})
|
||||
configReloadsFailures := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
configReloadsFailures := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: configReloadsFailuresTotalName,
|
||||
Help: "Config failure reloads",
|
||||
}, []string{})
|
||||
lastConfigReloadSuccess := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
lastConfigReloadSuccess := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: configLastReloadSuccessName,
|
||||
Help: "Last config reload success",
|
||||
}, []string{})
|
||||
lastConfigReloadFailure := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
lastConfigReloadFailure := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: configLastReloadFailureName,
|
||||
Help: "Last config reload failure",
|
||||
}, []string{})
|
||||
tlsCertsNotAfterTimestamp := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
tlsCertsNotAfterTimestamp := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: tlsCertsNotAfterTimestamp,
|
||||
Help: "Certificate expiration timestamp",
|
||||
}, []string{"cn", "serial", "sans"})
|
||||
|
||||
promState.describers = []func(chan<- *stdprometheus.Desc){
|
||||
configReloads.cv.Describe,
|
||||
configReloadsFailures.cv.Describe,
|
||||
lastConfigReloadSuccess.gv.Describe,
|
||||
lastConfigReloadFailure.gv.Describe,
|
||||
tlsCertsNotAfterTimestamp.gv.Describe,
|
||||
promState.vectors = []vector{
|
||||
configReloads.cv,
|
||||
configReloadsFailures.cv,
|
||||
lastConfigReloadSuccess.gv,
|
||||
lastConfigReloadFailure.gv,
|
||||
tlsCertsNotAfterTimestamp.gv,
|
||||
}
|
||||
|
||||
reg := &standardRegistry{
|
||||
@@ -156,30 +149,30 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||
}
|
||||
|
||||
if config.AddEntryPointsLabels {
|
||||
entryPointReqs := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
entryPointReqs := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: entryPointReqsTotalName,
|
||||
Help: "How many HTTP requests processed on an entrypoint, partitioned by status code, protocol, and method.",
|
||||
}, []string{"code", "method", "protocol", "entrypoint"})
|
||||
entryPointReqsTLS := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
entryPointReqsTLS := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: entryPointReqsTLSTotalName,
|
||||
Help: "How many HTTP requests with TLS processed on an entrypoint, partitioned by TLS Version and TLS cipher Used.",
|
||||
}, []string{"tls_version", "tls_cipher", "entrypoint"})
|
||||
entryPointReqDurations := newHistogramFrom(promState.collectors, stdprometheus.HistogramOpts{
|
||||
entryPointReqDurations := newHistogramFrom(stdprometheus.HistogramOpts{
|
||||
Name: entryPointReqDurationName,
|
||||
Help: "How long it took to process the request on an entrypoint, partitioned by status code, protocol, and method.",
|
||||
Buckets: buckets,
|
||||
}, []string{"code", "method", "protocol", "entrypoint"})
|
||||
entryPointOpenConns := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
entryPointOpenConns := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: entryPointOpenConnsName,
|
||||
Help: "How many open connections exist on an entrypoint, partitioned by method and protocol.",
|
||||
}, []string{"method", "protocol", "entrypoint"})
|
||||
|
||||
promState.describers = append(promState.describers, []func(chan<- *stdprometheus.Desc){
|
||||
entryPointReqs.cv.Describe,
|
||||
entryPointReqsTLS.cv.Describe,
|
||||
entryPointReqDurations.hv.Describe,
|
||||
entryPointOpenConns.gv.Describe,
|
||||
}...)
|
||||
promState.vectors = append(promState.vectors,
|
||||
entryPointReqs.cv,
|
||||
entryPointReqsTLS.cv,
|
||||
entryPointReqDurations.hv,
|
||||
entryPointOpenConns.gv,
|
||||
)
|
||||
|
||||
reg.entryPointReqsCounter = entryPointReqs
|
||||
reg.entryPointReqsTLSCounter = entryPointReqsTLS
|
||||
@@ -188,30 +181,30 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||
}
|
||||
|
||||
if config.AddRoutersLabels {
|
||||
routerReqs := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
routerReqs := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: routerReqsTotalName,
|
||||
Help: "How many HTTP requests are processed on a router, partitioned by service, status code, protocol, and method.",
|
||||
}, []string{"code", "method", "protocol", "router", "service"})
|
||||
routerReqsTLS := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
routerReqsTLS := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: routerReqsTLSTotalName,
|
||||
Help: "How many HTTP requests with TLS are processed on a router, partitioned by service, TLS Version, and TLS cipher Used.",
|
||||
}, []string{"tls_version", "tls_cipher", "router", "service"})
|
||||
routerReqDurations := newHistogramFrom(promState.collectors, stdprometheus.HistogramOpts{
|
||||
routerReqDurations := newHistogramFrom(stdprometheus.HistogramOpts{
|
||||
Name: routerReqDurationName,
|
||||
Help: "How long it took to process the request on a router, partitioned by service, status code, protocol, and method.",
|
||||
Buckets: buckets,
|
||||
}, []string{"code", "method", "protocol", "router", "service"})
|
||||
routerOpenConns := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
routerOpenConns := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: routerOpenConnsName,
|
||||
Help: "How many open connections exist on a router, partitioned by service, method, and protocol.",
|
||||
}, []string{"method", "protocol", "router", "service"})
|
||||
|
||||
promState.describers = append(promState.describers, []func(chan<- *stdprometheus.Desc){
|
||||
routerReqs.cv.Describe,
|
||||
routerReqsTLS.cv.Describe,
|
||||
routerReqDurations.hv.Describe,
|
||||
routerOpenConns.gv.Describe,
|
||||
}...)
|
||||
promState.vectors = append(promState.vectors,
|
||||
routerReqs.cv,
|
||||
routerReqsTLS.cv,
|
||||
routerReqDurations.hv,
|
||||
routerOpenConns.gv,
|
||||
)
|
||||
reg.routerReqsCounter = routerReqs
|
||||
reg.routerReqsTLSCounter = routerReqsTLS
|
||||
reg.routerReqDurationHistogram, _ = NewHistogramWithScale(routerReqDurations, time.Second)
|
||||
@@ -219,40 +212,40 @@ func initStandardRegistry(config *types.Prometheus) Registry {
|
||||
}
|
||||
|
||||
if config.AddServicesLabels {
|
||||
serviceReqs := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
serviceReqs := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: serviceReqsTotalName,
|
||||
Help: "How many HTTP requests processed on a service, partitioned by status code, protocol, and method.",
|
||||
}, []string{"code", "method", "protocol", "service"})
|
||||
serviceReqsTLS := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
serviceReqsTLS := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: serviceReqsTLSTotalName,
|
||||
Help: "How many HTTP requests with TLS processed on a service, partitioned by TLS version and TLS cipher.",
|
||||
}, []string{"tls_version", "tls_cipher", "service"})
|
||||
serviceReqDurations := newHistogramFrom(promState.collectors, stdprometheus.HistogramOpts{
|
||||
serviceReqDurations := newHistogramFrom(stdprometheus.HistogramOpts{
|
||||
Name: serviceReqDurationName,
|
||||
Help: "How long it took to process the request on a service, partitioned by status code, protocol, and method.",
|
||||
Buckets: buckets,
|
||||
}, []string{"code", "method", "protocol", "service"})
|
||||
serviceOpenConns := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
serviceOpenConns := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: serviceOpenConnsName,
|
||||
Help: "How many open connections exist on a service, partitioned by method and protocol.",
|
||||
}, []string{"method", "protocol", "service"})
|
||||
serviceRetries := newCounterFrom(promState.collectors, stdprometheus.CounterOpts{
|
||||
serviceRetries := newCounterFrom(stdprometheus.CounterOpts{
|
||||
Name: serviceRetriesTotalName,
|
||||
Help: "How many request retries happened on a service.",
|
||||
}, []string{"service"})
|
||||
serviceServerUp := newGaugeFrom(promState.collectors, stdprometheus.GaugeOpts{
|
||||
serviceServerUp := newGaugeFrom(stdprometheus.GaugeOpts{
|
||||
Name: serviceServerUpName,
|
||||
Help: "service server is up, described by gauge value of 0 or 1.",
|
||||
}, []string{"service", "url"})
|
||||
|
||||
promState.describers = append(promState.describers, []func(chan<- *stdprometheus.Desc){
|
||||
serviceReqs.cv.Describe,
|
||||
serviceReqsTLS.cv.Describe,
|
||||
serviceReqDurations.hv.Describe,
|
||||
serviceOpenConns.gv.Describe,
|
||||
serviceRetries.cv.Describe,
|
||||
serviceServerUp.gv.Describe,
|
||||
}...)
|
||||
promState.vectors = append(promState.vectors,
|
||||
serviceReqs.cv,
|
||||
serviceReqsTLS.cv,
|
||||
serviceReqDurations.hv,
|
||||
serviceOpenConns.gv,
|
||||
serviceRetries.cv,
|
||||
serviceServerUp.gv,
|
||||
)
|
||||
|
||||
reg.serviceReqsCounter = serviceReqs
|
||||
reg.serviceReqsTLSCounter = serviceReqsTLS
|
||||
@@ -287,64 +280,93 @@ func registerPromState(ctx context.Context) bool {
|
||||
// It then converts the configuration to the optimized package internal format
|
||||
// and sets it to the promState.
|
||||
func OnConfigurationUpdate(conf dynamic.Configuration, entryPoints []string) {
|
||||
dynamicConfig := newDynamicConfig()
|
||||
dynCfg := newDynamicConfig()
|
||||
|
||||
for _, value := range entryPoints {
|
||||
dynamicConfig.entryPoints[value] = true
|
||||
dynCfg.entryPoints[value] = true
|
||||
}
|
||||
|
||||
if conf.HTTP == nil {
|
||||
promState.SetDynamicConfig(dynCfg)
|
||||
return
|
||||
}
|
||||
|
||||
for name := range conf.HTTP.Routers {
|
||||
dynamicConfig.routers[name] = true
|
||||
dynCfg.routers[name] = true
|
||||
}
|
||||
|
||||
for serviceName, service := range conf.HTTP.Services {
|
||||
dynamicConfig.services[serviceName] = make(map[string]bool)
|
||||
dynCfg.services[serviceName] = make(map[string]bool)
|
||||
if service.LoadBalancer != nil {
|
||||
for _, server := range service.LoadBalancer.Servers {
|
||||
dynamicConfig.services[serviceName][server.URL] = true
|
||||
dynCfg.services[serviceName][server.URL] = true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
promState.SetDynamicConfig(dynamicConfig)
|
||||
promState.SetDynamicConfig(dynCfg)
|
||||
}
|
||||
|
||||
func newPrometheusState() *prometheusState {
|
||||
return &prometheusState{
|
||||
collectors: make(chan *collector),
|
||||
dynamicConfig: newDynamicConfig(),
|
||||
state: make(map[string]*collector),
|
||||
deletedURLs: make(map[string]string),
|
||||
}
|
||||
}
|
||||
|
||||
type prometheusState struct {
|
||||
collectors chan *collector
|
||||
describers []func(ch chan<- *stdprometheus.Desc)
|
||||
type vector interface {
|
||||
stdprometheus.Collector
|
||||
DeletePartialMatch(labels stdprometheus.Labels) int
|
||||
}
|
||||
|
||||
mtx sync.Mutex
|
||||
dynamicConfig *dynamicConfig
|
||||
state map[string]*collector
|
||||
type prometheusState struct {
|
||||
vectors []vector
|
||||
|
||||
mtx sync.Mutex
|
||||
dynamicConfig *dynamicConfig
|
||||
deletedEP []string
|
||||
deletedRouters []string
|
||||
deletedServices []string
|
||||
deletedURLs map[string]string
|
||||
}
|
||||
|
||||
func (ps *prometheusState) SetDynamicConfig(dynamicConfig *dynamicConfig) {
|
||||
ps.mtx.Lock()
|
||||
defer ps.mtx.Unlock()
|
||||
ps.dynamicConfig = dynamicConfig
|
||||
}
|
||||
|
||||
func (ps *prometheusState) ListenValueUpdates() {
|
||||
for collector := range ps.collectors {
|
||||
ps.mtx.Lock()
|
||||
ps.state[collector.id] = collector
|
||||
ps.mtx.Unlock()
|
||||
for ep := range ps.dynamicConfig.entryPoints {
|
||||
if _, ok := dynamicConfig.entryPoints[ep]; !ok {
|
||||
ps.deletedEP = append(ps.deletedEP, ep)
|
||||
}
|
||||
}
|
||||
|
||||
for router := range ps.dynamicConfig.routers {
|
||||
if _, ok := dynamicConfig.routers[router]; !ok {
|
||||
ps.deletedRouters = append(ps.deletedRouters, router)
|
||||
}
|
||||
}
|
||||
|
||||
for service, serV := range ps.dynamicConfig.services {
|
||||
actualService, ok := dynamicConfig.services[service]
|
||||
if !ok {
|
||||
ps.deletedServices = append(ps.deletedServices, service)
|
||||
continue
|
||||
}
|
||||
for url := range serV {
|
||||
if _, ok := actualService[url]; !ok {
|
||||
ps.deletedURLs[service] = url
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ps.dynamicConfig = dynamicConfig
|
||||
}
|
||||
|
||||
// Describe implements prometheus.Collector and simply calls
|
||||
// the registered describer functions.
|
||||
func (ps *prometheusState) Describe(ch chan<- *stdprometheus.Desc) {
|
||||
for _, desc := range ps.describers {
|
||||
desc(ch)
|
||||
for _, v := range ps.vectors {
|
||||
v.Describe(ch)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -354,49 +376,52 @@ func (ps *prometheusState) Describe(ch chan<- *stdprometheus.Desc) {
|
||||
// The removal happens only after their Collect method was called to ensure that
|
||||
// also those metrics will be exported on the current scrape.
|
||||
func (ps *prometheusState) Collect(ch chan<- stdprometheus.Metric) {
|
||||
for _, v := range ps.vectors {
|
||||
v.Collect(ch)
|
||||
}
|
||||
|
||||
ps.mtx.Lock()
|
||||
defer ps.mtx.Unlock()
|
||||
|
||||
var outdatedKeys []string
|
||||
for key, cs := range ps.state {
|
||||
cs.collector.Collect(ch)
|
||||
|
||||
if ps.isOutdated(cs) {
|
||||
outdatedKeys = append(outdatedKeys, key)
|
||||
for _, ep := range ps.deletedEP {
|
||||
if !ps.dynamicConfig.hasEntryPoint(ep) {
|
||||
ps.DeletePartialMatch(map[string]string{"entrypoint": ep})
|
||||
}
|
||||
}
|
||||
|
||||
for _, key := range outdatedKeys {
|
||||
ps.state[key].delete()
|
||||
delete(ps.state, key)
|
||||
for _, router := range ps.deletedRouters {
|
||||
if !ps.dynamicConfig.hasRouter(router) {
|
||||
ps.DeletePartialMatch(map[string]string{"router": router})
|
||||
}
|
||||
}
|
||||
|
||||
for _, service := range ps.deletedServices {
|
||||
if !ps.dynamicConfig.hasService(service) {
|
||||
ps.DeletePartialMatch(map[string]string{"service": service})
|
||||
}
|
||||
}
|
||||
|
||||
for service, url := range ps.deletedURLs {
|
||||
if !ps.dynamicConfig.hasServerURL(service, url) {
|
||||
ps.DeletePartialMatch(map[string]string{"service": service, "url": url})
|
||||
}
|
||||
}
|
||||
|
||||
ps.deletedEP = nil
|
||||
ps.deletedRouters = nil
|
||||
ps.deletedServices = nil
|
||||
ps.deletedURLs = make(map[string]string)
|
||||
}
|
||||
|
||||
// isOutdated checks whether the passed collector has labels that mark
|
||||
// it as belonging to an outdated configuration of Traefik.
|
||||
func (ps *prometheusState) isOutdated(collector *collector) bool {
|
||||
labels := collector.labels
|
||||
|
||||
if entrypointName, ok := labels["entrypoint"]; ok && !ps.dynamicConfig.hasEntryPoint(entrypointName) {
|
||||
return true
|
||||
// DeletePartialMatch deletes all metrics where the variable labels contain all of those passed in as labels.
|
||||
// The order of the labels does not matter.
|
||||
// It returns the number of metrics deleted.
|
||||
func (ps *prometheusState) DeletePartialMatch(labels stdprometheus.Labels) int {
|
||||
var count int
|
||||
for _, elem := range ps.vectors {
|
||||
count += elem.DeletePartialMatch(labels)
|
||||
}
|
||||
|
||||
if routerName, ok := labels["router"]; ok {
|
||||
if !ps.dynamicConfig.hasRouter(routerName) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
if serviceName, ok := labels["service"]; ok {
|
||||
if !ps.dynamicConfig.hasService(serviceName) {
|
||||
return true
|
||||
}
|
||||
if url, ok := labels["url"]; ok && !ps.dynamicConfig.hasServerURL(serviceName, url) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
return count
|
||||
}
|
||||
|
||||
func newDynamicConfig() *dynamicConfig {
|
||||
@@ -440,42 +465,15 @@ func (d *dynamicConfig) hasServerURL(serviceName, serverURL string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func newCollector(metricName string, labels stdprometheus.Labels, c stdprometheus.Collector, deleteFn func()) *collector {
|
||||
return &collector{
|
||||
id: buildMetricID(metricName, labels),
|
||||
labels: labels,
|
||||
collector: c,
|
||||
delete: deleteFn,
|
||||
}
|
||||
}
|
||||
|
||||
// collector wraps a Collector object from the Prometheus client library.
|
||||
// It adds information on how many generations this metric should be present
|
||||
// in the /metrics output, relative to the time it was last tracked.
|
||||
type collector struct {
|
||||
id string
|
||||
labels stdprometheus.Labels
|
||||
collector stdprometheus.Collector
|
||||
delete func()
|
||||
}
|
||||
|
||||
func buildMetricID(metricName string, labels stdprometheus.Labels) string {
|
||||
var labelNamesValues []string
|
||||
for name, value := range labels {
|
||||
labelNamesValues = append(labelNamesValues, name, value)
|
||||
}
|
||||
sort.Strings(labelNamesValues)
|
||||
return metricName + ":" + strings.Join(labelNamesValues, "|")
|
||||
}
|
||||
|
||||
func newCounterFrom(collectors chan<- *collector, opts stdprometheus.CounterOpts, labelNames []string) *counter {
|
||||
func newCounterFrom(opts stdprometheus.CounterOpts, labelNames []string) *counter {
|
||||
cv := stdprometheus.NewCounterVec(opts, labelNames)
|
||||
c := &counter{
|
||||
name: opts.Name,
|
||||
cv: cv,
|
||||
collectors: collectors,
|
||||
name: opts.Name,
|
||||
cv: cv,
|
||||
labelNamesValues: make([]string, 0, 16),
|
||||
}
|
||||
if len(labelNames) == 0 {
|
||||
c.collector = cv.WithLabelValues()
|
||||
c.Add(0)
|
||||
}
|
||||
return c
|
||||
@@ -485,39 +483,37 @@ type counter struct {
|
||||
name string
|
||||
cv *stdprometheus.CounterVec
|
||||
labelNamesValues labelNamesValues
|
||||
collectors chan<- *collector
|
||||
collector stdprometheus.Counter
|
||||
}
|
||||
|
||||
func (c *counter) With(labelValues ...string) metrics.Counter {
|
||||
lnv := c.labelNamesValues.With(labelValues...)
|
||||
return &counter{
|
||||
name: c.name,
|
||||
cv: c.cv,
|
||||
labelNamesValues: c.labelNamesValues.With(labelValues...),
|
||||
collectors: c.collectors,
|
||||
labelNamesValues: lnv,
|
||||
collector: c.cv.With(lnv.ToLabels()),
|
||||
}
|
||||
}
|
||||
|
||||
func (c *counter) Add(delta float64) {
|
||||
labels := c.labelNamesValues.ToLabels()
|
||||
collector := c.cv.With(labels)
|
||||
collector.Add(delta)
|
||||
c.collectors <- newCollector(c.name, labels, collector, func() {
|
||||
c.cv.Delete(labels)
|
||||
})
|
||||
c.collector.Add(delta)
|
||||
}
|
||||
|
||||
func (c *counter) Describe(ch chan<- *stdprometheus.Desc) {
|
||||
c.cv.Describe(ch)
|
||||
}
|
||||
|
||||
func newGaugeFrom(collectors chan<- *collector, opts stdprometheus.GaugeOpts, labelNames []string) *gauge {
|
||||
func newGaugeFrom(opts stdprometheus.GaugeOpts, labelNames []string) *gauge {
|
||||
gv := stdprometheus.NewGaugeVec(opts, labelNames)
|
||||
g := &gauge{
|
||||
name: opts.Name,
|
||||
gv: gv,
|
||||
collectors: collectors,
|
||||
name: opts.Name,
|
||||
gv: gv,
|
||||
labelNamesValues: make([]string, 0, 16),
|
||||
}
|
||||
|
||||
if len(labelNames) == 0 {
|
||||
g.collector = gv.WithLabelValues()
|
||||
g.Set(0)
|
||||
}
|
||||
return g
|
||||
@@ -527,46 +523,37 @@ type gauge struct {
|
||||
name string
|
||||
gv *stdprometheus.GaugeVec
|
||||
labelNamesValues labelNamesValues
|
||||
collectors chan<- *collector
|
||||
collector stdprometheus.Gauge
|
||||
}
|
||||
|
||||
func (g *gauge) With(labelValues ...string) metrics.Gauge {
|
||||
lnv := g.labelNamesValues.With(labelValues...)
|
||||
return &gauge{
|
||||
name: g.name,
|
||||
gv: g.gv,
|
||||
labelNamesValues: g.labelNamesValues.With(labelValues...),
|
||||
collectors: g.collectors,
|
||||
labelNamesValues: lnv,
|
||||
collector: g.gv.With(lnv.ToLabels()),
|
||||
}
|
||||
}
|
||||
|
||||
func (g *gauge) Add(delta float64) {
|
||||
labels := g.labelNamesValues.ToLabels()
|
||||
collector := g.gv.With(labels)
|
||||
collector.Add(delta)
|
||||
g.collectors <- newCollector(g.name, labels, collector, func() {
|
||||
g.gv.Delete(labels)
|
||||
})
|
||||
g.collector.Add(delta)
|
||||
}
|
||||
|
||||
func (g *gauge) Set(value float64) {
|
||||
labels := g.labelNamesValues.ToLabels()
|
||||
collector := g.gv.With(labels)
|
||||
collector.Set(value)
|
||||
g.collectors <- newCollector(g.name, labels, collector, func() {
|
||||
g.gv.Delete(labels)
|
||||
})
|
||||
g.collector.Set(value)
|
||||
}
|
||||
|
||||
func (g *gauge) Describe(ch chan<- *stdprometheus.Desc) {
|
||||
g.gv.Describe(ch)
|
||||
}
|
||||
|
||||
func newHistogramFrom(collectors chan<- *collector, opts stdprometheus.HistogramOpts, labelNames []string) *histogram {
|
||||
func newHistogramFrom(opts stdprometheus.HistogramOpts, labelNames []string) *histogram {
|
||||
hv := stdprometheus.NewHistogramVec(opts, labelNames)
|
||||
return &histogram{
|
||||
name: opts.Name,
|
||||
hv: hv,
|
||||
collectors: collectors,
|
||||
name: opts.Name,
|
||||
hv: hv,
|
||||
labelNamesValues: make([]string, 0, 16),
|
||||
}
|
||||
}
|
||||
|
||||
@@ -574,28 +561,21 @@ type histogram struct {
|
||||
name string
|
||||
hv *stdprometheus.HistogramVec
|
||||
labelNamesValues labelNamesValues
|
||||
collectors chan<- *collector
|
||||
collector stdprometheus.Observer
|
||||
}
|
||||
|
||||
func (h *histogram) With(labelValues ...string) metrics.Histogram {
|
||||
lnv := h.labelNamesValues.With(labelValues...)
|
||||
return &histogram{
|
||||
name: h.name,
|
||||
hv: h.hv,
|
||||
labelNamesValues: h.labelNamesValues.With(labelValues...),
|
||||
collectors: h.collectors,
|
||||
labelNamesValues: lnv,
|
||||
collector: h.hv.With(lnv.ToLabels()),
|
||||
}
|
||||
}
|
||||
|
||||
func (h *histogram) Observe(value float64) {
|
||||
labels := h.labelNamesValues.ToLabels()
|
||||
observer := h.hv.With(labels)
|
||||
observer.Observe(value)
|
||||
// Do a type assertion to be sure that prometheus will be able to call the Collect method.
|
||||
if collector, ok := observer.(stdprometheus.Histogram); ok {
|
||||
h.collectors <- newCollector(h.name, labels, collector, func() {
|
||||
h.hv.Delete(labels)
|
||||
})
|
||||
}
|
||||
h.collector.Observe(value)
|
||||
}
|
||||
|
||||
func (h *histogram) Describe(ch chan<- *stdprometheus.Desc) {
|
||||
@@ -618,7 +598,7 @@ func (lvs labelNamesValues) With(labelValues ...string) labelNamesValues {
|
||||
// ToLabels is a convenience method to convert a labelNamesValues
|
||||
// to the native prometheus.Labels.
|
||||
func (lvs labelNamesValues) ToLabels() stdprometheus.Labels {
|
||||
labels := stdprometheus.Labels{}
|
||||
labels := make(map[string]string, len(lvs)/2)
|
||||
for i := 0; i < len(lvs); i += 2 {
|
||||
labels[lvs[i]] = lvs[i+1]
|
||||
}
|
||||
|
@@ -17,8 +17,7 @@ import (
|
||||
)
|
||||
|
||||
func TestRegisterPromState(t *testing.T) {
|
||||
// Reset state of global promState.
|
||||
defer promState.reset()
|
||||
t.Cleanup(promState.reset)
|
||||
|
||||
testCases := []struct {
|
||||
desc string
|
||||
@@ -88,21 +87,10 @@ func TestRegisterPromState(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// reset is a utility method for unit testing. It should be called after each
|
||||
// test run that changes promState internally in order to avoid dependencies
|
||||
// between unit tests.
|
||||
func (ps *prometheusState) reset() {
|
||||
ps.collectors = make(chan *collector)
|
||||
ps.describers = []func(ch chan<- *prometheus.Desc){}
|
||||
ps.dynamicConfig = newDynamicConfig()
|
||||
ps.state = make(map[string]*collector)
|
||||
}
|
||||
|
||||
func TestPrometheus(t *testing.T) {
|
||||
promState = newPrometheusState()
|
||||
promRegistry = prometheus.NewRegistry()
|
||||
// Reset state of global promState.
|
||||
defer promState.reset()
|
||||
t.Cleanup(promState.reset)
|
||||
|
||||
prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddRoutersLabels: true, AddServicesLabels: true})
|
||||
defer promRegistry.Unregister(promState)
|
||||
@@ -361,30 +349,40 @@ func TestPrometheus(t *testing.T) {
|
||||
func TestPrometheusMetricRemoval(t *testing.T) {
|
||||
promState = newPrometheusState()
|
||||
promRegistry = prometheus.NewRegistry()
|
||||
// Reset state of global promState.
|
||||
defer promState.reset()
|
||||
t.Cleanup(promState.reset)
|
||||
|
||||
prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddServicesLabels: true, AddRoutersLabels: true})
|
||||
defer promRegistry.Unregister(promState)
|
||||
|
||||
conf := dynamic.Configuration{
|
||||
conf1 := dynamic.Configuration{
|
||||
HTTP: th.BuildConfiguration(
|
||||
th.WithRouters(
|
||||
th.WithRouter("foo@providerName",
|
||||
th.WithServiceName("bar")),
|
||||
th.WithRouter("foo@providerName", th.WithServiceName("bar")),
|
||||
th.WithRouter("router2", th.WithServiceName("bar@providerName")),
|
||||
),
|
||||
th.WithLoadBalancerServices(th.WithService("bar@providerName",
|
||||
th.WithServers(th.WithServer("http://localhost:9000"))),
|
||||
th.WithLoadBalancerServices(
|
||||
th.WithService("bar@providerName", th.WithServers(
|
||||
th.WithServer("http://localhost:9000"),
|
||||
th.WithServer("http://localhost:9999"),
|
||||
)),
|
||||
th.WithService("service1", th.WithServers(th.WithServer("http://localhost:9000"))),
|
||||
),
|
||||
func(cfg *dynamic.HTTPConfiguration) {
|
||||
cfg.Services["fii"] = &dynamic.Service{
|
||||
Weighted: &dynamic.WeightedRoundRobin{},
|
||||
}
|
||||
},
|
||||
),
|
||||
}
|
||||
|
||||
OnConfigurationUpdate(conf, []string{"entrypoint1"})
|
||||
conf2 := dynamic.Configuration{
|
||||
HTTP: th.BuildConfiguration(
|
||||
th.WithRouters(
|
||||
th.WithRouter("foo@providerName", th.WithServiceName("bar")),
|
||||
),
|
||||
th.WithLoadBalancerServices(
|
||||
th.WithService("bar@providerName", th.WithServers(th.WithServer("http://localhost:9000"))),
|
||||
),
|
||||
),
|
||||
}
|
||||
|
||||
OnConfigurationUpdate(conf1, []string{"entrypoint1", "entrypoint2"})
|
||||
OnConfigurationUpdate(conf2, []string{"entrypoint1"})
|
||||
|
||||
// Register some metrics manually that are not part of the active configuration.
|
||||
// Those metrics should be part of the /metrics output on the first scrape but
|
||||
@@ -393,22 +391,21 @@ func TestPrometheusMetricRemoval(t *testing.T) {
|
||||
EntryPointReqsCounter().
|
||||
With("entrypoint", "entrypoint2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
Add(1)
|
||||
prometheusRegistry.
|
||||
RouterReqsCounter().
|
||||
With("router", "router2", "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
Add(1)
|
||||
prometheusRegistry.
|
||||
ServiceReqsCounter().
|
||||
With("service", "service2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
With("service", "service1", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
Add(1)
|
||||
prometheusRegistry.
|
||||
ServiceServerUpGauge().
|
||||
With("service", "service1", "url", "http://localhost:9999").
|
||||
With("service", "bar@providerName", "url", "http://localhost:9999").
|
||||
Set(1)
|
||||
prometheusRegistry.
|
||||
RouterReqsCounter().
|
||||
With("router", "router2", "service", "service2", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
Add(1)
|
||||
|
||||
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName)
|
||||
assertMetricsAbsent(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName)
|
||||
assertMetricsAbsent(t, mustScrape(), routerReqsTotalName, routerReqDurationName, routerOpenConnsName)
|
||||
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, routerReqsTotalName, serviceReqsTotalName, serviceServerUpName)
|
||||
assertMetricsAbsent(t, mustScrape(), entryPointReqsTotalName, routerReqsTotalName, serviceReqsTotalName, serviceServerUpName)
|
||||
|
||||
// To verify that metrics belonging to active configurations are not removed
|
||||
// here the counter examples.
|
||||
@@ -418,24 +415,39 @@ func TestPrometheusMetricRemoval(t *testing.T) {
|
||||
Add(1)
|
||||
prometheusRegistry.
|
||||
RouterReqsCounter().
|
||||
With("router", "foo@providerName", "service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
With("router", "foo@providerName", "service", "bar", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
Add(1)
|
||||
prometheusRegistry.
|
||||
ServiceReqsCounter().
|
||||
With("service", "bar@providerName", "code", strconv.Itoa(http.StatusOK), "method", http.MethodGet, "protocol", "http").
|
||||
Add(1)
|
||||
prometheusRegistry.
|
||||
ServiceServerUpGauge().
|
||||
With("service", "bar@providerName", "url", "http://localhost:9000").
|
||||
Set(1)
|
||||
|
||||
delayForTrackingCompletion()
|
||||
|
||||
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName)
|
||||
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName)
|
||||
assertMetricsExist(t, mustScrape(), routerReqsTotalName)
|
||||
assertMetricsExist(t, mustScrape(), routerReqsTotalName)
|
||||
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName, routerReqsTotalName)
|
||||
assertMetricsExist(t, mustScrape(), entryPointReqsTotalName, serviceReqsTotalName, serviceServerUpName, routerReqsTotalName)
|
||||
}
|
||||
|
||||
func TestPrometheusRemovedMetricsReset(t *testing.T) {
|
||||
// Reset state of global promState.
|
||||
defer promState.reset()
|
||||
t.Cleanup(promState.reset)
|
||||
|
||||
prometheusRegistry := RegisterPrometheus(context.Background(), &types.Prometheus{AddEntryPointsLabels: true, AddServicesLabels: true})
|
||||
defer promRegistry.Unregister(promState)
|
||||
|
||||
conf1 := dynamic.Configuration{
|
||||
HTTP: th.BuildConfiguration(
|
||||
th.WithLoadBalancerServices(th.WithService("service",
|
||||
th.WithServers(th.WithServer("http://localhost:9000"))),
|
||||
),
|
||||
),
|
||||
}
|
||||
OnConfigurationUpdate(conf1, []string{"entrypoint1", "entrypoint2"})
|
||||
OnConfigurationUpdate(dynamic.Configuration{}, nil)
|
||||
|
||||
labelNamesValues := []string{
|
||||
"service", "service",
|
||||
"code", strconv.Itoa(http.StatusOK),
|
||||
@@ -467,12 +479,24 @@ func TestPrometheusRemovedMetricsReset(t *testing.T) {
|
||||
assertCounterValue(t, 1, findMetricFamily(serviceReqsTotalName, metricsFamilies), labelNamesValues...)
|
||||
}
|
||||
|
||||
// reset is a utility method for unit testing.
|
||||
// It should be called after each test run that changes promState internally
|
||||
// in order to avoid dependencies between unit tests.
|
||||
func (ps *prometheusState) reset() {
|
||||
ps.dynamicConfig = newDynamicConfig()
|
||||
ps.vectors = nil
|
||||
ps.deletedEP = nil
|
||||
ps.deletedRouters = nil
|
||||
ps.deletedServices = nil
|
||||
ps.deletedURLs = make(map[string]string)
|
||||
}
|
||||
|
||||
// Tracking and gathering the metrics happens concurrently.
|
||||
// In practice this is no problem, because in case a tracked metric would miss
|
||||
// the current scrape, it would just be there in the next one.
|
||||
// That we can test reliably the tracking of all metrics here, we sleep
|
||||
// for a short amount of time, to make sure the metric will be present
|
||||
// in the next scrape.
|
||||
// In practice this is no problem, because in case a tracked metric would miss the current scrape,
|
||||
// it would just be there in the next one.
|
||||
// That we can test reliably the tracking of all metrics here,
|
||||
// we sleep for a short amount of time,
|
||||
// to make sure the metric will be present in the next scrape.
|
||||
func delayForTrackingCompletion() {
|
||||
time.Sleep(250 * time.Millisecond)
|
||||
}
|
||||
|
@@ -142,6 +142,9 @@ func (x *XForwarded) rewrite(outreq *http.Request) {
|
||||
|
||||
xfProto := unsafeHeader(outreq.Header).Get(xForwardedProto)
|
||||
if xfProto == "" {
|
||||
// TODO: is this expected to set the X-Forwarded-Proto header value to
|
||||
// ws(s) as the underlying request used to upgrade the connection is
|
||||
// made over HTTP(S)?
|
||||
if isWebsocketRequest(outreq) {
|
||||
if outreq.TLS != nil {
|
||||
unsafeHeader(outreq.Header).Set(xForwardedProto, "wss")
|
||||
|
@@ -103,8 +103,9 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||
labels = append(labels, m.baseLabels...)
|
||||
labels = append(labels, "method", getMethod(req), "protocol", getRequestProtocol(req))
|
||||
|
||||
m.openConnsGauge.With(labels...).Add(1)
|
||||
defer m.openConnsGauge.With(labels...).Add(-1)
|
||||
openConnsGauge := m.openConnsGauge.With(labels...)
|
||||
openConnsGauge.Add(1)
|
||||
defer openConnsGauge.Add(-1)
|
||||
|
||||
// TLS metrics
|
||||
if req.TLS != nil {
|
||||
@@ -122,8 +123,7 @@ func (m *metricsMiddleware) ServeHTTP(rw http.ResponseWriter, req *http.Request)
|
||||
|
||||
labels = append(labels, "code", strconv.Itoa(recorder.getCode()))
|
||||
|
||||
histograms := m.reqDurationHistogram.With(labels...)
|
||||
histograms.ObserveFromStart(start)
|
||||
m.reqDurationHistogram.With(labels...).ObserveFromStart(start)
|
||||
|
||||
m.reqsCounter.With(labels...).Add(1)
|
||||
}
|
||||
|
@@ -13,8 +13,9 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
typeSchemeName = "RedirectScheme"
|
||||
uriPattern = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
|
||||
typeSchemeName = "RedirectScheme"
|
||||
uriPattern = `^(https?:\/\/)?(\[[\w:.]+\]|[\w\._-]+)?(:\d+)?(.*)$`
|
||||
xForwardedProto = "X-Forwarded-Proto"
|
||||
)
|
||||
|
||||
// NewRedirectScheme creates a new RedirectScheme middleware.
|
||||
@@ -32,10 +33,10 @@ func NewRedirectScheme(ctx context.Context, next http.Handler, conf dynamic.Redi
|
||||
port = ":" + conf.Port
|
||||
}
|
||||
|
||||
return newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, rawURLScheme, name)
|
||||
return newRedirect(next, uriPattern, conf.Scheme+"://${2}"+port+"${4}", conf.Permanent, clientRequestURL, name)
|
||||
}
|
||||
|
||||
func rawURLScheme(req *http.Request) string {
|
||||
func clientRequestURL(req *http.Request) string {
|
||||
scheme := schemeHTTP
|
||||
host, port, err := net.SplitHostPort(req.Host)
|
||||
if err != nil {
|
||||
@@ -63,7 +64,23 @@ func rawURLScheme(req *http.Request) string {
|
||||
scheme = schemeHTTPS
|
||||
}
|
||||
|
||||
if scheme == schemeHTTP && port == ":80" || scheme == schemeHTTPS && port == ":443" || port == "" {
|
||||
if xProto := req.Header.Get(xForwardedProto); xProto != "" {
|
||||
// When the initial request is a connection upgrade request,
|
||||
// X-Forwarded-Proto header might have been set by a previous hop to ws(s),
|
||||
// even though the actual protocol used so far is HTTP(s).
|
||||
// Given that we're in a middleware that is only used in the context of HTTP(s) requests,
|
||||
// the only possible valid schemes are one of "http" or "https", so we convert back to them.
|
||||
switch {
|
||||
case strings.EqualFold(xProto, "ws"):
|
||||
scheme = schemeHTTP
|
||||
case strings.EqualFold(xProto, "wss"):
|
||||
scheme = schemeHTTPS
|
||||
default:
|
||||
scheme = xProto
|
||||
}
|
||||
}
|
||||
|
||||
if scheme == schemeHTTP && port == ":80" || scheme == schemeHTTPS && port == ":443" {
|
||||
port = ""
|
||||
}
|
||||
|
||||
|
@@ -47,11 +47,57 @@ func TestRedirectSchemeHandler(t *testing.T) {
|
||||
},
|
||||
url: "http://foo",
|
||||
headers: map[string]string{
|
||||
"X-Forwarded-Proto": "https",
|
||||
"X-Forwarded-Proto": "http",
|
||||
},
|
||||
expectedURL: "https://foo",
|
||||
expectedStatus: http.StatusFound,
|
||||
},
|
||||
{
|
||||
desc: "HTTP to HTTPS, with X-Forwarded-Proto to HTTPS",
|
||||
config: dynamic.RedirectScheme{
|
||||
Scheme: "https",
|
||||
},
|
||||
url: "http://foo",
|
||||
headers: map[string]string{
|
||||
"X-Forwarded-Proto": "https",
|
||||
},
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "HTTP to HTTPS, with X-Forwarded-Proto to unknown value",
|
||||
config: dynamic.RedirectScheme{
|
||||
Scheme: "https",
|
||||
},
|
||||
url: "http://foo",
|
||||
headers: map[string]string{
|
||||
"X-Forwarded-Proto": "bar",
|
||||
},
|
||||
expectedURL: "https://bar://foo",
|
||||
expectedStatus: http.StatusFound,
|
||||
},
|
||||
{
|
||||
desc: "HTTP to HTTPS, with X-Forwarded-Proto to ws",
|
||||
config: dynamic.RedirectScheme{
|
||||
Scheme: "https",
|
||||
},
|
||||
url: "http://foo",
|
||||
headers: map[string]string{
|
||||
"X-Forwarded-Proto": "ws",
|
||||
},
|
||||
expectedURL: "https://foo",
|
||||
expectedStatus: http.StatusFound,
|
||||
},
|
||||
{
|
||||
desc: "HTTP to HTTPS, with X-Forwarded-Proto to wss",
|
||||
config: dynamic.RedirectScheme{
|
||||
Scheme: "https",
|
||||
},
|
||||
url: "http://foo",
|
||||
headers: map[string]string{
|
||||
"X-Forwarded-Proto": "wss",
|
||||
},
|
||||
expectedStatus: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "HTTP with port to HTTPS without port",
|
||||
config: dynamic.RedirectScheme{
|
||||
|
@@ -1,6 +1,8 @@
|
||||
package http
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"net/http"
|
||||
"net/http/httptest"
|
||||
"testing"
|
||||
@@ -956,3 +958,74 @@ func TestParseDomains(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestAbsoluteFormURL(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
request string
|
||||
rule string
|
||||
expected int
|
||||
}{
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL with empty host with non-matching host header",
|
||||
request: "GET http://@/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
|
||||
rule: "!HostRegexp(`test.localhost`)",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!Host with absolute-form URL with empty host with non-matching host header",
|
||||
request: "GET http://@/ HTTP/1.1\r\nHost: test.localhost\r\n\r\n",
|
||||
rule: "!Host(`test.localhost`)",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL with matching host header",
|
||||
request: "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
rule: "!HostRegexp(`test.localhost`)",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!Host with absolute-form URL with matching host header",
|
||||
request: "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
rule: "!Host(`test.localhost`)",
|
||||
expected: http.StatusNotFound,
|
||||
},
|
||||
{
|
||||
desc: "!HostRegexp with absolute-form URL with non-matching host header",
|
||||
request: "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
rule: "!HostRegexp(`toto.localhost`)",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
{
|
||||
desc: "!Host with absolute-form URL with non-matching host header",
|
||||
request: "GET http://test.localhost/ HTTP/1.1\r\nHost: toto.localhost\r\n\r\n",
|
||||
rule: "!Host(`toto.localhost`)",
|
||||
expected: http.StatusOK,
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {})
|
||||
muxer, err := NewMuxer()
|
||||
require.NoError(t, err)
|
||||
|
||||
err = muxer.AddRoute(test.rule, 0, handler)
|
||||
require.NoError(t, err)
|
||||
|
||||
// RequestDecorator is necessary for the host rule
|
||||
reqHost := requestdecorator.New(nil)
|
||||
|
||||
w := httptest.NewRecorder()
|
||||
|
||||
req, err := http.ReadRequest(bufio.NewReader(bytes.NewReader([]byte(test.request))))
|
||||
require.NoError(t, err)
|
||||
|
||||
reqHost.ServeHTTP(w, req, muxer.ServeHTTP)
|
||||
assert.Equal(t, test.expected, w.Code)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@@ -84,7 +84,7 @@ func (p *Provider) loadIngressRouteConfiguration(ctx context.Context, client Cli
|
||||
serviceName := normalized
|
||||
|
||||
if len(route.Services) > 1 {
|
||||
spec := v1alpha1.ServiceSpec{
|
||||
spec := v1alpha1.TraefikServiceSpec{
|
||||
Weighted: &v1alpha1.WeightedRoundRobin{
|
||||
Services: route.Services,
|
||||
},
|
||||
@@ -217,7 +217,7 @@ func (c configBuilder) buildTraefikService(ctx context.Context, tService *v1alph
|
||||
|
||||
// buildServicesLB creates the configuration for the load-balancer of services named id, and defined in tService.
|
||||
// It adds it to the given conf map.
|
||||
func (c configBuilder) buildServicesLB(ctx context.Context, namespace string, tService v1alpha1.ServiceSpec, id string, conf map[string]*dynamic.Service) error {
|
||||
func (c configBuilder) buildServicesLB(ctx context.Context, namespace string, tService v1alpha1.TraefikServiceSpec, id string, conf map[string]*dynamic.Service) error {
|
||||
var wrrServices []dynamic.WRRService
|
||||
|
||||
for _, service := range tService.Weighted.Services {
|
||||
|
@@ -7,90 +7,130 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// IngressRouteSpec is a specification for a IngressRouteSpec resource.
|
||||
// IngressRouteSpec defines the desired state of IngressRoute.
|
||||
type IngressRouteSpec struct {
|
||||
Routes []Route `json:"routes"`
|
||||
// Routes defines the list of routes.
|
||||
Routes []Route `json:"routes"`
|
||||
// EntryPoints defines the list of entry point names to bind to.
|
||||
// Entry points have to be configured in the static configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/entrypoints/
|
||||
// Default: all.
|
||||
EntryPoints []string `json:"entryPoints,omitempty"`
|
||||
TLS *TLS `json:"tls,omitempty"`
|
||||
// TLS defines the TLS configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#tls
|
||||
TLS *TLS `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// Route contains the set of routes.
|
||||
// Route holds the HTTP route configuration.
|
||||
type Route struct {
|
||||
// Match defines the router's rule.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#rule
|
||||
Match string `json:"match"`
|
||||
// Kind defines the kind of the route.
|
||||
// Rule is the only supported kind.
|
||||
// +kubebuilder:validation:Enum=Rule
|
||||
Kind string `json:"kind"`
|
||||
Priority int `json:"priority,omitempty"`
|
||||
Services []Service `json:"services,omitempty"`
|
||||
Kind string `json:"kind"`
|
||||
// Priority defines the router's priority.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#priority
|
||||
Priority int `json:"priority,omitempty"`
|
||||
// Services defines the list of Service.
|
||||
// It can contain any combination of TraefikService and/or reference to a Kubernetes Service.
|
||||
Services []Service `json:"services,omitempty"`
|
||||
// Middlewares defines the list of references to Middleware resources.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-middleware
|
||||
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
|
||||
}
|
||||
|
||||
// TLS contains the TLS certificates configuration of the routes.
|
||||
// To enable Let's Encrypt, use an empty TLS struct,
|
||||
// e.g. in YAML:
|
||||
//
|
||||
// tls: {} # inline format
|
||||
//
|
||||
// tls:
|
||||
// secretName: # block format
|
||||
// TLS holds the TLS configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#tls
|
||||
type TLS struct {
|
||||
// SecretName is the name of the referenced Kubernetes Secret to specify the
|
||||
// certificate details.
|
||||
// SecretName is the name of the referenced Kubernetes Secret to specify the certificate details.
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
// Options is a reference to a TLSOption, that specifies the parameters of the TLS connection.
|
||||
// Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection.
|
||||
// If not defined, the `default` TLSOption is used.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#tls-options
|
||||
Options *TLSOptionRef `json:"options,omitempty"`
|
||||
// Store is a reference to a TLSStore, that specifies the parameters of the TLS store.
|
||||
Store *TLSStoreRef `json:"store,omitempty"`
|
||||
CertResolver string `json:"certResolver,omitempty"`
|
||||
Domains []types.Domain `json:"domains,omitempty"`
|
||||
// Store defines the reference to the TLSStore, that will be used to store certificates.
|
||||
// Please note that only `default` TLSStore can be used.
|
||||
Store *TLSStoreRef `json:"store,omitempty"`
|
||||
// CertResolver defines the name of the certificate resolver to use.
|
||||
// Cert resolvers have to be configured in the static configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/acme/#certificate-resolvers
|
||||
CertResolver string `json:"certResolver,omitempty"`
|
||||
// Domains defines the list of domains that will be used to issue certificates.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#domains
|
||||
Domains []types.Domain `json:"domains,omitempty"`
|
||||
}
|
||||
|
||||
// TLSOptionRef is a ref to the TLSOption resources.
|
||||
// TLSOptionRef is a reference to a TLSOption resource.
|
||||
type TLSOptionRef struct {
|
||||
Name string `json:"name"`
|
||||
// Name defines the name of the referenced TLSOption.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsoption
|
||||
Name string `json:"name"`
|
||||
// Namespace defines the namespace of the referenced TLSOption.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsoption
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
// TLSStoreRef is a ref to the TLSStore resource.
|
||||
// TLSStoreRef is a reference to a TLSStore resource.
|
||||
type TLSStoreRef struct {
|
||||
Name string `json:"name"`
|
||||
// Name defines the name of the referenced TLSStore.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsstore
|
||||
Name string `json:"name"`
|
||||
// Namespace defines the namespace of the referenced TLSStore.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-tlsstore
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
// LoadBalancerSpec can reference either a Kubernetes Service object (a load-balancer of servers),
|
||||
// or a TraefikService object (a traefik load-balancer of services).
|
||||
// LoadBalancerSpec defines the desired state of LoadBalancer.
|
||||
// It can reference either a Kubernetes Service object (a load-balancer of servers),
|
||||
// or a TraefikService object (a load-balancer of Traefik services).
|
||||
type LoadBalancerSpec struct {
|
||||
// Name is a reference to a Kubernetes Service object (for a load-balancer of servers),
|
||||
// or to a TraefikService object (service load-balancer, mirroring, etc).
|
||||
// Name defines the name of the referenced Kubernetes Service or TraefikService.
|
||||
// The differentiation between the two is specified in the Kind field.
|
||||
Name string `json:"name"`
|
||||
// Kind defines the kind of the Service.
|
||||
// +kubebuilder:validation:Enum=Service;TraefikService
|
||||
Kind string `json:"kind,omitempty"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Sticky *dynamic.Sticky `json:"sticky,omitempty"`
|
||||
|
||||
// Port and all the fields below are related to a servers load-balancer,
|
||||
// and therefore should only be specified when Name references a Kubernetes Service.
|
||||
|
||||
Port intstr.IntOrString `json:"port,omitempty"`
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
Strategy string `json:"strategy,omitempty"`
|
||||
PassHostHeader *bool `json:"passHostHeader,omitempty"`
|
||||
Kind string `json:"kind,omitempty"`
|
||||
// Namespace defines the namespace of the referenced Kubernetes Service or TraefikService.
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// Sticky defines the sticky sessions configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/services/#sticky-sessions
|
||||
Sticky *dynamic.Sticky `json:"sticky,omitempty"`
|
||||
// Port defines the port of a Kubernetes Service.
|
||||
// This can be a reference to a named port.
|
||||
Port intstr.IntOrString `json:"port,omitempty"`
|
||||
// Scheme defines the scheme to use for the request to the upstream Kubernetes Service.
|
||||
// It defaults to https when Kubernetes Service port is 443, http otherwise.
|
||||
Scheme string `json:"scheme,omitempty"`
|
||||
// Strategy defines the load balancing strategy between the servers.
|
||||
// RoundRobin is the only supported value at the moment.
|
||||
Strategy string `json:"strategy,omitempty"`
|
||||
// PassHostHeader defines whether the client Host header is forwarded to the upstream Kubernetes Service.
|
||||
// By default, passHostHeader is true.
|
||||
PassHostHeader *bool `json:"passHostHeader,omitempty"`
|
||||
// ResponseForwarding defines how Traefik forwards the response from the upstream Kubernetes Service to the client.
|
||||
ResponseForwarding *dynamic.ResponseForwarding `json:"responseForwarding,omitempty"`
|
||||
ServersTransport string `json:"serversTransport,omitempty"`
|
||||
// ServersTransport defines the name of ServersTransport resource to use.
|
||||
// It allows to configure the transport between Traefik and your servers.
|
||||
// Can only be used on a Kubernetes Service.
|
||||
ServersTransport string `json:"serversTransport,omitempty"`
|
||||
|
||||
// Weight should only be specified when Name references a TraefikService object
|
||||
// Weight defines the weight and should only be specified when Name references a TraefikService object
|
||||
// (and to be precise, one that embeds a Weighted Round Robin).
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
}
|
||||
|
||||
// Service defines an upstream to proxy traffic.
|
||||
// Service defines an upstream HTTP service to proxy traffic to.
|
||||
type Service struct {
|
||||
LoadBalancerSpec `json:",inline"`
|
||||
}
|
||||
|
||||
// MiddlewareRef is a ref to the Middleware resources.
|
||||
// MiddlewareRef is a reference to a Middleware resource.
|
||||
type MiddlewareRef struct {
|
||||
Name string `json:"name"`
|
||||
// Name defines the name of the referenced Middleware resource.
|
||||
Name string `json:"name"`
|
||||
// Namespace defines the namespace of the referenced Middleware resource.
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
@@ -98,9 +138,11 @@ type MiddlewareRef struct {
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// IngressRoute is an Ingress CRD specification.
|
||||
// IngressRoute is the CRD implementation of a Traefik HTTP Router.
|
||||
type IngressRoute struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec IngressRouteSpec `json:"spec"`
|
||||
@@ -108,9 +150,13 @@ type IngressRoute struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// IngressRouteList is a list of IngressRoutes.
|
||||
// IngressRouteList is a collection of IngressRoute.
|
||||
type IngressRouteList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
Items []IngressRoute `json:"items"`
|
||||
|
||||
// Items is the list of IngressRoute.
|
||||
Items []IngressRoute `json:"items"`
|
||||
}
|
||||
|
@@ -7,60 +7,88 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// IngressRouteTCPSpec is a specification for a IngressRouteTCPSpec resource.
|
||||
// IngressRouteTCPSpec defines the desired state of IngressRouteTCP.
|
||||
type IngressRouteTCPSpec struct {
|
||||
Routes []RouteTCP `json:"routes"`
|
||||
EntryPoints []string `json:"entryPoints,omitempty"`
|
||||
TLS *TLSTCP `json:"tls,omitempty"`
|
||||
// Routes defines the list of routes.
|
||||
Routes []RouteTCP `json:"routes"`
|
||||
// EntryPoints defines the list of entry point names to bind to.
|
||||
// Entry points have to be configured in the static configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/entrypoints/
|
||||
// Default: all.
|
||||
EntryPoints []string `json:"entryPoints,omitempty"`
|
||||
// TLS defines the TLS configuration on a layer 4 / TCP Route.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#tls_1
|
||||
TLS *TLSTCP `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// RouteTCP contains the set of routes.
|
||||
// RouteTCP holds the TCP route configuration.
|
||||
type RouteTCP struct {
|
||||
Match string `json:"match"`
|
||||
Priority int `json:"priority,omitempty"`
|
||||
// Match defines the router's rule.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#rule_1
|
||||
Match string `json:"match"`
|
||||
// Priority defines the router's priority.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#priority_1
|
||||
Priority int `json:"priority,omitempty"`
|
||||
// Services defines the list of TCP services.
|
||||
Services []ServiceTCP `json:"services,omitempty"`
|
||||
// Middlewares contains references to MiddlewareTCP resources.
|
||||
// Middlewares defines the list of references to MiddlewareTCP resources.
|
||||
Middlewares []ObjectReference `json:"middlewares,omitempty"`
|
||||
}
|
||||
|
||||
// TLSTCP contains the TLS certificates configuration of the routes.
|
||||
// To enable Let's Encrypt, use an empty TLS struct,
|
||||
// e.g. in YAML:
|
||||
//
|
||||
// tls: {} # inline format
|
||||
//
|
||||
// tls:
|
||||
// secretName: # block format
|
||||
// TLSTCP holds the TLS configuration for an IngressRouteTCP.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#tls_1
|
||||
type TLSTCP struct {
|
||||
// SecretName is the name of the referenced Kubernetes Secret to specify the
|
||||
// certificate details.
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
Passthrough bool `json:"passthrough,omitempty"`
|
||||
// Options is a reference to a TLSOption, that specifies the parameters of the TLS connection.
|
||||
// SecretName is the name of the referenced Kubernetes Secret to specify the certificate details.
|
||||
SecretName string `json:"secretName,omitempty"`
|
||||
// Passthrough defines whether a TLS router will terminate the TLS connection.
|
||||
Passthrough bool `json:"passthrough,omitempty"`
|
||||
// Options defines the reference to a TLSOption, that specifies the parameters of the TLS connection.
|
||||
// If not defined, the `default` TLSOption is used.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#tls-options
|
||||
Options *ObjectReference `json:"options,omitempty"`
|
||||
// Store is a reference to a TLSStore, that specifies the parameters of the TLS store.
|
||||
Store *ObjectReference `json:"store,omitempty"`
|
||||
CertResolver string `json:"certResolver,omitempty"`
|
||||
Domains []types.Domain `json:"domains,omitempty"`
|
||||
// Store defines the reference to the TLSStore, that will be used to store certificates.
|
||||
// Please note that only `default` TLSStore can be used.
|
||||
Store *ObjectReference `json:"store,omitempty"`
|
||||
// CertResolver defines the name of the certificate resolver to use.
|
||||
// Cert resolvers have to be configured in the static configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/acme/#certificate-resolvers
|
||||
CertResolver string `json:"certResolver,omitempty"`
|
||||
// Domains defines the list of domains that will be used to issue certificates.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/routers/#domains
|
||||
Domains []types.Domain `json:"domains,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceTCP defines an upstream to proxy traffic.
|
||||
// ServiceTCP defines an upstream TCP service to proxy traffic to.
|
||||
type ServiceTCP struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Port intstr.IntOrString `json:"port"`
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
TerminationDelay *int `json:"terminationDelay,omitempty"`
|
||||
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
||||
// Name defines the name of the referenced Kubernetes Service.
|
||||
Name string `json:"name"`
|
||||
// Namespace defines the namespace of the referenced Kubernetes Service.
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// Port defines the port of a Kubernetes Service.
|
||||
// This can be a reference to a named port.
|
||||
Port intstr.IntOrString `json:"port"`
|
||||
// Weight defines the weight used when balancing requests between multiple Kubernetes Service.
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
// TerminationDelay defines the deadline that the proxy sets, after one of its connected peers indicates
|
||||
// it has closed the writing capability of its connection, to close the reading capability as well,
|
||||
// hence fully terminating the connection.
|
||||
// It is a duration in milliseconds, defaulting to 100.
|
||||
// A negative value means an infinite deadline (i.e. the reading capability is never closed).
|
||||
TerminationDelay *int `json:"terminationDelay,omitempty"`
|
||||
// ProxyProtocol defines the PROXY protocol configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/services/#proxy-protocol
|
||||
ProxyProtocol *dynamic.ProxyProtocol `json:"proxyProtocol,omitempty"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// IngressRouteTCP is an Ingress CRD specification.
|
||||
// IngressRouteTCP is the CRD implementation of a Traefik TCP Router.
|
||||
type IngressRouteTCP struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec IngressRouteTCPSpec `json:"spec"`
|
||||
@@ -68,9 +96,13 @@ type IngressRouteTCP struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// IngressRouteTCPList is a list of IngressRoutes.
|
||||
// IngressRouteTCPList is a collection of IngressRouteTCP.
|
||||
type IngressRouteTCPList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
Items []IngressRouteTCP `json:"items"`
|
||||
|
||||
// Items is the list of IngressRouteTCP.
|
||||
Items []IngressRouteTCP `json:"items"`
|
||||
}
|
||||
|
@@ -5,38 +5,45 @@ import (
|
||||
"k8s.io/apimachinery/pkg/util/intstr"
|
||||
)
|
||||
|
||||
// IngressRouteUDPSpec is a specification for a IngressRouteUDPSpec resource.
|
||||
// IngressRouteUDPSpec defines the desired state of a IngressRouteUDP.
|
||||
type IngressRouteUDPSpec struct {
|
||||
Routes []RouteUDP `json:"routes"`
|
||||
EntryPoints []string `json:"entryPoints,omitempty"`
|
||||
// Routes defines the list of routes.
|
||||
Routes []RouteUDP `json:"routes"`
|
||||
// EntryPoints defines the list of entry point names to bind to.
|
||||
// Entry points have to be configured in the static configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/entrypoints/
|
||||
// Default: all.
|
||||
EntryPoints []string `json:"entryPoints,omitempty"`
|
||||
}
|
||||
|
||||
// RouteUDP contains the set of routes.
|
||||
// RouteUDP holds the UDP route configuration.
|
||||
type RouteUDP struct {
|
||||
// Services defines the list of UDP services.
|
||||
Services []ServiceUDP `json:"services,omitempty"`
|
||||
}
|
||||
|
||||
// TLSOptionUDPRef is a ref to the TLSOption resources.
|
||||
type TLSOptionUDPRef struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
||||
// ServiceUDP defines an upstream to proxy traffic.
|
||||
// ServiceUDP defines an upstream UDP service to proxy traffic to.
|
||||
type ServiceUDP struct {
|
||||
Name string `json:"name"`
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
Port intstr.IntOrString `json:"port"`
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
// Name defines the name of the referenced Kubernetes Service.
|
||||
Name string `json:"name"`
|
||||
// Namespace defines the namespace of the referenced Kubernetes Service.
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
// Port defines the port of a Kubernetes Service.
|
||||
// This can be a reference to a named port.
|
||||
Port intstr.IntOrString `json:"port"`
|
||||
// Weight defines the weight used when balancing requests between multiple Kubernetes Service.
|
||||
Weight *int `json:"weight,omitempty"`
|
||||
}
|
||||
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// IngressRouteUDP is an Ingress CRD specification.
|
||||
// IngressRouteUDP is a CRD implementation of a Traefik UDP Router.
|
||||
type IngressRouteUDP struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec IngressRouteUDPSpec `json:"spec"`
|
||||
@@ -44,9 +51,13 @@ type IngressRouteUDP struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// IngressRouteUDPList is a list of IngressRoutes.
|
||||
// IngressRouteUDPList is a collection of IngressRouteUDP.
|
||||
type IngressRouteUDPList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
Items []IngressRouteUDP `json:"items"`
|
||||
|
||||
// Items is the list of IngressRouteUDP.
|
||||
Items []IngressRouteUDP `json:"items"`
|
||||
}
|
||||
|
@@ -11,9 +11,12 @@ import (
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// Middleware is a specification for a Middleware resource.
|
||||
// Middleware is the CRD implementation of a Traefik Middleware.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/overview/
|
||||
type Middleware struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec MiddlewareSpec `json:"spec"`
|
||||
@@ -21,40 +24,53 @@ type Middleware struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// MiddlewareSpec holds the Middleware configuration.
|
||||
// MiddlewareSpec defines the desired state of a Middleware.
|
||||
type MiddlewareSpec struct {
|
||||
AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty"`
|
||||
StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty"`
|
||||
StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty"`
|
||||
ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty"`
|
||||
ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"`
|
||||
Chain *Chain `json:"chain,omitempty"`
|
||||
IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"`
|
||||
Headers *dynamic.Headers `json:"headers,omitempty"`
|
||||
Errors *ErrorPage `json:"errors,omitempty"`
|
||||
RateLimit *RateLimit `json:"rateLimit,omitempty"`
|
||||
RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty"`
|
||||
RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty"`
|
||||
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
|
||||
DigestAuth *DigestAuth `json:"digestAuth,omitempty"`
|
||||
ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"`
|
||||
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"`
|
||||
Buffering *dynamic.Buffering `json:"buffering,omitempty"`
|
||||
CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty"`
|
||||
Compress *dynamic.Compress `json:"compress,omitempty"`
|
||||
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"`
|
||||
Retry *Retry `json:"retry,omitempty"`
|
||||
ContentType *dynamic.ContentType `json:"contentType,omitempty"`
|
||||
Plugin map[string]apiextensionv1.JSON `json:"plugin,omitempty"`
|
||||
AddPrefix *dynamic.AddPrefix `json:"addPrefix,omitempty"`
|
||||
StripPrefix *dynamic.StripPrefix `json:"stripPrefix,omitempty"`
|
||||
StripPrefixRegex *dynamic.StripPrefixRegex `json:"stripPrefixRegex,omitempty"`
|
||||
ReplacePath *dynamic.ReplacePath `json:"replacePath,omitempty"`
|
||||
ReplacePathRegex *dynamic.ReplacePathRegex `json:"replacePathRegex,omitempty"`
|
||||
Chain *Chain `json:"chain,omitempty"`
|
||||
IPWhiteList *dynamic.IPWhiteList `json:"ipWhiteList,omitempty"`
|
||||
Headers *dynamic.Headers `json:"headers,omitempty"`
|
||||
Errors *ErrorPage `json:"errors,omitempty"`
|
||||
RateLimit *RateLimit `json:"rateLimit,omitempty"`
|
||||
RedirectRegex *dynamic.RedirectRegex `json:"redirectRegex,omitempty"`
|
||||
RedirectScheme *dynamic.RedirectScheme `json:"redirectScheme,omitempty"`
|
||||
BasicAuth *BasicAuth `json:"basicAuth,omitempty"`
|
||||
DigestAuth *DigestAuth `json:"digestAuth,omitempty"`
|
||||
ForwardAuth *ForwardAuth `json:"forwardAuth,omitempty"`
|
||||
InFlightReq *dynamic.InFlightReq `json:"inFlightReq,omitempty"`
|
||||
Buffering *dynamic.Buffering `json:"buffering,omitempty"`
|
||||
CircuitBreaker *CircuitBreaker `json:"circuitBreaker,omitempty"`
|
||||
Compress *dynamic.Compress `json:"compress,omitempty"`
|
||||
PassTLSClientCert *dynamic.PassTLSClientCert `json:"passTLSClientCert,omitempty"`
|
||||
Retry *Retry `json:"retry,omitempty"`
|
||||
ContentType *dynamic.ContentType `json:"contentType,omitempty"`
|
||||
// Plugin defines the middleware plugin configuration.
|
||||
// More info: https://doc.traefik.io/traefik/plugins/
|
||||
Plugin map[string]apiextensionv1.JSON `json:"plugin,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ErrorPage holds the custom error page configuration.
|
||||
// ErrorPage holds the custom error middleware configuration.
|
||||
// This middleware returns a custom page in lieu of the default, according to configured ranges of HTTP Status codes.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/errorpages/
|
||||
type ErrorPage struct {
|
||||
Status []string `json:"status,omitempty"`
|
||||
Service Service `json:"service,omitempty"`
|
||||
Query string `json:"query,omitempty"`
|
||||
// Status defines which status or range of statuses should result in an error page.
|
||||
// It can be either a status code as a number (500),
|
||||
// as multiple comma-separated numbers (500,502),
|
||||
// as ranges by separating two codes with a dash (500-599),
|
||||
// or a combination of the two (404,418,500-599).
|
||||
Status []string `json:"status,omitempty"`
|
||||
// Service defines the reference to a Kubernetes Service that will serve the error page.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/errorpages/#service
|
||||
Service Service `json:"service,omitempty"`
|
||||
// Query defines the URL for the error page (hosted by service).
|
||||
// The {status} variable can be used in order to insert the status code in the URL.
|
||||
Query string `json:"query,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
@@ -73,75 +89,135 @@ type CircuitBreaker struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Chain holds a chain of middlewares.
|
||||
// Chain holds the configuration of the chain middleware.
|
||||
// This middleware enables to define reusable combinations of other pieces of middleware.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/chain/
|
||||
type Chain struct {
|
||||
// Middlewares is the list of MiddlewareRef which composes the chain.
|
||||
Middlewares []MiddlewareRef `json:"middlewares,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// BasicAuth holds the HTTP basic authentication configuration.
|
||||
// BasicAuth holds the basic auth middleware configuration.
|
||||
// This middleware restricts access to your services to known users.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/
|
||||
type BasicAuth struct {
|
||||
Secret string `json:"secret,omitempty"`
|
||||
Realm string `json:"realm,omitempty"`
|
||||
RemoveHeader bool `json:"removeHeader,omitempty"`
|
||||
HeaderField string `json:"headerField,omitempty"`
|
||||
// Secret is the name of the referenced Kubernetes Secret containing user credentials.
|
||||
Secret string `json:"secret,omitempty"`
|
||||
// Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme.
|
||||
// Default: traefik.
|
||||
Realm string `json:"realm,omitempty"`
|
||||
// RemoveHeader sets the removeHeader option to true to remove the authorization header before forwarding the request to your service.
|
||||
// Default: false.
|
||||
RemoveHeader bool `json:"removeHeader,omitempty"`
|
||||
// HeaderField defines a header field to store the authenticated user.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/#headerfield
|
||||
HeaderField string `json:"headerField,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// DigestAuth holds the Digest HTTP authentication configuration.
|
||||
// DigestAuth holds the digest auth middleware configuration.
|
||||
// This middleware restricts access to your services to known users.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/digestauth/
|
||||
type DigestAuth struct {
|
||||
Secret string `json:"secret,omitempty"`
|
||||
RemoveHeader bool `json:"removeHeader,omitempty"`
|
||||
Realm string `json:"realm,omitempty"`
|
||||
HeaderField string `json:"headerField,omitempty"`
|
||||
// Secret is the name of the referenced Kubernetes Secret containing user credentials.
|
||||
Secret string `json:"secret,omitempty"`
|
||||
// RemoveHeader defines whether to remove the authorization header before forwarding the request to the backend.
|
||||
RemoveHeader bool `json:"removeHeader,omitempty"`
|
||||
// Realm allows the protected resources on a server to be partitioned into a set of protection spaces, each with its own authentication scheme.
|
||||
// Default: traefik.
|
||||
Realm string `json:"realm,omitempty"`
|
||||
// HeaderField defines a header field to store the authenticated user.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/basicauth/#headerfield
|
||||
HeaderField string `json:"headerField,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ForwardAuth holds the http forward authentication configuration.
|
||||
// ForwardAuth holds the forward auth middleware configuration.
|
||||
// This middleware delegates the request authentication to a Service.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/forwardauth/
|
||||
type ForwardAuth struct {
|
||||
Address string `json:"address,omitempty"`
|
||||
TrustForwardHeader bool `json:"trustForwardHeader,omitempty"`
|
||||
AuthResponseHeaders []string `json:"authResponseHeaders,omitempty"`
|
||||
AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty"`
|
||||
AuthRequestHeaders []string `json:"authRequestHeaders,omitempty"`
|
||||
TLS *ClientTLS `json:"tls,omitempty"`
|
||||
// Address defines the authentication server address.
|
||||
Address string `json:"address,omitempty"`
|
||||
// TrustForwardHeader defines whether to trust (ie: forward) all X-Forwarded-* headers.
|
||||
TrustForwardHeader bool `json:"trustForwardHeader,omitempty"`
|
||||
// AuthResponseHeaders defines the list of headers to copy from the authentication server response and set on forwarded request, replacing any existing conflicting headers.
|
||||
AuthResponseHeaders []string `json:"authResponseHeaders,omitempty"`
|
||||
// AuthResponseHeadersRegex defines the regex to match headers to copy from the authentication server response and set on forwarded request, after stripping all headers that match the regex.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/forwardauth/#authresponseheadersregex
|
||||
AuthResponseHeadersRegex string `json:"authResponseHeadersRegex,omitempty"`
|
||||
// AuthRequestHeaders defines the list of the headers to copy from the request to the authentication server.
|
||||
// If not set or empty then all request headers are passed.
|
||||
AuthRequestHeaders []string `json:"authRequestHeaders,omitempty"`
|
||||
// TLS defines the configuration used to secure the connection to the authentication server.
|
||||
TLS *ClientTLS `json:"tls,omitempty"`
|
||||
}
|
||||
|
||||
// ClientTLS holds TLS specific configurations as client.
|
||||
// ClientTLS holds the client TLS configuration.
|
||||
type ClientTLS struct {
|
||||
CASecret string `json:"caSecret,omitempty"`
|
||||
CAOptional bool `json:"caOptional,omitempty"`
|
||||
CertSecret string `json:"certSecret,omitempty"`
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MiddlewareList is a list of Middleware resources.
|
||||
type MiddlewareList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
Items []Middleware `json:"items"`
|
||||
// CASecret is the name of the referenced Kubernetes Secret containing the CA to validate the server certificate.
|
||||
// The CA certificate is extracted from key `tls.ca` or `ca.crt`.
|
||||
CASecret string `json:"caSecret,omitempty"`
|
||||
// CertSecret is the name of the referenced Kubernetes Secret containing the client certificate.
|
||||
// The client certificate is extracted from the keys `tls.crt` and `tls.key`.
|
||||
CertSecret string `json:"certSecret,omitempty"`
|
||||
// InsecureSkipVerify defines whether the server certificates should be validated.
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||
CAOptional bool `json:"caOptional,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// RateLimit holds the rate limiting configuration for a given router.
|
||||
// RateLimit holds the rate limit configuration.
|
||||
// This middleware ensures that services will receive a fair amount of requests, and allows one to define what fair is.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/ratelimit/
|
||||
type RateLimit struct {
|
||||
Average int64 `json:"average,omitempty"`
|
||||
Period *intstr.IntOrString `json:"period,omitempty"`
|
||||
Burst *int64 `json:"burst,omitempty"`
|
||||
// Average is the maximum rate, by default in requests/s, allowed for the given source.
|
||||
// It defaults to 0, which means no rate limiting.
|
||||
// The rate is actually defined by dividing Average by Period. So for a rate below 1req/s,
|
||||
// one needs to define a Period larger than a second.
|
||||
Average int64 `json:"average,omitempty"`
|
||||
// Period, in combination with Average, defines the actual maximum rate, such as:
|
||||
// r = Average / Period. It defaults to a second.
|
||||
Period *intstr.IntOrString `json:"period,omitempty"`
|
||||
// Burst is the maximum number of requests allowed to arrive in the same arbitrarily small period of time.
|
||||
// It defaults to 1.
|
||||
Burst *int64 `json:"burst,omitempty"`
|
||||
// SourceCriterion defines what criterion is used to group requests as originating from a common source.
|
||||
// If several strategies are defined at the same time, an error will be raised.
|
||||
// If none are set, the default is to use the request's remote address field (as an ipStrategy).
|
||||
SourceCriterion *dynamic.SourceCriterion `json:"sourceCriterion,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Retry holds the retry configuration.
|
||||
// Retry holds the retry middleware configuration.
|
||||
// This middleware reissues requests a given number of times to a backend server if that server does not reply.
|
||||
// As soon as the server answers, the middleware stops retrying, regardless of the response status.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/http/retry/
|
||||
type Retry struct {
|
||||
Attempts int `json:"attempts,omitempty"`
|
||||
// Attempts defines how many times the request should be retried.
|
||||
Attempts int `json:"attempts,omitempty"`
|
||||
// InitialInterval defines the first wait time in the exponential backoff series.
|
||||
// The maximum interval is calculated as twice the initialInterval.
|
||||
// If unspecified, requests will be retried immediately.
|
||||
// The value of initialInterval should be provided in seconds or as a valid duration format,
|
||||
// see https://pkg.go.dev/time#ParseDuration.
|
||||
InitialInterval intstr.IntOrString `json:"initialInterval,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MiddlewareList is a collection of Middleware resources.
|
||||
type MiddlewareList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Items is the list of Middleware.
|
||||
Items []Middleware `json:"items"`
|
||||
}
|
||||
|
@@ -8,9 +8,12 @@ import (
|
||||
// +genclient
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MiddlewareTCP is a specification for a MiddlewareTCP resource.
|
||||
// MiddlewareTCP is the CRD implementation of a Traefik TCP middleware.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/middlewares/overview/
|
||||
type MiddlewareTCP struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec MiddlewareTCPSpec `json:"spec"`
|
||||
@@ -18,18 +21,23 @@ type MiddlewareTCP struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// MiddlewareTCPSpec holds the MiddlewareTCP configuration.
|
||||
// MiddlewareTCPSpec defines the desired state of a MiddlewareTCP.
|
||||
type MiddlewareTCPSpec struct {
|
||||
// InFlightConn defines the InFlightConn middleware configuration.
|
||||
InFlightConn *dynamic.TCPInFlightConn `json:"inFlightConn,omitempty"`
|
||||
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
||||
// IPWhiteList defines the IPWhiteList middleware configuration.
|
||||
IPWhiteList *dynamic.TCPIPWhiteList `json:"ipWhiteList,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// MiddlewareTCPList is a list of MiddlewareTCP resources.
|
||||
// MiddlewareTCPList is a collection of MiddlewareTCP resources.
|
||||
type MiddlewareTCPList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Items is the list of MiddlewareTCP.
|
||||
Items []MiddlewareTCP `json:"items"`
|
||||
}
|
||||
|
@@ -2,6 +2,8 @@ package v1alpha1
|
||||
|
||||
// ObjectReference is a generic reference to a Traefik resource.
|
||||
type ObjectReference struct {
|
||||
Name string `json:"name"`
|
||||
// Name defines the name of the referenced Traefik resource.
|
||||
Name string `json:"name"`
|
||||
// Namespace defines the namespace of the referenced Traefik resource.
|
||||
Namespace string `json:"namespace,omitempty"`
|
||||
}
|
||||
|
@@ -9,9 +9,14 @@ import (
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// ServersTransport is a specification for a ServersTransport resource.
|
||||
// ServersTransport is the CRD implementation of a ServersTransport.
|
||||
// If no serversTransport is specified, the default@internal will be used.
|
||||
// The default@internal serversTransport is created from the static configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/services/#serverstransport_1
|
||||
type ServersTransport struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec ServersTransportSpec `json:"spec"`
|
||||
@@ -19,38 +24,37 @@ type ServersTransport struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ServersTransportSpec options to configure communication between Traefik and the servers.
|
||||
// ServersTransportSpec defines the desired state of a ServersTransport.
|
||||
type ServersTransportSpec struct {
|
||||
// ServerName used to contact the server.
|
||||
// ServerName defines the server name used to contact the server.
|
||||
ServerName string `json:"serverName,omitempty"`
|
||||
// Disable SSL certificate verification.
|
||||
// InsecureSkipVerify disables SSL certificate verification.
|
||||
InsecureSkipVerify bool `json:"insecureSkipVerify,omitempty"`
|
||||
// Add cert file for self-signed certificate.
|
||||
// RootCAsSecrets defines a list of CA secret used to validate self-signed certificate.
|
||||
RootCAsSecrets []string `json:"rootCAsSecrets,omitempty"`
|
||||
// Certificates for mTLS.
|
||||
// CertificatesSecrets defines a list of secret storing client certificates for mTLS.
|
||||
CertificatesSecrets []string `json:"certificatesSecrets,omitempty"`
|
||||
// If non-zero, controls the maximum idle (keep-alive) to keep per-host. If zero, DefaultMaxIdleConnsPerHost is used.
|
||||
// MaxIdleConnsPerHost controls the maximum idle (keep-alive) to keep per-host.
|
||||
MaxIdleConnsPerHost int `json:"maxIdleConnsPerHost,omitempty"`
|
||||
// Timeouts for requests forwarded to the backend servers.
|
||||
// ForwardingTimeouts defines the timeouts for requests forwarded to the backend servers.
|
||||
ForwardingTimeouts *ForwardingTimeouts `json:"forwardingTimeouts,omitempty"`
|
||||
// Disable HTTP/2 for connections with backend servers.
|
||||
// DisableHTTP2 disables HTTP/2 for connections with backend servers.
|
||||
DisableHTTP2 bool `json:"disableHTTP2,omitempty"`
|
||||
// URI used to match against SAN URI during the peer certificate verification.
|
||||
// PeerCertURI defines the peer cert URI used to match against SAN URI during the peer certificate verification.
|
||||
PeerCertURI string `json:"peerCertURI,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ForwardingTimeouts contains timeout configurations for forwarding requests to the backend servers.
|
||||
// ForwardingTimeouts holds the timeout configurations for forwarding requests to the backend servers.
|
||||
type ForwardingTimeouts struct {
|
||||
// DialTimeout is the amount of time to wait until a connection to a backend server can be established. If zero, no timeout exists.
|
||||
// DialTimeout is the amount of time to wait until a connection to a backend server can be established.
|
||||
DialTimeout *intstr.IntOrString `json:"dialTimeout,omitempty"`
|
||||
// ResponseHeaderTimeout is the amount of time to wait for a server's response headers after fully writing the request (including its body, if any).
|
||||
// If zero, no timeout exists.
|
||||
ResponseHeaderTimeout *intstr.IntOrString `json:"responseHeaderTimeout,omitempty"`
|
||||
// IdleConnTimeout is the maximum period for which an idle HTTP keep-alive connection will remain open before closing itself.
|
||||
IdleConnTimeout *intstr.IntOrString `json:"idleConnTimeout,omitempty"`
|
||||
// ReadIdleTimeout is the timeout after which a health check using ping frame will be carried out if no frame is received on the HTTP/2 connection. If zero, no health check is performed.
|
||||
// ReadIdleTimeout is the timeout after which a health check using ping frame will be carried out if no frame is received on the HTTP/2 connection.
|
||||
ReadIdleTimeout *intstr.IntOrString `json:"readIdleTimeout,omitempty"`
|
||||
// PingTimeout is the timeout after which the HTTP/2 connection will be closed if a response to ping is not received.
|
||||
PingTimeout *intstr.IntOrString `json:"pingTimeout,omitempty"`
|
||||
@@ -58,10 +62,13 @@ type ForwardingTimeouts struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// ServersTransportList is a list of ServersTransport resources.
|
||||
// ServersTransportList is a collection of ServersTransport resources.
|
||||
type ServersTransportList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Items is the list of ServersTransport.
|
||||
Items []ServersTransport `json:"items"`
|
||||
}
|
||||
|
@@ -9,60 +9,77 @@ import (
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// TraefikService is the specification for a service (that an IngressRoute refers
|
||||
// to) that is usually not a terminal service (i.e. not a pod of servers), as
|
||||
// opposed to a Kubernetes Service. That is to say, it usually refers to other
|
||||
// (children) services, which themselves can be TraefikServices or Services.
|
||||
// TraefikService is the CRD implementation of a Traefik Service.
|
||||
// TraefikService object allows to:
|
||||
// - Apply weight to Services on load-balancing
|
||||
// - Mirror traffic on services
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#kind-traefikservice
|
||||
type TraefikService struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec ServiceSpec `json:"spec"`
|
||||
Spec TraefikServiceSpec `json:"spec"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// TraefikServiceList is a list of TraefikService resources.
|
||||
// TraefikServiceList is a collection of TraefikService resources.
|
||||
type TraefikServiceList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Items is the list of TraefikService.
|
||||
Items []TraefikService `json:"items"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ServiceSpec defines whether a TraefikService is a load-balancer of services or a
|
||||
// mirroring service.
|
||||
type ServiceSpec struct {
|
||||
Weighted *WeightedRoundRobin `json:"weighted,omitempty"`
|
||||
Mirroring *Mirroring `json:"mirroring,omitempty"`
|
||||
// TraefikServiceSpec defines the desired state of a TraefikService.
|
||||
type TraefikServiceSpec struct {
|
||||
// Weighted defines the Weighted Round Robin configuration.
|
||||
Weighted *WeightedRoundRobin `json:"weighted,omitempty"`
|
||||
// Mirroring defines the Mirroring service configuration.
|
||||
Mirroring *Mirroring `json:"mirroring,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// Mirroring defines a mirroring service, which is composed of a main
|
||||
// load-balancer, and a list of mirrors.
|
||||
// Mirroring holds the mirroring service configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/services/#mirroring-service
|
||||
type Mirroring struct {
|
||||
LoadBalancerSpec `json:",inline"`
|
||||
|
||||
MaxBodySize *int64 `json:"maxBodySize,omitempty"`
|
||||
Mirrors []MirrorService `json:"mirrors,omitempty"`
|
||||
// MaxBodySize defines the maximum size allowed for the body of the request.
|
||||
// If the body is larger, the request is not mirrored.
|
||||
// Default value is -1, which means unlimited size.
|
||||
MaxBodySize *int64 `json:"maxBodySize,omitempty"`
|
||||
// Mirrors defines the list of mirrors where Traefik will duplicate the traffic.
|
||||
Mirrors []MirrorService `json:"mirrors,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// MirrorService defines one of the mirrors of a Mirroring service.
|
||||
// MirrorService holds the mirror configuration.
|
||||
type MirrorService struct {
|
||||
LoadBalancerSpec `json:",inline"`
|
||||
|
||||
// Percent defines the part of the traffic to mirror.
|
||||
// Supported values: 0 to 100.
|
||||
Percent int `json:"percent,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// WeightedRoundRobin defines a load-balancer of services.
|
||||
// WeightedRoundRobin holds the weighted round-robin configuration.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/services/#weighted-round-robin-service
|
||||
type WeightedRoundRobin struct {
|
||||
Services []Service `json:"services,omitempty"`
|
||||
Sticky *dynamic.Sticky `json:"sticky,omitempty"`
|
||||
// Services defines the list of Kubernetes Service and/or TraefikService to load-balance, with weight.
|
||||
Services []Service `json:"services,omitempty"`
|
||||
// Sticky defines whether sticky sessions are enabled.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/routing/providers/kubernetes-crd/#stickiness-and-load-balancing
|
||||
Sticky *dynamic.Sticky `json:"sticky,omitempty"`
|
||||
}
|
||||
|
@@ -8,9 +8,12 @@ import (
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// TLSOption is a specification for a TLSOption resource.
|
||||
// TLSOption is the CRD implementation of a Traefik TLS Option, allowing to configure some parameters of the TLS connection.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#tls-options
|
||||
type TLSOption struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec TLSOptionSpec `json:"spec"`
|
||||
@@ -18,35 +21,54 @@ type TLSOption struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TLSOptionSpec configures TLS for an entry point.
|
||||
// TLSOptionSpec defines the desired state of a TLSOption.
|
||||
type TLSOptionSpec struct {
|
||||
MinVersion string `json:"minVersion,omitempty"`
|
||||
MaxVersion string `json:"maxVersion,omitempty"`
|
||||
CipherSuites []string `json:"cipherSuites,omitempty"`
|
||||
CurvePreferences []string `json:"curvePreferences,omitempty"`
|
||||
ClientAuth ClientAuth `json:"clientAuth,omitempty"`
|
||||
SniStrict bool `json:"sniStrict,omitempty"`
|
||||
PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty"`
|
||||
ALPNProtocols []string `json:"alpnProtocols,omitempty"`
|
||||
// MinVersion defines the minimum TLS version that Traefik will accept.
|
||||
// Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13.
|
||||
// Default: VersionTLS10.
|
||||
MinVersion string `json:"minVersion,omitempty"`
|
||||
// MaxVersion defines the maximum TLS version that Traefik will accept.
|
||||
// Possible values: VersionTLS10, VersionTLS11, VersionTLS12, VersionTLS13.
|
||||
// Default: None.
|
||||
MaxVersion string `json:"maxVersion,omitempty"`
|
||||
// CipherSuites defines the list of supported cipher suites for TLS versions up to TLS 1.2.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#cipher-suites
|
||||
CipherSuites []string `json:"cipherSuites,omitempty"`
|
||||
// CurvePreferences defines the preferred elliptic curves in a specific order.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#curve-preferences
|
||||
CurvePreferences []string `json:"curvePreferences,omitempty"`
|
||||
// ClientAuth defines the server's policy for TLS Client Authentication.
|
||||
ClientAuth ClientAuth `json:"clientAuth,omitempty"`
|
||||
// SniStrict defines whether Traefik allows connections from clients connections that do not specify a server_name extension.
|
||||
SniStrict bool `json:"sniStrict,omitempty"`
|
||||
// PreferServerCipherSuites defines whether the server chooses a cipher suite among his own instead of among the client's.
|
||||
// It is enabled automatically when minVersion or maxVersion are set.
|
||||
PreferServerCipherSuites bool `json:"preferServerCipherSuites,omitempty"`
|
||||
// ALPNProtocols defines the list of supported application level protocols for the TLS handshake, in order of preference.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#alpn-protocols
|
||||
ALPNProtocols []string `json:"alpnProtocols,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// ClientAuth defines the parameters of the client authentication part of the TLS connection, if any.
|
||||
// ClientAuth holds the TLS client authentication configuration.
|
||||
type ClientAuth struct {
|
||||
// SecretName is the name of the referenced Kubernetes Secret to specify the certificate details.
|
||||
// SecretNames defines the names of the referenced Kubernetes Secret storing certificate details.
|
||||
SecretNames []string `json:"secretNames,omitempty"`
|
||||
// +kubebuilder:validation:Enum=NoClientCert;RequestClientCert;RequireAnyClientCert;VerifyClientCertIfGiven;RequireAndVerifyClientCert
|
||||
// ClientAuthType defines the client authentication type to apply.
|
||||
// +kubebuilder:validation:Enum=NoClientCert;RequestClientCert;RequireAnyClientCert;VerifyClientCertIfGiven;RequireAndVerifyClientCert
|
||||
ClientAuthType string `json:"clientAuthType,omitempty"`
|
||||
}
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// TLSOptionList is a list of TLSOption resources.
|
||||
// TLSOptionList is a collection of TLSOption resources.
|
||||
type TLSOptionList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Items is the list of TLSOption.
|
||||
Items []TLSOption `json:"items"`
|
||||
}
|
||||
|
@@ -8,9 +8,14 @@ import (
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
// +kubebuilder:storageversion
|
||||
|
||||
// TLSStore is a specification for a TLSStore resource.
|
||||
// TLSStore is the CRD implementation of a Traefik TLS Store.
|
||||
// For the time being, only the TLSStore named default is supported.
|
||||
// This means that you cannot have two stores that are named default in different Kubernetes namespaces.
|
||||
// More info: https://doc.traefik.io/traefik/v2.8/https/tls/#certificates-stores
|
||||
type TLSStore struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ObjectMeta `json:"metadata"`
|
||||
|
||||
Spec TLSStoreSpec `json:"spec"`
|
||||
@@ -18,9 +23,9 @@ type TLSStore struct {
|
||||
|
||||
// +k8s:deepcopy-gen=true
|
||||
|
||||
// TLSStoreSpec configures a TLSStore resource.
|
||||
// TLSStoreSpec defines the desired state of a TLSStore.
|
||||
type TLSStoreSpec struct {
|
||||
// DefaultCertificate is the name of the secret holding the default key/certificate pair for the store.
|
||||
// DefaultCertificate defines the default certificate configuration.
|
||||
DefaultCertificate *Certificate `json:"defaultCertificate,omitempty"`
|
||||
// Certificates is a list of secret names, each secret holding a key/certificate pair to add to the store.
|
||||
Certificates []Certificate `json:"certificates,omitempty"`
|
||||
@@ -36,10 +41,13 @@ type Certificate struct {
|
||||
|
||||
// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object
|
||||
|
||||
// TLSStoreList is a list of TLSStore resources.
|
||||
// TLSStoreList is a collection of TLSStore resources.
|
||||
type TLSStoreList struct {
|
||||
metav1.TypeMeta `json:",inline"`
|
||||
// Standard object's metadata.
|
||||
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata
|
||||
metav1.ListMeta `json:"metadata"`
|
||||
|
||||
// Items is the list of TLSStore.
|
||||
Items []TLSStore `json:"items"`
|
||||
}
|
||||
|
@@ -1171,32 +1171,6 @@ func (in *Service) DeepCopy() *Service {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceSpec) DeepCopyInto(out *ServiceSpec) {
|
||||
*out = *in
|
||||
if in.Weighted != nil {
|
||||
in, out := &in.Weighted, &out.Weighted
|
||||
*out = new(WeightedRoundRobin)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Mirroring != nil {
|
||||
in, out := &in.Mirroring, &out.Mirroring
|
||||
*out = new(Mirroring)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ServiceSpec.
|
||||
func (in *ServiceSpec) DeepCopy() *ServiceSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(ServiceSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *ServiceTCP) DeepCopyInto(out *ServiceTCP) {
|
||||
*out = *in
|
||||
@@ -1392,22 +1366,6 @@ func (in *TLSOptionSpec) DeepCopy() *TLSOptionSpec {
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TLSOptionUDPRef) DeepCopyInto(out *TLSOptionUDPRef) {
|
||||
*out = *in
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TLSOptionUDPRef.
|
||||
func (in *TLSOptionUDPRef) DeepCopy() *TLSOptionUDPRef {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TLSOptionUDPRef)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TLSStore) DeepCopyInto(out *TLSStore) {
|
||||
*out = *in
|
||||
@@ -1603,6 +1561,32 @@ func (in *TraefikServiceList) DeepCopyObject() runtime.Object {
|
||||
return nil
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *TraefikServiceSpec) DeepCopyInto(out *TraefikServiceSpec) {
|
||||
*out = *in
|
||||
if in.Weighted != nil {
|
||||
in, out := &in.Weighted, &out.Weighted
|
||||
*out = new(WeightedRoundRobin)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
if in.Mirroring != nil {
|
||||
in, out := &in.Mirroring, &out.Mirroring
|
||||
*out = new(Mirroring)
|
||||
(*in).DeepCopyInto(*out)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new TraefikServiceSpec.
|
||||
func (in *TraefikServiceSpec) DeepCopy() *TraefikServiceSpec {
|
||||
if in == nil {
|
||||
return nil
|
||||
}
|
||||
out := new(TraefikServiceSpec)
|
||||
in.DeepCopyInto(out)
|
||||
return out
|
||||
}
|
||||
|
||||
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
|
||||
func (in *WeightedRoundRobin) DeepCopyInto(out *WeightedRoundRobin) {
|
||||
*out = *in
|
||||
|
@@ -21,12 +21,13 @@ spec:
|
||||
kind: Gateway
|
||||
apiVersion: gateway.networking.k8s.io/v1alpha2
|
||||
metadata:
|
||||
name: my-gateway
|
||||
name: my-gateway-http
|
||||
namespace: default
|
||||
spec:
|
||||
gatewayClassName: my-gateway-class
|
||||
listeners: # Use GatewayClass defaults for listener definition.
|
||||
- name: http1
|
||||
hostname: foo.bar
|
||||
protocol: HTTP
|
||||
port: 9080
|
||||
allowedRoutes:
|
||||
@@ -37,6 +38,7 @@ spec:
|
||||
from: Same
|
||||
|
||||
- name: http2
|
||||
hostname: foo.bar
|
||||
protocol: HTTP
|
||||
port: 9080
|
||||
allowedRoutes:
|
||||
@@ -45,7 +47,26 @@ spec:
|
||||
namespaces:
|
||||
from: Same
|
||||
|
||||
- name: tcp
|
||||
---
|
||||
kind: Gateway
|
||||
apiVersion: gateway.networking.k8s.io/v1alpha2
|
||||
metadata:
|
||||
name: my-gateway-tcp
|
||||
namespace: default
|
||||
spec:
|
||||
gatewayClassName: my-gateway-class
|
||||
listeners: # Use GatewayClass defaults for listener definition.
|
||||
- name: tcp1
|
||||
hostname: foo.bar
|
||||
protocol: TCP
|
||||
port: 9000
|
||||
allowedRoutes:
|
||||
kinds:
|
||||
- kind: TCPRoute
|
||||
namespaces:
|
||||
from: Same
|
||||
- name: tcp2
|
||||
hostname: foo.bar
|
||||
protocol: TCP
|
||||
port: 9000
|
||||
allowedRoutes:
|
||||
@@ -54,7 +75,17 @@ spec:
|
||||
namespaces:
|
||||
from: Same
|
||||
|
||||
- name: tls
|
||||
---
|
||||
kind: Gateway
|
||||
apiVersion: gateway.networking.k8s.io/v1alpha2
|
||||
metadata:
|
||||
name: my-gateway-tls
|
||||
namespace: default
|
||||
spec:
|
||||
gatewayClassName: my-gateway-class
|
||||
listeners: # Use GatewayClass defaults for listener definition.
|
||||
- name: tls1
|
||||
hostname: foo.bar
|
||||
protocol: TLS
|
||||
port: 9000
|
||||
tls:
|
||||
@@ -66,6 +97,7 @@ spec:
|
||||
from: Same
|
||||
|
||||
- name: tls2
|
||||
hostname: foo.bar
|
||||
protocol: TLS
|
||||
port: 9000
|
||||
tls:
|
@@ -317,7 +317,7 @@ func (p *Provider) createGatewayConf(ctx context.Context, client Client, gateway
|
||||
func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *v1alpha2.Gateway, conf *dynamic.Configuration, tlsConfigs map[string]*tls.CertAndStores) []v1alpha2.ListenerStatus {
|
||||
logger := log.FromContext(ctx)
|
||||
listenerStatuses := make([]v1alpha2.ListenerStatus, len(gateway.Spec.Listeners))
|
||||
allocatedPort := map[v1alpha2.PortNumber]v1alpha2.ProtocolType{}
|
||||
allocatedListeners := make(map[string]struct{})
|
||||
|
||||
for i, listener := range gateway.Spec.Listeners {
|
||||
listenerStatuses[i] = v1alpha2.ListenerStatus{
|
||||
@@ -340,19 +340,22 @@ func (p *Provider) fillGatewayConf(ctx context.Context, client Client, gateway *
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := allocatedPort[listener.Port]; ok {
|
||||
listenerKey := makeListenerKey(listener)
|
||||
|
||||
if _, ok := allocatedListeners[listenerKey]; ok {
|
||||
listenerStatuses[i].Conditions = append(listenerStatuses[i].Conditions, metav1.Condition{
|
||||
Type: string(v1alpha2.ListenerConditionDetached),
|
||||
Type: string(v1alpha2.ListenerConditionConflicted),
|
||||
Status: metav1.ConditionTrue,
|
||||
LastTransitionTime: metav1.Now(),
|
||||
Reason: string(v1alpha2.ListenerReasonPortUnavailable),
|
||||
Message: fmt.Sprintf("Port %d unavailable", listener.Port),
|
||||
Reason: "DuplicateListener",
|
||||
Message: "A listener with same protocol, port and hostname already exists",
|
||||
})
|
||||
|
||||
continue
|
||||
}
|
||||
|
||||
allocatedPort[listener.Port] = listener.Protocol
|
||||
allocatedListeners[listenerKey] = struct{}{}
|
||||
|
||||
ep, err := p.entryPointName(listener.Port, listener.Protocol)
|
||||
if err != nil {
|
||||
// update "Detached" status with "PortUnavailable" reason
|
||||
@@ -1700,3 +1703,13 @@ func isInternalService(ref v1alpha2.BackendRef) bool {
|
||||
*ref.Group == traefikv1alpha1.GroupName &&
|
||||
strings.HasSuffix(string(ref.Name), "@internal")
|
||||
}
|
||||
|
||||
// makeListenerKey joins protocol, hostname, and port of a listener into a string key.
|
||||
func makeListenerKey(l v1alpha2.Listener) string {
|
||||
var hostname v1alpha2.Hostname
|
||||
if l.Hostname != nil {
|
||||
hostname = *l.Hostname
|
||||
}
|
||||
|
||||
return fmt.Sprintf("%s|%s|%d", l.Protocol, hostname, l.Port)
|
||||
}
|
||||
|
@@ -3566,8 +3566,8 @@ func TestLoadMixedRoutes(t *testing.T) {
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Empty caused by mixed routes multiple protocol using same port",
|
||||
paths: []string{"services.yml", "mixed/with_multiple_protocol_using_same_port.yml"},
|
||||
desc: "Empty caused by mixed routes with multiple listeners using same hostname, port and protocol",
|
||||
paths: []string{"services.yml", "mixed/with_multiple_listeners_using_same_hostname_port_protocol.yml"},
|
||||
entryPoints: map[string]Entrypoint{
|
||||
"web": {Address: ":9080"},
|
||||
"tcp": {Address: ":9000"},
|
||||
@@ -4989,7 +4989,7 @@ func Test_shouldAttach(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_matchingHostnames(t *testing.T) {
|
||||
tests := []struct {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
listener v1alpha2.Listener
|
||||
hostnames []v1alpha2.Hostname
|
||||
@@ -5081,7 +5081,7 @@ func Test_matchingHostnames(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -5093,7 +5093,7 @@ func Test_matchingHostnames(t *testing.T) {
|
||||
}
|
||||
|
||||
func Test_getAllowedRoutes(t *testing.T) {
|
||||
tests := []struct {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
listener v1alpha2.Listener
|
||||
supportedRouteKinds []v1alpha2.RouteGroupKind
|
||||
@@ -5193,7 +5193,7 @@ func Test_getAllowedRoutes(t *testing.T) {
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
@@ -5210,6 +5210,45 @@ func Test_getAllowedRoutes(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func Test_makeListenerKey(t *testing.T) {
|
||||
testCases := []struct {
|
||||
desc string
|
||||
listener v1alpha2.Listener
|
||||
expectedKey string
|
||||
}{
|
||||
{
|
||||
desc: "empty",
|
||||
expectedKey: "||0",
|
||||
},
|
||||
{
|
||||
desc: "listener with port, protocol and hostname",
|
||||
listener: v1alpha2.Listener{
|
||||
Port: 443,
|
||||
Protocol: v1alpha2.HTTPSProtocolType,
|
||||
Hostname: hostnamePtr("www.example.com"),
|
||||
},
|
||||
expectedKey: "HTTPS|www.example.com|443",
|
||||
},
|
||||
{
|
||||
desc: "listener with port, protocol and nil hostname",
|
||||
listener: v1alpha2.Listener{
|
||||
Port: 443,
|
||||
Protocol: v1alpha2.HTTPSProtocolType,
|
||||
},
|
||||
expectedKey: "HTTPS||443",
|
||||
},
|
||||
}
|
||||
|
||||
for _, test := range testCases {
|
||||
test := test
|
||||
t.Run(test.desc, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
assert.Equal(t, test.expectedKey, makeListenerKey(test.listener))
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func hostnamePtr(hostname v1alpha2.Hostname) *v1alpha2.Hostname {
|
||||
return &hostname
|
||||
}
|
||||
|
@@ -164,9 +164,10 @@ func (p *Provider) loadConfiguration(ctx context.Context, configurationC chan<-
|
||||
func createClient(namespace string, endpoint *EndpointConfig) (*api.Client, error) {
|
||||
config := api.Config{
|
||||
Address: endpoint.Address,
|
||||
Region: endpoint.Region,
|
||||
WaitTime: time.Duration(endpoint.EndpointWaitTime),
|
||||
Namespace: namespace,
|
||||
Region: endpoint.Region,
|
||||
SecretID: endpoint.Token,
|
||||
WaitTime: time.Duration(endpoint.EndpointWaitTime),
|
||||
}
|
||||
|
||||
if endpoint.TLS != nil {
|
||||
|
@@ -283,6 +283,7 @@
|
||||
"notAfter": true,
|
||||
"notBefore": true,
|
||||
"sans": true,
|
||||
"serialNumber": true,
|
||||
"subject": {
|
||||
"country": true,
|
||||
"province": true,
|
||||
@@ -301,8 +302,7 @@
|
||||
"commonName": true,
|
||||
"serialNumber": true,
|
||||
"domainComponent": true
|
||||
},
|
||||
"serialNumber": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"retry": {
|
||||
|
@@ -286,6 +286,7 @@
|
||||
"notAfter": true,
|
||||
"notBefore": true,
|
||||
"sans": true,
|
||||
"serialNumber": true,
|
||||
"subject": {
|
||||
"country": true,
|
||||
"province": true,
|
||||
@@ -304,8 +305,7 @@
|
||||
"commonName": true,
|
||||
"serialNumber": true,
|
||||
"domainComponent": true
|
||||
},
|
||||
"serialNumber": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"retry": {
|
||||
|
@@ -529,6 +529,8 @@ func createHTTPServer(ctx context.Context, ln net.Listener, configuration *stati
|
||||
return nil, err
|
||||
}
|
||||
|
||||
handler = http.AllowQuerySemicolons(handler)
|
||||
|
||||
if withH2c {
|
||||
handler = h2c.NewHandler(handler, &http2.Server{
|
||||
MaxConcurrentStreams: uint32(configuration.HTTP2.MaxConcurrentStreams),
|
||||
|
@@ -9,6 +9,7 @@ import (
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"net/url"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
ptypes "github.com/traefik/paerser/types"
|
||||
@@ -46,7 +47,7 @@ func buildProxy(passHostHeader *bool, responseForwarding *dynamic.ResponseForwar
|
||||
|
||||
outReq.URL.Path = u.Path
|
||||
outReq.URL.RawPath = u.RawPath
|
||||
outReq.URL.RawQuery = u.RawQuery
|
||||
outReq.URL.RawQuery = strings.ReplaceAll(u.RawQuery, ";", "&")
|
||||
outReq.RequestURI = "" // Outgoing request should not have RequestURI
|
||||
|
||||
outReq.Proto = "HTTP/1.1"
|
||||
|
@@ -311,12 +311,17 @@ func (m *Manager) LaunchHealthCheck() {
|
||||
}
|
||||
|
||||
func buildHealthCheckOptions(ctx context.Context, lb healthcheck.Balancer, backend string, hc *dynamic.ServerHealthCheck) *healthcheck.Options {
|
||||
if hc == nil || hc.Path == "" {
|
||||
if hc == nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
logger := log.FromContext(ctx)
|
||||
|
||||
if hc.Path == "" {
|
||||
logger.Errorf("Ignoring heath check configuration for '%s': no path provided", backend)
|
||||
return nil
|
||||
}
|
||||
|
||||
interval := defaultHealthCheckInterval
|
||||
if hc.Interval != "" {
|
||||
intervalOverride, err := time.ParseDuration(hc.Interval)
|
||||
|
@@ -8,7 +8,9 @@ import (
|
||||
|
||||
// Domain holds a domain name with SANs.
|
||||
type Domain struct {
|
||||
Main string `description:"Default subject name." json:"main,omitempty" toml:"main,omitempty" yaml:"main,omitempty"`
|
||||
// Main defines the main domain name.
|
||||
Main string `description:"Default subject name." json:"main,omitempty" toml:"main,omitempty" yaml:"main,omitempty"`
|
||||
// SANs defines the subject alternative domain names.
|
||||
SANs []string `description:"Subject alternative names." json:"sans,omitempty" toml:"sans,omitempty" yaml:"sans,omitempty"`
|
||||
}
|
||||
|
||||
|
@@ -26,4 +26,4 @@ CGO_ENABLED=0 GOGC=off go build ${FLAGS[*]} -ldflags "-s -w \
|
||||
-X github.com/traefik/traefik/v2/pkg/version.Version=$VERSION \
|
||||
-X github.com/traefik/traefik/v2/pkg/version.Codename=$CODENAME \
|
||||
-X github.com/traefik/traefik/v2/pkg/version.BuildDate=$DATE" \
|
||||
-a -installsuffix nocgo -o dist/traefik ./cmd/traefik
|
||||
-installsuffix nocgo -o dist/traefik ./cmd/traefik
|
||||
|
@@ -32,8 +32,9 @@ docker run --rm \
|
||||
-w "/go/src/${PROJECT_MODULE}" \
|
||||
"${IMAGE_NAME}" $cmd
|
||||
|
||||
echo "Concatenate the CRD definitions for the integration tests ..."
|
||||
cat $(pwd)/docs/content/reference/dynamic-configuration/traefik.containo.us_*.yaml > $(pwd)/integration/fixtures/k8s/01-traefik-crd.yml
|
||||
echo "Concatenate the CRD definitions for publication and integration tests ..."
|
||||
cat $(pwd)/docs/content/reference/dynamic-configuration/traefik.containo.us_*.yaml > $(pwd)/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml
|
||||
cp -f $(pwd)/docs/content/reference/dynamic-configuration/kubernetes-crd-definition-v1.yml $(pwd)/integration/fixtures/k8s/01-traefik-crd.yml
|
||||
|
||||
cp -r $(pwd)/${MODULE_VERSION}/* $(pwd)
|
||||
rm -rf $(pwd)/${MODULE_VERSION}
|
||||
|
@@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example new bugfix v2.7.1
|
||||
CurrentRef = "v2.7"
|
||||
PreviousRef = "v2.7.0"
|
||||
BaseBranch = "v2.7"
|
||||
FutureCurrentRefName = "v2.7.1"
|
||||
# example new bugfix v2.8.1
|
||||
CurrentRef = "v2.8"
|
||||
PreviousRef = "v2.8.0"
|
||||
BaseBranch = "v2.8"
|
||||
FutureCurrentRefName = "v2.8.1"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
@@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example final release of v2.7.0
|
||||
CurrentRef = "v2.7"
|
||||
PreviousRef = "v2.7.0-rc1"
|
||||
BaseBranch = "v2.7"
|
||||
FutureCurrentRefName = "v2.7.0"
|
||||
# example final release of v2.8.0
|
||||
CurrentRef = "v2.8"
|
||||
PreviousRef = "v2.8.0-rc1"
|
||||
BaseBranch = "v2.8"
|
||||
FutureCurrentRefName = "v2.8.0"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
@@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example final release of v2.7.0
|
||||
CurrentRef = "v2.7.0-rc1"
|
||||
PreviousRef = "v2.6.0-rc1"
|
||||
# example final release of v2.8.0
|
||||
CurrentRef = "v2.8.0-rc1"
|
||||
PreviousRef = "v2.7.0-rc1"
|
||||
BaseBranch = "master"
|
||||
FutureCurrentRefName = "v2.7.0-rc1"
|
||||
FutureCurrentRefName = "v2.8.0-rc1"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
@@ -4,11 +4,11 @@ RepositoryName = "traefik"
|
||||
OutputType = "file"
|
||||
FileName = "traefik_changelog.md"
|
||||
|
||||
# example RC2 of v2.7.0
|
||||
CurrentRef = "v2.7"
|
||||
PreviousRef = "v2.7.0-rc1"
|
||||
BaseBranch = "v2.7"
|
||||
FutureCurrentRefName = "v2.7.0-rc2"
|
||||
# example RC2 of v2.8.0
|
||||
CurrentRef = "v2.8"
|
||||
PreviousRef = "v2.8.0-rc1"
|
||||
BaseBranch = "v2.8"
|
||||
FutureCurrentRefName = "v2.8.0-rc2"
|
||||
|
||||
ThresholdPreviousRef = 10
|
||||
ThresholdCurrentRef = 10
|
||||
|
Reference in New Issue
Block a user