diff --git a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go index 8a80eb65b79..eddf54ada0e 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/apiserver/apiserver.go @@ -117,6 +117,9 @@ type preparedAPIAggregator struct { type APIAggregator struct { GenericAPIServer *genericapiserver.GenericAPIServer + // provided for easier embedding + APIRegistrationInformers informers.SharedInformerFactory + delegateHandler http.Handler // proxyCurrentCertKeyContent holds he client cert used to identify this proxy. Backing APIServices use this to confirm the proxy's identity @@ -132,9 +135,6 @@ type APIAggregator struct { // controller state lister listers.APIServiceLister - // provided for easier embedding - APIRegistrationInformers informers.SharedInformerFactory - // Information needed to determine routing for the aggregator serviceResolver ServiceResolver @@ -181,6 +181,16 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg 5*time.Minute, // this is effectively used as a refresh interval right now. Might want to do something nicer later on. ) + // apiServiceRegistrationControllerInitiated is closed when APIServiceRegistrationController has finished "installing" all known APIServices. + // At this point we know that the proxy handler knows about APIServices and can handle client requests. + // Before it might have resulted in a 404 response which could have serious consequences for some controllers like GC and NS + // + // Note that the APIServiceRegistrationController waits for APIServiceInformer to synced before doing its work. + apiServiceRegistrationControllerInitiated := make(chan struct{}) + if err := genericServer.RegisterMuxCompleteSignal("APIServiceRegistrationControllerInitiated", apiServiceRegistrationControllerInitiated); err != nil { + return nil, err + } + s := &APIAggregator{ GenericAPIServer: genericServer, delegateHandler: delegationTarget.UnprotectedHandler(), @@ -265,6 +275,7 @@ func (c completedConfig) NewWithDelegate(delegationTarget genericapiserver.Deleg select { case <-context.StopCh: case <-handlerSyncedCh: + close(apiServiceRegistrationControllerInitiated) } return nil diff --git a/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator/aggregator.go b/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator/aggregator.go index 693c635357f..f9b78ddaa54 100644 --- a/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator/aggregator.go +++ b/staging/src/k8s.io/kube-aggregator/pkg/controllers/openapi/aggregator/aggregator.go @@ -96,6 +96,12 @@ func BuildAndRegisterAggregator(downloader *Downloader, delegationTarget server. } delegateSpec, etag, _, err := downloader.Download(handler, "") if err != nil { + // ignore errors for the empty delegate we attach at the end the chain + // atm the empty delegate returns 503 when the server hasn't been fully initialized + // and the spec downloader only silences 404s + if len(delegate.ListedPaths()) == 0 && delegate.NextDelegate() == nil { + continue + } return nil, err } if delegateSpec == nil {