mirror of
https://github.com/traefik/traefik.git
synced 2026-05-05 12:26:25 +02:00
feat(provider/k8s/ingress-nginx): add limit-burst-multiplier annotation support
This commit is contained in:
parent
ea92a3e150
commit
ea7f300c85
@ -384,6 +384,7 @@ The following annotations are organized by category for easier navigation.
|
||||
| ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |-----------------------------------------------------------------------------------------------------------|
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-rps" href="#opt-nginx-ingress-kubernetes-iolimit-rps" title="#opt-nginx-ingress-kubernetes-iolimit-rps">`nginx.ingress.kubernetes.io/limit-rps`</a> | Exceeding the limit returns `429 Too Many Requests` instead of NGINX's default `503 Service Unavailable`. |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-rpm" href="#opt-nginx-ingress-kubernetes-iolimit-rpm" title="#opt-nginx-ingress-kubernetes-iolimit-rpm">`nginx.ingress.kubernetes.io/limit-rpm`</a> | Exceeding the limit returns `429 Too Many Requests` instead of NGINX's default `503 Service Unavailable`. |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-burst-multiplier" href="#opt-nginx-ingress-kubernetes-iolimit-burst-multiplier" title="#opt-nginx-ingress-kubernetes-iolimit-burst-multiplier">`nginx.ingress.kubernetes.io/limit-burst-multiplier`</a> | Default to a multiplier of 5 if the configured value is less than 1. Exceeding the limit returns `429 Too Many Requests` instead of NGINX's default `503 Service Unavailable`. |
|
||||
|
||||
### Buffering
|
||||
|
||||
@ -456,7 +457,6 @@ In practice, Traefik is slightly more lenient under bursty load, as it smooths o
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-rate-after" href="#opt-nginx-ingress-kubernetes-iolimit-rate-after" title="#opt-nginx-ingress-kubernetes-iolimit-rate-after">`nginx.ingress.kubernetes.io/limit-rate-after`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-rate" href="#opt-nginx-ingress-kubernetes-iolimit-rate" title="#opt-nginx-ingress-kubernetes-iolimit-rate">`nginx.ingress.kubernetes.io/limit-rate`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-whitelist" href="#opt-nginx-ingress-kubernetes-iolimit-whitelist" title="#opt-nginx-ingress-kubernetes-iolimit-whitelist">`nginx.ingress.kubernetes.io/limit-whitelist`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-burst-multiplier" href="#opt-nginx-ingress-kubernetes-iolimit-burst-multiplier" title="#opt-nginx-ingress-kubernetes-iolimit-burst-multiplier">`nginx.ingress.kubernetes.io/limit-burst-multiplier`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-iolimit-connections" href="#opt-nginx-ingress-kubernetes-iolimit-connections" title="#opt-nginx-ingress-kubernetes-iolimit-connections">`nginx.ingress.kubernetes.io/limit-connections`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-ioglobal-rate-limit" href="#opt-nginx-ingress-kubernetes-ioglobal-rate-limit" title="#opt-nginx-ingress-kubernetes-ioglobal-rate-limit">`nginx.ingress.kubernetes.io/global-rate-limit`</a> | |
|
||||
| <a id="opt-nginx-ingress-kubernetes-ioglobal-rate-limit-window" href="#opt-nginx-ingress-kubernetes-ioglobal-rate-limit-window" title="#opt-nginx-ingress-kubernetes-ioglobal-rate-limit-window">`nginx.ingress.kubernetes.io/global-rate-limit-window`</a> | |
|
||||
|
||||
@ -84,8 +84,9 @@ type IngressConfig struct {
|
||||
WhitelistSourceRange *string `annotation:"nginx.ingress.kubernetes.io/whitelist-source-range"`
|
||||
AllowlistSourceRange *string `annotation:"nginx.ingress.kubernetes.io/allowlist-source-range"`
|
||||
|
||||
LimitRPM *int `annotation:"nginx.ingress.kubernetes.io/limit-rpm"`
|
||||
LimitRPS *int `annotation:"nginx.ingress.kubernetes.io/limit-rps"`
|
||||
LimitRPM *int `annotation:"nginx.ingress.kubernetes.io/limit-rpm"`
|
||||
LimitRPS *int `annotation:"nginx.ingress.kubernetes.io/limit-rps"`
|
||||
LimitBurstMultiplier *int `annotation:"nginx.ingress.kubernetes.io/limit-burst-multiplier"`
|
||||
|
||||
CustomHeaders *string `annotation:"nginx.ingress.kubernetes.io/custom-headers"`
|
||||
UpstreamVhost *string `annotation:"nginx.ingress.kubernetes.io/upstream-vhost"`
|
||||
|
||||
@ -0,0 +1,43 @@
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-with-limit-burst-multiplier
|
||||
namespace: default
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/limit-rps: "10"
|
||||
nginx.ingress.kubernetes.io/limit-burst-multiplier: "10"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: whoami-burst.localhost
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Exact
|
||||
backend:
|
||||
service:
|
||||
name: whoami
|
||||
port:
|
||||
number: 80
|
||||
---
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: ingress-with-limit-burst-multiplier-zero
|
||||
namespace: default
|
||||
annotations:
|
||||
nginx.ingress.kubernetes.io/limit-rps: "10"
|
||||
nginx.ingress.kubernetes.io/limit-burst-multiplier: "0"
|
||||
spec:
|
||||
ingressClassName: nginx
|
||||
rules:
|
||||
- host: whoami-burst-zero.localhost
|
||||
http:
|
||||
paths:
|
||||
- path: /
|
||||
pathType: Exact
|
||||
backend:
|
||||
service:
|
||||
name: whoami
|
||||
port:
|
||||
number: 80
|
||||
@ -1454,6 +1454,16 @@ func (p *Provider) applyCustomHTTPErrors(namespace, ingressName, routerName stri
|
||||
return nil
|
||||
}
|
||||
|
||||
func getLimitBurstMultiplier(config IngressConfig) int64 {
|
||||
multiplier := ptr.Deref(config.LimitBurstMultiplier, defaultLimitBurstMultiplier)
|
||||
|
||||
if multiplier < 1 {
|
||||
multiplier = defaultLimitBurstMultiplier
|
||||
}
|
||||
|
||||
return int64(multiplier)
|
||||
}
|
||||
|
||||
func applyLimitRPMConfiguration(routerName string, ingressConfig IngressConfig, rt *dynamic.Router, conf *dynamic.Configuration) {
|
||||
limitRPM := ptr.Deref(ingressConfig.LimitRPM, 0)
|
||||
if limitRPM <= 0 {
|
||||
@ -1465,7 +1475,7 @@ func applyLimitRPMConfiguration(routerName string, ingressConfig IngressConfig,
|
||||
RateLimit: &dynamic.RateLimit{
|
||||
Average: int64(limitRPM),
|
||||
Period: ptypes.Duration(time.Minute),
|
||||
Burst: int64(limitRPM) * defaultLimitBurstMultiplier,
|
||||
Burst: int64(limitRPM) * getLimitBurstMultiplier(ingressConfig),
|
||||
},
|
||||
}
|
||||
|
||||
@ -1483,7 +1493,7 @@ func applyLimitRPSConfiguration(routerName string, ingressConfig IngressConfig,
|
||||
RateLimit: &dynamic.RateLimit{
|
||||
Average: int64(limitRPS),
|
||||
Period: ptypes.Duration(time.Second),
|
||||
Burst: int64(limitRPS) * defaultLimitBurstMultiplier,
|
||||
Burst: int64(limitRPS) * getLimitBurstMultiplier(ingressConfig),
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
@ -9640,6 +9640,98 @@ func TestLoadIngresses(t *testing.T) {
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Limit Burst Multiplier",
|
||||
paths: []string{
|
||||
"services.yml",
|
||||
"ingressclasses.yml",
|
||||
"ingresses/ingress-with-limit-burst-multiplier.yml",
|
||||
},
|
||||
expected: &dynamic.Configuration{
|
||||
TCP: &dynamic.TCPConfiguration{Routers: map[string]*dynamic.TCPRouter{}, Services: map[string]*dynamic.TCPService{}},
|
||||
HTTP: &dynamic.HTTPConfiguration{
|
||||
Routers: map[string]*dynamic.Router{
|
||||
"default-ingress-with-limit-burst-multiplier-rule-0-path-0": {
|
||||
EntryPoints: []string{"http"},
|
||||
Rule: `Host("whoami-burst.localhost") && Path("/")`,
|
||||
RuleSyntax: "default",
|
||||
Middlewares: []string{"default-ingress-with-limit-burst-multiplier-rule-0-path-0-limit-rps", "default-ingress-with-limit-burst-multiplier-rule-0-path-0-retry"},
|
||||
Service: "default-ingress-with-limit-burst-multiplier-whoami-80",
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-rule-0-path-0-tls": {
|
||||
EntryPoints: []string{"https"},
|
||||
Rule: `Host("whoami-burst.localhost") && Path("/")`,
|
||||
RuleSyntax: "default",
|
||||
Middlewares: []string{"default-ingress-with-limit-burst-multiplier-rule-0-path-0-tls-limit-rps", "default-ingress-with-limit-burst-multiplier-rule-0-path-0-tls-retry"},
|
||||
Service: "default-ingress-with-limit-burst-multiplier-whoami-80",
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0": {
|
||||
EntryPoints: []string{"http"},
|
||||
Rule: `Host("whoami-burst-zero.localhost") && Path("/")`,
|
||||
RuleSyntax: "default",
|
||||
Middlewares: []string{"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-limit-rps", "default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-retry"},
|
||||
Service: "default-ingress-with-limit-burst-multiplier-zero-whoami-80",
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-tls": {
|
||||
EntryPoints: []string{"https"},
|
||||
Rule: `Host("whoami-burst-zero.localhost") && Path("/")`,
|
||||
RuleSyntax: "default",
|
||||
Middlewares: []string{"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-tls-limit-rps", "default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-tls-retry"},
|
||||
Service: "default-ingress-with-limit-burst-multiplier-zero-whoami-80",
|
||||
TLS: &dynamic.RouterTLSConfig{},
|
||||
},
|
||||
},
|
||||
Middlewares: map[string]*dynamic.Middleware{
|
||||
"default-ingress-with-limit-burst-multiplier-rule-0-path-0-retry": {Retry: &dynamic.Retry{Attempts: 3}},
|
||||
"default-ingress-with-limit-burst-multiplier-rule-0-path-0-tls-retry": {Retry: &dynamic.Retry{Attempts: 3}},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-retry": {Retry: &dynamic.Retry{Attempts: 3}},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-tls-retry": {Retry: &dynamic.Retry{Attempts: 3}},
|
||||
"default-ingress-with-limit-burst-multiplier-rule-0-path-0-limit-rps": {
|
||||
RateLimit: &dynamic.RateLimit{Average: 10, Burst: 100, Period: ptypes.Duration(time.Second)},
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-rule-0-path-0-tls-limit-rps": {
|
||||
RateLimit: &dynamic.RateLimit{Average: 10, Burst: 100, Period: ptypes.Duration(time.Second)},
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-limit-rps": {
|
||||
RateLimit: &dynamic.RateLimit{Average: 10, Burst: 50, Period: ptypes.Duration(time.Second)},
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-rule-0-path-0-tls-limit-rps": {
|
||||
RateLimit: &dynamic.RateLimit{Average: 10, Burst: 50, Period: ptypes.Duration(time.Second)},
|
||||
},
|
||||
},
|
||||
Services: map[string]*dynamic.Service{
|
||||
"default-ingress-with-limit-burst-multiplier-whoami-80": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{{URL: "http://10.10.0.1:80"}, {URL: "http://10.10.0.2:80"}},
|
||||
Strategy: "wrr",
|
||||
PassHostHeader: ptr.To(true),
|
||||
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
||||
ServersTransport: "default-ingress-with-limit-burst-multiplier",
|
||||
},
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-zero-whoami-80": {
|
||||
LoadBalancer: &dynamic.ServersLoadBalancer{
|
||||
Servers: []dynamic.Server{{URL: "http://10.10.0.1:80"}, {URL: "http://10.10.0.2:80"}},
|
||||
Strategy: "wrr",
|
||||
PassHostHeader: ptr.To(true),
|
||||
ResponseForwarding: &dynamic.ResponseForwarding{FlushInterval: dynamic.DefaultFlushInterval},
|
||||
ServersTransport: "default-ingress-with-limit-burst-multiplier-zero",
|
||||
},
|
||||
},
|
||||
},
|
||||
ServersTransports: map[string]*dynamic.ServersTransport{
|
||||
"default-ingress-with-limit-burst-multiplier": {
|
||||
ForwardingTimeouts: &dynamic.ForwardingTimeouts{DialTimeout: ptypes.Duration(60 * time.Second), ReadTimeout: ptypes.Duration(60 * time.Second), WriteTimeout: ptypes.Duration(60 * time.Second), IdleConnTimeout: ptypes.Duration(60 * time.Second)},
|
||||
},
|
||||
"default-ingress-with-limit-burst-multiplier-zero": {
|
||||
ForwardingTimeouts: &dynamic.ForwardingTimeouts{DialTimeout: ptypes.Duration(60 * time.Second), ReadTimeout: ptypes.Duration(60 * time.Second), WriteTimeout: ptypes.Duration(60 * time.Second), IdleConnTimeout: ptypes.Duration(60 * time.Second)},
|
||||
},
|
||||
},
|
||||
},
|
||||
TLS: &dynamic.TLSConfiguration{},
|
||||
},
|
||||
},
|
||||
{
|
||||
desc: "Use Regex with Prefix pathType and StrictValidatePathType enabled",
|
||||
paths: []string{
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user