Skip to content

Commit f14f4c9

Browse files
committed
add ability to pre-configure poststarthooks for apiservers
1 parent c2c8215 commit f14f4c9

File tree

7 files changed

+88
-39
lines changed

7 files changed

+88
-39
lines changed

cmd/kube-apiserver/app/aggregator.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,8 @@ func createAggregatorConfig(
6464
// make a shallow copy to let us twiddle a few things
6565
// most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the aggregator
6666
genericConfig := kubeAPIServerConfig
67+
genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{}
68+
genericConfig.RESTOptionsGetter = nil
6769

6870
// override genericConfig.AdmissionControl with kube-aggregator's scheme,
6971
// because aggregator apiserver should use its own scheme to convert its own resources.

cmd/kube-apiserver/app/apiextensions.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ func createAPIExtensionsConfig(
4848
// make a shallow copy to let us twiddle a few things
4949
// most of the config actually remains the same. We only need to mess with a couple items related to the particulars of the apiextensions
5050
genericConfig := kubeAPIServerConfig
51+
genericConfig.PostStartHooks = map[string]genericapiserver.PostStartHookConfigEntry{}
52+
genericConfig.RESTOptionsGetter = nil
5153

5254
// override genericConfig.AdmissionControl with apiextensions' scheme,
5355
// because apiextentions apiserver should use its own scheme to convert resources.

cmd/kube-apiserver/app/server.go

Lines changed: 29 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -168,7 +168,7 @@ func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan
168168
return nil, err
169169
}
170170

171-
kubeAPIServerConfig, insecureServingInfo, serviceResolver, pluginInitializer, admissionPostStartHook, err := CreateKubeAPIServerConfig(completedOptions, nodeTunneler, proxyTransport)
171+
kubeAPIServerConfig, insecureServingInfo, serviceResolver, pluginInitializer, err := CreateKubeAPIServerConfig(completedOptions, nodeTunneler, proxyTransport)
172172
if err != nil {
173173
return nil, err
174174
}
@@ -184,7 +184,7 @@ func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan
184184
return nil, err
185185
}
186186

187-
kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer, admissionPostStartHook)
187+
kubeAPIServer, err := CreateKubeAPIServer(kubeAPIServerConfig, apiExtensionsServer.GenericAPIServer)
188188
if err != nil {
189189
return nil, err
190190
}
@@ -211,14 +211,12 @@ func CreateServerChain(completedOptions completedServerRunOptions, stopCh <-chan
211211
}
212212

213213
// CreateKubeAPIServer creates and wires a workable kube-apiserver
214-
func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, delegateAPIServer genericapiserver.DelegationTarget, admissionPostStartHook genericapiserver.PostStartHookFunc) (*master.Master, error) {
214+
func CreateKubeAPIServer(kubeAPIServerConfig *master.Config, delegateAPIServer genericapiserver.DelegationTarget) (*master.Master, error) {
215215
kubeAPIServer, err := kubeAPIServerConfig.Complete().New(delegateAPIServer)
216216
if err != nil {
217217
return nil, err
218218
}
219219

220-
kubeAPIServer.GenericAPIServer.AddPostStartHookOrDie("start-kube-apiserver-admission-initializer", admissionPostStartHook)
221-
222220
return kubeAPIServer, nil
223221
}
224222

@@ -273,25 +271,20 @@ func CreateKubeAPIServerConfig(
273271
nodeTunneler tunneler.Tunneler,
274272
proxyTransport *http.Transport,
275273
) (
276-
config *master.Config,
277-
insecureServingInfo *genericapiserver.DeprecatedInsecureServingInfo,
278-
serviceResolver aggregatorapiserver.ServiceResolver,
279-
pluginInitializers []admission.PluginInitializer,
280-
admissionPostStartHook genericapiserver.PostStartHookFunc,
281-
lastErr error,
274+
*master.Config,
275+
*genericapiserver.DeprecatedInsecureServingInfo,
276+
aggregatorapiserver.ServiceResolver,
277+
[]admission.PluginInitializer,
278+
error,
282279
) {
283-
var genericConfig *genericapiserver.Config
284-
var storageFactory *serverstorage.DefaultStorageFactory
285-
var versionedInformers clientgoinformers.SharedInformerFactory
286-
genericConfig, versionedInformers, insecureServingInfo, serviceResolver, pluginInitializers, admissionPostStartHook, storageFactory, lastErr = buildGenericConfig(s.ServerRunOptions, proxyTransport)
287-
if lastErr != nil {
288-
return
280+
genericConfig, versionedInformers, insecureServingInfo, serviceResolver, pluginInitializers, admissionPostStartHook, storageFactory, err := buildGenericConfig(s.ServerRunOptions, proxyTransport)
281+
if err != nil {
282+
return nil, nil, nil, nil, err
289283
}
290284

291285
if _, port, err := net.SplitHostPort(s.Etcd.StorageConfig.Transport.ServerList[0]); err == nil && port != "0" && len(port) != 0 {
292286
if err := utilwait.PollImmediate(etcdRetryInterval, etcdRetryLimit*etcdRetryInterval, preflight.EtcdConnection{ServerList: s.Etcd.StorageConfig.Transport.ServerList}.CheckEtcdServers); err != nil {
293-
lastErr = fmt.Errorf("error waiting for etcd connection: %v", err)
294-
return
287+
return nil, nil, nil, nil, fmt.Errorf("error waiting for etcd connection: %v", err)
295288
}
296289
}
297290

@@ -306,31 +299,31 @@ func CreateKubeAPIServerConfig(
306299
PerConnectionBandwidthLimitBytesPerSec: s.MaxConnectionBytesPerSec,
307300
})
308301

309-
serviceIPRange, apiServerServiceIP, lastErr := master.ServiceIPRange(s.PrimaryServiceClusterIPRange)
310-
if lastErr != nil {
311-
return
302+
serviceIPRange, apiServerServiceIP, err := master.ServiceIPRange(s.PrimaryServiceClusterIPRange)
303+
if err != nil {
304+
return nil, nil, nil, nil, err
312305
}
313306

314307
// defaults to empty range and ip
315308
var secondaryServiceIPRange net.IPNet
316309
// process secondary range only if provided by user
317310
if s.SecondaryServiceClusterIPRange.IP != nil {
318-
secondaryServiceIPRange, _, lastErr = master.ServiceIPRange(s.SecondaryServiceClusterIPRange)
319-
if lastErr != nil {
320-
return
311+
secondaryServiceIPRange, _, err = master.ServiceIPRange(s.SecondaryServiceClusterIPRange)
312+
if err != nil {
313+
return nil, nil, nil, nil, err
321314
}
322315
}
323316

324-
clientCA, lastErr := readCAorNil(s.Authentication.ClientCert.ClientCA)
325-
if lastErr != nil {
326-
return
317+
clientCA, err := readCAorNil(s.Authentication.ClientCert.ClientCA)
318+
if err != nil {
319+
return nil, nil, nil, nil, err
327320
}
328-
requestHeaderProxyCA, lastErr := readCAorNil(s.Authentication.RequestHeader.ClientCAFile)
329-
if lastErr != nil {
330-
return
321+
requestHeaderProxyCA, err := readCAorNil(s.Authentication.RequestHeader.ClientCAFile)
322+
if err != nil {
323+
return nil, nil, nil, nil, err
331324
}
332325

333-
config = &master.Config{
326+
config := &master.Config{
334327
GenericConfig: genericConfig,
335328
ExtraConfig: master.ExtraConfig{
336329
ClientCARegistrationHook: master.ClientCARegistrationHook{
@@ -369,6 +362,9 @@ func CreateKubeAPIServerConfig(
369362
VersionedInformers: versionedInformers,
370363
},
371364
}
365+
if err := config.GenericConfig.AddPostStartHook("start-kube-apiserver-admission-initializer", admissionPostStartHook); err != nil {
366+
return nil, nil, nil, nil, err
367+
}
372368

373369
if nodeTunneler != nil {
374370
// Use the nodeTunneler's dialer to connect to the kubelet
@@ -379,7 +375,7 @@ func CreateKubeAPIServerConfig(
379375
config.ExtraConfig.KubeletClientConfig.Lookup = config.GenericConfig.EgressSelector.Lookup
380376
}
381377

382-
return
378+
return config, insecureServingInfo, serviceResolver, pluginInitializers, nil
383379
}
384380

385381
// BuildGenericConfig takes the master server options and produces the genericapiserver.Config associated with it

staging/src/k8s.io/apiserver/pkg/server/config.go

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import (
2323
"net"
2424
"net/http"
2525
goruntime "runtime"
26+
"runtime/debug"
2627
"sort"
2728
"strconv"
2829
"strings"
@@ -116,6 +117,8 @@ type Config struct {
116117
EnableMetrics bool
117118

118119
DisabledPostStartHooks sets.String
120+
// done values in this values for this map are ignored.
121+
PostStartHooks map[string]PostStartHookConfigEntry
119122

120123
// Version will enable the /version endpoint if non-nil
121124
Version *version.Info
@@ -282,6 +285,7 @@ func NewConfig(codecs serializer.CodecFactory) *Config {
282285
HandlerChainWaitGroup: new(utilwaitgroup.SafeWaitGroup),
283286
LegacyAPIGroupPrefixes: sets.NewString(DefaultLegacyAPIPrefix),
284287
DisabledPostStartHooks: sets.NewString(),
288+
PostStartHooks: map[string]PostStartHookConfigEntry{},
285289
HealthzChecks: append([]healthz.HealthChecker{}, defaultHealthChecks...),
286290
ReadyzChecks: append([]healthz.HealthChecker{}, defaultHealthChecks...),
287291
LivezChecks: append([]healthz.HealthChecker{}, defaultHealthChecks...),
@@ -391,6 +395,36 @@ func (c *Config) AddHealthChecks(healthChecks ...healthz.HealthChecker) {
391395
}
392396
}
393397

398+
// AddPostStartHook allows you to add a PostStartHook that will later be added to the server itself in a New call.
399+
// Name conflicts will cause an error.
400+
func (c *Config) AddPostStartHook(name string, hook PostStartHookFunc) error {
401+
if len(name) == 0 {
402+
return fmt.Errorf("missing name")
403+
}
404+
if hook == nil {
405+
return fmt.Errorf("hook func may not be nil: %q", name)
406+
}
407+
if c.DisabledPostStartHooks.Has(name) {
408+
klog.V(1).Infof("skipping %q because it was explicitly disabled", name)
409+
return nil
410+
}
411+
412+
if postStartHook, exists := c.PostStartHooks[name]; exists {
413+
// this is programmer error, but it can be hard to debug
414+
return fmt.Errorf("unable to add %q because it was already registered by: %s", name, postStartHook.originatingStack)
415+
}
416+
c.PostStartHooks[name] = PostStartHookConfigEntry{hook: hook, originatingStack: string(debug.Stack())}
417+
418+
return nil
419+
}
420+
421+
// AddPostStartHookOrDie allows you to add a PostStartHook, but dies on failure.
422+
func (c *Config) AddPostStartHookOrDie(name string, hook PostStartHookFunc) {
423+
if err := c.AddPostStartHook(name, hook); err != nil {
424+
klog.Fatalf("Error registering PostStartHook %q: %v", name, err)
425+
}
426+
}
427+
394428
// Complete fills in any fields not set that are required to have valid data and can be derived
395429
// from other fields. If you're going to `ApplyOptions`, do that first. It's mutating the receiver.
396430
func (c *Config) Complete(informers informers.SharedInformerFactory) CompletedConfig {
@@ -552,6 +586,7 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
552586
}
553587
}
554588

589+
// first add poststarthooks from delegated targets
555590
for k, v := range delegationTarget.PostStartHooks() {
556591
s.postStartHooks[k] = v
557592
}
@@ -560,6 +595,13 @@ func (c completedConfig) New(name string, delegationTarget DelegationTarget) (*G
560595
s.preShutdownHooks[k] = v
561596
}
562597

598+
// add poststarthooks that were preconfigured. Using the add method will give us an error if the same name has already been registered.
599+
for name, preconfiguredPostStartHook := range c.PostStartHooks {
600+
if err := s.AddPostStartHook(name, preconfiguredPostStartHook.hook); err != nil {
601+
return nil, err
602+
}
603+
}
604+
563605
genericApiServerHookName := "generic-apiserver-start-informers"
564606
if c.SharedInformerFactory != nil && !s.isPostStartHookRegistered(genericApiServerHookName) {
565607
err := s.AddPostStartHook(genericApiServerHookName, func(context PostStartHookContext) error {
@@ -613,7 +655,6 @@ func DefaultBuildHandlerChain(apiHandler http.Handler, c *Config) http.Handler {
613655
handler = genericfilters.WithTimeoutForNonLongRunningRequests(handler, c.LongRunningFunc, c.RequestTimeout)
614656
handler = genericfilters.WithWaitGroup(handler, c.LongRunningFunc, c.HandlerChainWaitGroup)
615657
handler = genericapifilters.WithRequestInfo(handler, c.RequestInfoResolver)
616-
handler = genericapifilters.WithCacheControl(handler)
617658
handler = genericfilters.WithPanicRecovery(handler)
618659
return handler
619660
}

staging/src/k8s.io/apiserver/pkg/server/hooks.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,13 @@ type postStartHookEntry struct {
6666
done chan struct{}
6767
}
6868

69+
type PostStartHookConfigEntry struct {
70+
hook PostStartHookFunc
71+
// originatingStack holds the stack that registered postStartHooks. This allows us to show a more helpful message
72+
// for duplicate registration.
73+
originatingStack string
74+
}
75+
6976
type preShutdownHookEntry struct {
7077
hook PreShutdownHookFunc
7178
}
@@ -76,9 +83,10 @@ func (s *GenericAPIServer) AddPostStartHook(name string, hook PostStartHookFunc)
7683
return fmt.Errorf("missing name")
7784
}
7885
if hook == nil {
79-
return nil
86+
return fmt.Errorf("hook func may not be nil: %q", name)
8087
}
8188
if s.disabledPostStartHooks.Has(name) {
89+
klog.V(1).Infof("skipping %q because it was explicitly disabled", name)
8290
return nil
8391
}
8492

test/integration/examples/apiserver_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ func TestAggregatedAPIServer(t *testing.T) {
118118
if err != nil {
119119
t.Fatal(err)
120120
}
121-
kubeAPIServerConfig, _, _, _, admissionPostStartHook, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport)
121+
kubeAPIServerConfig, _, _, _, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport)
122122
if err != nil {
123123
t.Fatal(err)
124124
}
@@ -129,7 +129,7 @@ func TestAggregatedAPIServer(t *testing.T) {
129129
kubeAPIServerClientConfig.ServerName = ""
130130
kubeClientConfigValue.Store(kubeAPIServerClientConfig)
131131

132-
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate(), admissionPostStartHook)
132+
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate())
133133
if err != nil {
134134
t.Fatal(err)
135135
}

test/integration/framework/test_server.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -113,15 +113,15 @@ func StartTestServer(t *testing.T, stopCh <-chan struct{}, setup TestServerSetup
113113
if err != nil {
114114
t.Fatal(err)
115115
}
116-
kubeAPIServerConfig, _, _, _, admissionPostStartHook, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport)
116+
kubeAPIServerConfig, _, _, _, err := app.CreateKubeAPIServerConfig(completedOptions, tunneler, proxyTransport)
117117
if err != nil {
118118
t.Fatal(err)
119119
}
120120

121121
if setup.ModifyServerConfig != nil {
122122
setup.ModifyServerConfig(kubeAPIServerConfig)
123123
}
124-
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate(), admissionPostStartHook)
124+
kubeAPIServer, err := app.CreateKubeAPIServer(kubeAPIServerConfig, genericapiserver.NewEmptyDelegate())
125125
if err != nil {
126126
t.Fatal(err)
127127
}

0 commit comments

Comments
 (0)