Skip to content

Commit 7a1b16d

Browse files
authored
Merge pull request #3378 from k8s-infra-cherrypick-robot/cherry-pick-3376-to-release-0.22
[release-0.22] ✨ cache: Allow fine-granular SyncPeriod configuration
2 parents 8be8410 + 539c94f commit 7a1b16d

File tree

2 files changed

+103
-5
lines changed

2 files changed

+103
-5
lines changed

pkg/cache/cache.go

Lines changed: 79 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -308,6 +308,42 @@ type ByObject struct {
308308
//
309309
// Defaults to true.
310310
EnableWatchBookmarks *bool
311+
312+
// SyncPeriod determines the minimum frequency at which watched resources are
313+
// reconciled. A lower period will correct entropy more quickly, but reduce
314+
// responsiveness to change if there are many watched resources. Change this
315+
// value only if you know what you are doing. Defaults to 10 hours if unset.
316+
// there will a 10 percent jitter between the SyncPeriod of all controllers
317+
// so that all controllers will not send list requests simultaneously.
318+
//
319+
// This applies to all controllers.
320+
//
321+
// A period sync happens for two reasons:
322+
// 1. To insure against a bug in the controller that causes an object to not
323+
// be requeued, when it otherwise should be requeued.
324+
// 2. To insure against an unknown bug in controller-runtime, or its dependencies,
325+
// that causes an object to not be requeued, when it otherwise should be
326+
// requeued, or to be removed from the queue, when it otherwise should not
327+
// be removed.
328+
//
329+
// If you want
330+
// 1. to insure against missed watch events, or
331+
// 2. to poll services that cannot be watched,
332+
// then we recommend that, instead of changing the default period, the
333+
// controller requeue, with a constant duration `t`, whenever the controller
334+
// is "done" with an object, and would otherwise not requeue it, i.e., we
335+
// recommend the `Reconcile` function return `reconcile.Result{RequeueAfter: t}`,
336+
// instead of `reconcile.Result{}`.
337+
//
338+
// SyncPeriod will locally trigger an artificial Update event with the same
339+
// object in both ObjectOld and ObjectNew for everything that is in the
340+
// cache.
341+
//
342+
// Predicates or Handlers that expect ObjectOld and ObjectNew to be different
343+
// (such as GenerationChangedPredicate) will filter out this event, preventing
344+
// it from triggering a reconciliation.
345+
// SyncPeriod does not sync between the local cache and the server.
346+
SyncPeriod *time.Duration
311347
}
312348

313349
// Config describes all potential options for a given watch.
@@ -343,6 +379,42 @@ type Config struct {
343379
//
344380
// Defaults to true.
345381
EnableWatchBookmarks *bool
382+
383+
// SyncPeriod determines the minimum frequency at which watched resources are
384+
// reconciled. A lower period will correct entropy more quickly, but reduce
385+
// responsiveness to change if there are many watched resources. Change this
386+
// value only if you know what you are doing. Defaults to 10 hours if unset.
387+
// there will a 10 percent jitter between the SyncPeriod of all controllers
388+
// so that all controllers will not send list requests simultaneously.
389+
//
390+
// This applies to all controllers.
391+
//
392+
// A period sync happens for two reasons:
393+
// 1. To insure against a bug in the controller that causes an object to not
394+
// be requeued, when it otherwise should be requeued.
395+
// 2. To insure against an unknown bug in controller-runtime, or its dependencies,
396+
// that causes an object to not be requeued, when it otherwise should be
397+
// requeued, or to be removed from the queue, when it otherwise should not
398+
// be removed.
399+
//
400+
// If you want
401+
// 1. to insure against missed watch events, or
402+
// 2. to poll services that cannot be watched,
403+
// then we recommend that, instead of changing the default period, the
404+
// controller requeue, with a constant duration `t`, whenever the controller
405+
// is "done" with an object, and would otherwise not requeue it, i.e., we
406+
// recommend the `Reconcile` function return `reconcile.Result{RequeueAfter: t}`,
407+
// instead of `reconcile.Result{}`.
408+
//
409+
// SyncPeriod will locally trigger an artificial Update event with the same
410+
// object in both ObjectOld and ObjectNew for everything that is in the
411+
// cache.
412+
//
413+
// Predicates or Handlers that expect ObjectOld and ObjectNew to be different
414+
// (such as GenerationChangedPredicate) will filter out this event, preventing
415+
// it from triggering a reconciliation.
416+
// SyncPeriod does not sync between the local cache and the server.
417+
SyncPeriod *time.Duration
346418
}
347419

348420
// NewCacheFunc - Function for creating a new cache from the options and a rest config.
@@ -413,6 +485,7 @@ func optionDefaultsToConfig(opts *Options) Config {
413485
Transform: opts.DefaultTransform,
414486
UnsafeDisableDeepCopy: opts.DefaultUnsafeDisableDeepCopy,
415487
EnableWatchBookmarks: opts.DefaultEnableWatchBookmarks,
488+
SyncPeriod: opts.SyncPeriod,
416489
}
417490
}
418491

@@ -423,6 +496,7 @@ func byObjectToConfig(byObject ByObject) Config {
423496
Transform: byObject.Transform,
424497
UnsafeDisableDeepCopy: byObject.UnsafeDisableDeepCopy,
425498
EnableWatchBookmarks: byObject.EnableWatchBookmarks,
499+
SyncPeriod: byObject.SyncPeriod,
426500
}
427501
}
428502

@@ -436,7 +510,7 @@ func newCache(restConfig *rest.Config, opts Options) newCacheFunc {
436510
HTTPClient: opts.HTTPClient,
437511
Scheme: opts.Scheme,
438512
Mapper: opts.Mapper,
439-
ResyncPeriod: *opts.SyncPeriod,
513+
ResyncPeriod: ptr.Deref(config.SyncPeriod, defaultSyncPeriod),
440514
Namespace: namespace,
441515
Selector: internal.Selector{
442516
Label: config.LabelSelector,
@@ -534,6 +608,7 @@ func defaultOpts(config *rest.Config, opts Options) (Options, error) {
534608
byObject.Transform = defaultedConfig.Transform
535609
byObject.UnsafeDisableDeepCopy = defaultedConfig.UnsafeDisableDeepCopy
536610
byObject.EnableWatchBookmarks = defaultedConfig.EnableWatchBookmarks
611+
byObject.SyncPeriod = defaultedConfig.SyncPeriod
537612
}
538613

539614
opts.ByObject[obj] = byObject
@@ -555,10 +630,6 @@ func defaultOpts(config *rest.Config, opts Options) (Options, error) {
555630
opts.DefaultNamespaces[namespace] = cfg
556631
}
557632

558-
// Default the resync period to 10 hours if unset
559-
if opts.SyncPeriod == nil {
560-
opts.SyncPeriod = &defaultSyncPeriod
561-
}
562633
return opts, nil
563634
}
564635

@@ -578,6 +649,9 @@ func defaultConfig(toDefault, defaultFrom Config) Config {
578649
if toDefault.EnableWatchBookmarks == nil {
579650
toDefault.EnableWatchBookmarks = defaultFrom.EnableWatchBookmarks
580651
}
652+
if toDefault.SyncPeriod == nil {
653+
toDefault.SyncPeriod = defaultFrom.SyncPeriod
654+
}
581655
return toDefault
582656
}
583657

pkg/cache/defaulting_test.go

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -249,6 +249,30 @@ func TestDefaultOpts(t *testing.T) {
249249
return cmp.Diff(expected, o.ByObject[pod].EnableWatchBookmarks)
250250
},
251251
},
252+
{
253+
name: "ByObject.SyncPeriod gets defaulted from SyncPeriod",
254+
in: Options{
255+
ByObject: map[client.Object]ByObject{pod: {}},
256+
SyncPeriod: ptr.To(5 * time.Minute),
257+
},
258+
259+
verification: func(o Options) string {
260+
expected := ptr.To(5 * time.Minute)
261+
return cmp.Diff(expected, o.ByObject[pod].SyncPeriod)
262+
},
263+
},
264+
{
265+
name: "ByObject.SyncPeriod doesn't get defaulted when set",
266+
in: Options{
267+
ByObject: map[client.Object]ByObject{pod: {SyncPeriod: ptr.To(1 * time.Minute)}},
268+
SyncPeriod: ptr.To(5 * time.Minute),
269+
},
270+
271+
verification: func(o Options) string {
272+
expected := ptr.To(1 * time.Minute)
273+
return cmp.Diff(expected, o.ByObject[pod].SyncPeriod)
274+
},
275+
},
252276
{
253277
name: "DefaultNamespace label selector gets defaulted from DefaultLabelSelector",
254278
in: Options{

0 commit comments

Comments
 (0)