@@ -44,18 +44,25 @@ var (
4444 // DefaultClusterUID is the uid to use for clusters resources created by an
4545 // L7 controller created without specifying the --cluster-uid flag.
4646 DefaultClusterUID = ""
47+
48+ // Frequency to poll on local stores to sync.
49+ storeSyncPollPeriod = 5 * time .Second
4750)
4851
4952// LoadBalancerController watches the kubernetes api and adds/removes services
5053// from the loadbalancer, via loadBalancerConfig.
5154type LoadBalancerController struct {
52- client * client.Client
53- ingController * framework.Controller
54- nodeController * framework.Controller
55- svcController * framework.Controller
56- ingLister StoreToIngressLister
57- nodeLister cache.StoreToNodeLister
58- svcLister cache.StoreToServiceLister
55+ client * client.Client
56+ ingController * framework.Controller
57+ nodeController * framework.Controller
58+ svcController * framework.Controller
59+ podController * framework.Controller
60+ ingLister StoreToIngressLister
61+ nodeLister cache.StoreToNodeLister
62+ svcLister cache.StoreToServiceLister
63+ // Health checks are the readiness probes of containers on pods.
64+ podLister cache.StoreToPodLister
65+ // TODO: Watch secrets
5966 CloudClusterManager * ClusterManager
6067 recorder record.EventRecorder
6168 nodeQueue * taskQueue
@@ -69,6 +76,9 @@ type LoadBalancerController struct {
6976 shutdown bool
7077 // tlsLoader loads secrets from the Kubernetes apiserver for Ingresses.
7178 tlsLoader tlsLoader
79+ // hasSynced returns true if all associated sub-controllers have synced.
80+ // Abstracted into a func for testing.
81+ hasSynced func () bool
7282}
7383
7484// NewLoadBalancerController creates a controller for gce loadbalancers.
@@ -90,6 +100,7 @@ func NewLoadBalancerController(kubeClient *client.Client, clusterManager *Cluste
90100 }
91101 lbc .nodeQueue = NewTaskQueue (lbc .syncNodes )
92102 lbc .ingQueue = NewTaskQueue (lbc .sync )
103+ lbc .hasSynced = lbc .storesSynced
93104
94105 // Ingress watch handlers
95106 pathHandlers := framework.ResourceEventHandlerFuncs {
@@ -130,12 +141,19 @@ func NewLoadBalancerController(kubeClient *client.Client, clusterManager *Cluste
130141 lbc .client , "services" , namespace , fields .Everything ()),
131142 & api.Service {}, resyncPeriod , svcHandlers )
132143
144+ lbc .podLister .Indexer , lbc .podController = framework .NewIndexerInformer (
145+ cache .NewListWatchFromClient (lbc .client , "pods" , namespace , fields .Everything ()),
146+ & api.Pod {},
147+ resyncPeriod ,
148+ framework.ResourceEventHandlerFuncs {},
149+ cache.Indexers {cache .NamespaceIndex : cache .MetaNamespaceIndexFunc },
150+ )
151+
133152 nodeHandlers := framework.ResourceEventHandlerFuncs {
134153 AddFunc : lbc .nodeQueue .enqueue ,
135154 DeleteFunc : lbc .nodeQueue .enqueue ,
136155 // Nodes are updated every 10s and we don't care, so no update handler.
137156 }
138-
139157 // Node watch handlers
140158 lbc .nodeLister .Store , lbc .nodeController = framework .NewInformer (
141159 & cache.ListWatch {
@@ -194,6 +212,7 @@ func (lbc *LoadBalancerController) Run() {
194212 go lbc .ingController .Run (lbc .stopCh )
195213 go lbc .nodeController .Run (lbc .stopCh )
196214 go lbc .svcController .Run (lbc .stopCh )
215+ go lbc .podController .Run (lbc .stopCh )
197216 go lbc .ingQueue .run (time .Second , lbc .stopCh )
198217 go lbc .nodeQueue .run (time .Second , lbc .stopCh )
199218 <- lbc .stopCh
@@ -224,8 +243,29 @@ func (lbc *LoadBalancerController) Stop(deleteAll bool) error {
224243 return nil
225244}
226245
246+ // storesSynced returns true if all the sub-controllers have finished their
247+ // first sync with apiserver.
248+ func (lbc * LoadBalancerController ) storesSynced () bool {
249+ return (
250+ // wait for pods to sync so we don't allocate a default health check when
251+ // an endpoint has a readiness probe.
252+ lbc .podController .HasSynced () &&
253+ // wait for services so we don't thrash on backend creation.
254+ lbc .svcController .HasSynced () &&
255+ // wait for nodes so we don't disconnect a backend from an instance
256+ // group just because we don't realize there are nodes in that zone.
257+ lbc .nodeController .HasSynced () &&
258+ // Wait for ingresses as a safety measure. We don't really need this.
259+ lbc .ingController .HasSynced ())
260+ }
261+
227262// sync manages Ingress create/updates/deletes.
228263func (lbc * LoadBalancerController ) sync (key string ) {
264+ if ! lbc .hasSynced () {
265+ time .Sleep (storeSyncPollPeriod )
266+ lbc .ingQueue .requeue (key , fmt .Errorf ("Waiting for stores to sync" ))
267+ return
268+ }
229269 glog .V (3 ).Infof ("Syncing %v" , key )
230270
231271 paths , err := lbc .ingLister .List ()
0 commit comments