diff --git a/docs/toml.md b/docs/toml.md index c5fdc50d0..80d3fb8c8 100644 --- a/docs/toml.md +++ b/docs/toml.md @@ -1068,6 +1068,10 @@ Annotations can be used on the Kubernetes service to override default behaviour: You can find here an example [ingress](https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/cheese-ingress.yaml) and [replication controller](https://raw.githubusercontent.com/containous/traefik/master/examples/k8s/traefik.yaml). +Additionally, an annotation can be used on Kubernetes services to set the [circuit breaker expression](https://docs.traefik.io/basics/#backends) for a backend. + +- `traefik.backend.circuitbreaker: `: set the circuit breaker expression for the backend (Default: nil). + ## Consul backend Træfɪk can be configured to use Consul as a backend configuration: diff --git a/docs/user-guide/kubernetes.md b/docs/user-guide/kubernetes.md index 0421303f1..643bd2f76 100644 --- a/docs/user-guide/kubernetes.md +++ b/docs/user-guide/kubernetes.md @@ -1,6 +1,6 @@ # Kubernetes Ingress Controller -This guide explains how to use Træfɪk as an Ingress controller in a Kubernetes cluster. +This guide explains how to use Træfɪk as an Ingress controller in a Kubernetes cluster. If you are not familiar with Ingresses in Kubernetes you might want to read the [Kubernetes user guide](http://kubernetes.io/docs/user-guide/ingress/) The config files used in this guide can be found in the [examples directory](https://github.com/containous/traefik/tree/master/examples/k8s) @@ -113,7 +113,7 @@ metadata: namespace: kube-system spec: selector: - k8s-app: traefik-ingress-lb + k8s-app: traefik-ingress-lb ports: - port: 80 targetPort: 8080 @@ -139,7 +139,7 @@ kubectl apply -f examples/k8s/ui.yaml ``` Now lets setup an entry in our /etc/hosts file to route `traefik-ui.local` -to our cluster. +to our cluster. > In production you would want to set up real dns entries. @@ -299,6 +299,8 @@ apiVersion: v1 kind: Service metadata: name: wensleydale + annotations: + traefik.backend.circuitbreaker: "NetworkErrorRatio() > 0.5" spec: ports: - name: http @@ -308,6 +310,11 @@ spec: app: cheese task: wensleydale ``` + +> Notice that we also set a [circuit breaker expression](https://docs.traefik.io/basics/#backends) for one of the backends +> by setting the `traefik.backend.circuitbreaker` annotation on the service. + + [examples/k8s/cheese-services.yaml](https://github.com/containous/traefik/tree/master/examples/k8s/cheese-services.yaml) ```sh diff --git a/provider/kubernetes.go b/provider/kubernetes.go index 16c09d2ea..9747d60e1 100644 --- a/provider/kubernetes.go +++ b/provider/kubernetes.go @@ -175,12 +175,18 @@ func (provider *Kubernetes) loadIngresses(k8sClient k8s.Client) (*types.Configur continue } + if expression := service.Annotations["traefik.backend.circuitbreaker"]; expression != "" { + templateObjects.Backends[r.Host+pa.Path].CircuitBreaker = &types.CircuitBreaker{ + Expression: expression, + } + } if service.Annotations["traefik.backend.loadbalancer.method"] == "drr" { templateObjects.Backends[r.Host+pa.Path].LoadBalancer.Method = "drr" } if service.Annotations["traefik.backend.loadbalancer.sticky"] == "true" { templateObjects.Backends[r.Host+pa.Path].LoadBalancer.Sticky = true } + protocol := "http" for _, port := range service.Spec.Ports { if equalPorts(port, pa.Backend.ServicePort) { diff --git a/provider/kubernetes_test.go b/provider/kubernetes_test.go index 462ce26b4..a3866f9cc 100644 --- a/provider/kubernetes_test.go +++ b/provider/kubernetes_test.go @@ -1288,7 +1288,7 @@ func TestHostlessIngress(t *testing.T) { } } -func TestLoadBalancerAnnotation(t *testing.T) { +func TestServiceAnnotations(t *testing.T) { ingresses := []*v1beta1.Ingress{{ ObjectMeta: v1.ObjectMeta{ Namespace: "testing", @@ -1336,6 +1336,7 @@ func TestLoadBalancerAnnotation(t *testing.T) { UID: "1", Namespace: "testing", Annotations: map[string]string{ + "traefik.backend.circuitbreaker": "NetworkErrorRatio() > 0.5", "traefik.backend.loadbalancer.method": "drr", }, }, @@ -1354,6 +1355,7 @@ func TestLoadBalancerAnnotation(t *testing.T) { UID: "2", Namespace: "testing", Annotations: map[string]string{ + "traefik.backend.circuitbreaker": "", "traefik.backend.loadbalancer.sticky": "true", }, }, @@ -1463,7 +1465,9 @@ func TestLoadBalancerAnnotation(t *testing.T) { Weight: 1, }, }, - CircuitBreaker: nil, + CircuitBreaker: &types.CircuitBreaker{ + Expression: "NetworkErrorRatio() > 0.5", + }, LoadBalancer: &types.LoadBalancer{ Method: "drr", Sticky: false, diff --git a/templates/kubernetes.tmpl b/templates/kubernetes.tmpl index 89bc66b3b..1e4683786 100644 --- a/templates/kubernetes.tmpl +++ b/templates/kubernetes.tmpl @@ -1,4 +1,8 @@ [backends]{{range $backendName, $backend := .Backends}} + {{if $backend.CircuitBreaker}} + [backends."{{$backendName}}".circuitbreaker] + expression = "{{$backend.CircuitBreaker.Expression}}" + {{end}} [backends."{{$backendName}}".loadbalancer] method = "{{$backend.LoadBalancer.Method}}" {{if $backend.LoadBalancer.Sticky}}