From 4833eb5d9f770fe8ab2b991f1c4d114cd09bf99c Mon Sep 17 00:00:00 2001 From: Benjamin Bennett Date: Mon, 2 Oct 2017 15:07:15 -0400 Subject: [PATCH] Made the router skip health checks when there is one endpoint If there is only one endpoint for a route, there is no point to doing health checks. If the endpoint is down, haproxy will fail to connect. Skipping the checks helps tremendously on servers with large numbers of routes, because reducing any checking means the router doesn't spend a lot of time doing health checks pointlessly. Fixes bug 1492189 (https://bugzilla.redhat.com/show_bug.cgi?id=1492189) --- pkg/router/template/plugin.go | 9 +- pkg/router/template/plugin_test.go | 153 +++++++++++++++++++++++++++-- 2 files changed, 152 insertions(+), 10 deletions(-) diff --git a/pkg/router/template/plugin.go b/pkg/router/template/plugin.go index aa27fbdab8ee..756de92ec7f4 100644 --- a/pkg/router/template/plugin.go +++ b/pkg/router/template/plugin.go @@ -265,9 +265,10 @@ func createRouterEndpoints(endpoints *kapi.Endpoints, excludeUDP bool, lookupSvc wasIdled = true } + // Take a reasonable guess at the number of endpoints to avoid reallocating the out array when we append out := make([]Endpoint, 0, len(endpoints.Subsets)*4) - // TODO: review me for sanity + // Now build the actual endpoints we pass to the template for _, s := range subsets { for _, p := range s.Ports { if excludeUDP && p.Protocol == kapi.ProtocolUDP { @@ -306,5 +307,11 @@ func createRouterEndpoints(endpoints *kapi.Endpoints, excludeUDP bool, lookupSvc } } + // We want to disable endpoint checks if there is only one endpoint + // We skip the case where it is idled, since we set NoHealthCheck above + if wasIdled == false && len(out) == 1 { + out[0].NoHealthCheck = true + } + return out } diff --git a/pkg/router/template/plugin_test.go b/pkg/router/template/plugin_test.go index 36d9abcc1eed..42980f4900cf 100644 --- a/pkg/router/template/plugin_test.go +++ b/pkg/router/template/plugin_test.go @@ -271,15 +271,16 @@ func TestHandleEndpoints(t *testing.T) { Name: "foo/test", //service name from kapi.endpoints object EndpointTable: []Endpoint{ { - ID: "ept:test:1.1.1.1:345", - IP: "1.1.1.1", - Port: "345", + ID: "ept:test:1.1.1.1:345", + IP: "1.1.1.1", + Port: "345", + NoHealthCheck: true, }, }, }, }, { - name: "Endpoint mod", + name: "Endpoint mod (one ep, one address)", eventType: watch.Modified, endpoints: &kapi.Endpoints{ ObjectMeta: metav1.ObjectMeta{ @@ -295,9 +296,143 @@ func TestHandleEndpoints(t *testing.T) { Name: "foo/test", EndpointTable: []Endpoint{ { - ID: "pod:pod-1:test:2.2.2.2:8080", - IP: "2.2.2.2", - Port: "8080", + ID: "pod:pod-1:test:2.2.2.2:8080", + IP: "2.2.2.2", + Port: "8080", + NoHealthCheck: true, + }, + }, + }, + }, + { + name: "Endpoint mod (second ep, one address each)", + eventType: watch.Modified, + endpoints: &kapi.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "test", + }, + Subsets: []kapi.EndpointSubset{ + { + Addresses: []kapi.EndpointAddress{{IP: "2.2.2.2", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-1"}}}, + Ports: []kapi.EndpointPort{{Port: 8080}}, + }, + { + Addresses: []kapi.EndpointAddress{{IP: "3.3.3.3", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-2"}}}, + Ports: []kapi.EndpointPort{{Port: 8081}}, + }, + }, + }, + expectedServiceUnit: &ServiceUnit{ + Name: "foo/test", + EndpointTable: []Endpoint{ + { + ID: "pod:pod-1:test:2.2.2.2:8080", + IP: "2.2.2.2", + Port: "8080", + NoHealthCheck: false, + }, + { + ID: "pod:pod-2:test:3.3.3.3:8081", + IP: "3.3.3.3", + Port: "8081", + NoHealthCheck: false, + }, + }, + }, + }, + { + name: "Endpoint mod (one ep, two addresses)", + eventType: watch.Modified, + endpoints: &kapi.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "test", + }, + Subsets: []kapi.EndpointSubset{ + { + Addresses: []kapi.EndpointAddress{ + {IP: "3.3.3.3", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-2"}}, + {IP: "4.4.4.4", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-3"}}, + }, + Ports: []kapi.EndpointPort{{Port: 8080}}, + }, + }, + }, + expectedServiceUnit: &ServiceUnit{ + Name: "foo/test", + EndpointTable: []Endpoint{ + { + ID: "pod:pod-2:test:3.3.3.3:8080", + IP: "3.3.3.3", + Port: "8080", + NoHealthCheck: false, + }, + { + ID: "pod:pod-3:test:4.4.4.4:8080", + IP: "4.4.4.4", + Port: "8080", + NoHealthCheck: false, + }, + }, + }, + }, + { + name: "Endpoint mod (one ep, two ports)", + eventType: watch.Modified, + endpoints: &kapi.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "test", + }, + Subsets: []kapi.EndpointSubset{ + { + Addresses: []kapi.EndpointAddress{ + {IP: "3.3.3.3", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-2"}}, + }, + Ports: []kapi.EndpointPort{{Port: 8080}, {Port: 8081}}, + }, + }, + }, + expectedServiceUnit: &ServiceUnit{ + Name: "foo/test", + EndpointTable: []Endpoint{ + { + ID: "pod:pod-2:test:3.3.3.3:8080", + IP: "3.3.3.3", + Port: "8080", + NoHealthCheck: false, + }, + { + ID: "pod:pod-2:test:3.3.3.3:8081", + IP: "3.3.3.3", + Port: "8081", + NoHealthCheck: false, + }, + }, + }, + }, + { + name: "Endpoint mod (back to one ep)", + eventType: watch.Modified, + endpoints: &kapi.Endpoints{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: "foo", + Name: "test", + }, + Subsets: []kapi.EndpointSubset{{ + Addresses: []kapi.EndpointAddress{{IP: "3.3.3.3", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-1"}}}, + Ports: []kapi.EndpointPort{{Port: 8080}}, + }}, + }, + expectedServiceUnit: &ServiceUnit{ + Name: "foo/test", + EndpointTable: []Endpoint{ + { + ID: "pod:pod-1:test:3.3.3.3:8080", + IP: "3.3.3.3", + Port: "8080", + NoHealthCheck: true, }, }, }, @@ -311,8 +446,8 @@ func TestHandleEndpoints(t *testing.T) { Name: "test", }, Subsets: []kapi.EndpointSubset{{ - Addresses: []kapi.EndpointAddress{{IP: "3.3.3.3"}}, - Ports: []kapi.EndpointPort{{Port: 0}}, + Addresses: []kapi.EndpointAddress{{IP: "3.3.3.3", TargetRef: &kapi.ObjectReference{Kind: "Pod", Name: "pod-1"}}}, + Ports: []kapi.EndpointPort{{Port: 8080}}, }}, }, expectedServiceUnit: &ServiceUnit{