From 0c2a4302f5a43fd7d00906856650e998622c2213 Mon Sep 17 00:00:00 2001 From: Eric Tune Date: Tue, 2 Dec 2014 22:04:45 -0800 Subject: [PATCH] Fix race that drops the first event on restart. RegisterHandlers was called after the listening for events had already begun. So, there was a race where sometimes the first update would, with the initial state, would notify an empty list of listeners. This showed up in services.sh e2e test as empty service and endpoint maps after the test step which restarts the kube-proxy. Perhaps due to timing, this doesn't show up with etcd source, but does show up with apiserver as a source. A separate PR makes APIserver the source as a default, and depends on this. This took me several days to debug. --- cmd/kube-proxy/proxy.go | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/cmd/kube-proxy/proxy.go b/cmd/kube-proxy/proxy.go index 61fb4f8b9dd..4a60171beb3 100644 --- a/cmd/kube-proxy/proxy.go +++ b/cmd/kube-proxy/proxy.go @@ -60,6 +60,21 @@ func main() { serviceConfig := config.NewServiceConfig() endpointsConfig := config.NewEndpointsConfig() + protocol := iptables.ProtocolIpv4 + if net.IP(bindAddress).To4() == nil { + protocol = iptables.ProtocolIpv6 + } + loadBalancer := proxy.NewLoadBalancerRR() + proxier := proxy.NewProxier(loadBalancer, net.IP(bindAddress), iptables.New(exec.New(), protocol)) + // Wire proxier to handle changes to services + serviceConfig.RegisterHandler(proxier) + // And wire loadBalancer to handle changes to endpoints to services + endpointsConfig.RegisterHandler(loadBalancer) + + // Note: RegisterHandler() calls need to happen before creation of Sources because sources + // only notify on changes, and the initial update (on process start) may be lost if no handlers + // are registered yet. + // define api config source if clientConfig.Host != "" { glog.Infof("Using api calls to get config %v", clientConfig.Host) @@ -113,17 +128,6 @@ func main() { }, 5*time.Second) } - protocol := iptables.ProtocolIpv4 - if net.IP(bindAddress).To4() == nil { - protocol = iptables.ProtocolIpv6 - } - loadBalancer := proxy.NewLoadBalancerRR() - proxier := proxy.NewProxier(loadBalancer, net.IP(bindAddress), iptables.New(exec.New(), protocol)) - // Wire proxier to handle changes to services - serviceConfig.RegisterHandler(proxier) - // And wire loadBalancer to handle changes to endpoints to services - endpointsConfig.RegisterHandler(loadBalancer) - // Just loop forever for now... proxier.SyncLoop() }