diff --git a/provider/kubernetes/builder_configuration_test.go b/provider/kubernetes/builder_configuration_test.go index 1ddea79e5..c728dba0a 100644 --- a/provider/kubernetes/builder_configuration_test.go +++ b/provider/kubernetes/builder_configuration_test.go @@ -133,6 +133,24 @@ func retrying(exp string) func(*types.Buffering) { } } +func maxConnExtractorFunc(exp string) func(*types.Backend) { + return func(b *types.Backend) { + if b.MaxConn == nil { + b.MaxConn = &types.MaxConn{} + } + b.MaxConn.ExtractorFunc = exp + } +} + +func maxConnAmount(value int64) func(*types.Backend) { + return func(b *types.Backend) { + if b.MaxConn == nil { + b.MaxConn = &types.MaxConn{} + } + b.MaxConn.Amount = value + } +} + // Frontend func buildFrontends(opts ...func(*types.Frontend) string) map[string]*types.Frontend { diff --git a/provider/kubernetes/kubernetes.go b/provider/kubernetes/kubernetes.go index 30562cfe0..5940b3570 100644 --- a/provider/kubernetes/kubernetes.go +++ b/provider/kubernetes/kubernetes.go @@ -273,6 +273,10 @@ func (p *Provider) loadIngresses(k8sClient Client) (*types.Configuration, error) templateObjects.Backends[r.Host+pa.Path].LoadBalancer = getLoadBalancer(service) templateObjects.Backends[r.Host+pa.Path].Buffering = getBuffering(service) + if maxConn := getMaxConn(service); maxConn != nil { + templateObjects.Backends[r.Host+pa.Path].MaxConn = maxConn + } + protocol := label.DefaultProtocol for _, port := range service.Spec.Ports { if equalPorts(port, pa.Backend.ServicePort) { @@ -587,3 +591,15 @@ func getRateLimit(i *v1beta1.Ingress) *types.RateLimit { } return nil } + +func getMaxConn(service *v1.Service) *types.MaxConn { + amount := label.GetInt64Value(service.Annotations, label.TraefikBackendMaxConnAmount, -1) + extractorFunc := service.Annotations[label.TraefikBackendMaxConnExtractorFunc] + if amount >= 0 && len(extractorFunc) > 0 { + return &types.MaxConn{ + ExtractorFunc: extractorFunc, + Amount: amount, + } + } + return nil +} diff --git a/provider/kubernetes/kubernetes_test.go b/provider/kubernetes/kubernetes_test.go index d0de4e88f..8df53fa2b 100644 --- a/provider/kubernetes/kubernetes_test.go +++ b/provider/kubernetes/kubernetes_test.go @@ -435,6 +435,9 @@ func TestServiceAnnotations(t *testing.T) { iRule( iHost("baz"), iPaths(onePath(iBackend("service3", intstr.FromInt(803))))), + iRule( + iHost("max-conn"), + iPaths(onePath(iBackend("service4", intstr.FromInt(804))))), ), ), } @@ -473,6 +476,16 @@ func TestServiceAnnotations(t *testing.T) { clusterIP("10.0.0.3"), sPorts(sPort(803, ""))), ), + buildService( + sName("service4"), + sNamespace("testing"), + sUID("4"), + sAnnotation(label.TraefikBackendMaxConnExtractorFunc, "client.ip"), + sAnnotation(label.TraefikBackendMaxConnAmount, "6"), + sSpec( + clusterIP("10.0.0.4"), + sPorts(sPort(804, ""))), + ), } endpoints := []*v1.Endpoints{ @@ -509,6 +522,17 @@ func TestServiceAnnotations(t *testing.T) { eAddresses(eAddress("10.12.0.1")), ePorts(ePort(8080, "http"))), ), + buildEndpoint( + eNamespace("testing"), + eName("service4"), + eUID("4"), + subset( + eAddresses(eAddress("10.4.0.1")), + ePorts(ePort(8080, "http"))), + subset( + eAddresses(eAddress("10.4.0.2")), + ePorts(ePort(8080, "http"))), + ), } watchChan := make(chan interface{}) @@ -551,6 +575,14 @@ func TestServiceAnnotations(t *testing.T) { retrying("IsNetworkError() && Attempts() <= 2"), ), ), + backend("max-conn", + servers( + server("http://10.4.0.1:8080", weight(1)), + server("http://10.4.0.2:8080", weight(1))), + maxConnExtractorFunc("client.ip"), + maxConnAmount(6), + lbMethod("wrr"), + ), ), frontends( frontend("foo/bar", @@ -563,13 +595,16 @@ func TestServiceAnnotations(t *testing.T) { frontend("bar", headers(), passHostHeader(), - routes(route("bar", "Host:bar")), - ), + routes(route("bar", "Host:bar"))), frontend("baz", headers(), passHostHeader(), - routes(route("baz", "Host:baz")), - ), + routes(route("baz", "Host:baz"))), + frontend("max-conn", + headers(), + passHostHeader(), + routes( + route("max-conn", "Host:max-conn"))), ), ) diff --git a/templates/kubernetes.tmpl b/templates/kubernetes.tmpl index 97d79d139..963ae9cea 100644 --- a/templates/kubernetes.tmpl +++ b/templates/kubernetes.tmpl @@ -18,6 +18,12 @@ cookieName = "{{$backend.LoadBalancer.Stickiness.CookieName}}" {{end}} + {{if $backend.MaxConn}} + [backends.backend-{{$backendName}}.maxConn] + amount = {{ $backend.MaxConn.Amount }} + extractorFunc = "{{ $backend.MaxConn.ExtractorFunc }}" + {{end}} + {{if $backend.Buffering }} [backends."{{ $backendName }}".buffering] maxRequestBodyBytes = {{ $backend.Buffering.MaxRequestBodyBytes }}