Skip to content

Commit fac7581

Browse files
committed
feedback: leasecandidate clients
1 parent 68226b0 commit fac7581

File tree

9 files changed

+64
-82
lines changed

9 files changed

+64
-82
lines changed

cmd/kube-controller-manager/app/controllermanager.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -293,19 +293,23 @@ func Run(ctx context.Context, c *config.CompletedConfig) error {
293293
}
294294

295295
if utilfeature.DefaultFeatureGate.Enabled(kubefeatures.CoordinatedLeaderElection) {
296-
ver, err := semver.ParseTolerant(version.Get().String())
296+
binaryVersion, err := semver.ParseTolerant(utilversion.DefaultComponentGlobalsRegistry.EffectiveVersionFor(utilversion.DefaultKubeComponent).BinaryVersion().String())
297+
if err != nil {
298+
return err
299+
}
300+
emulationVersion, err := semver.ParseTolerant(utilversion.DefaultComponentGlobalsRegistry.EffectiveVersionFor(utilversion.DefaultKubeComponent).EmulationVersion().String())
297301
if err != nil {
298302
return err
299303
}
300304

301305
// Start lease candidate controller for coordinated leader election
302306
leaseCandidate, waitForSync, err := leaderelection.NewCandidate(
303307
c.Client,
304-
id,
305308
"kube-system",
309+
id,
306310
"kube-controller-manager",
307-
ver.FinalizeVersion(),
308-
ver.FinalizeVersion(), // TODO(Jefftree): Use compatibility version when it's available
311+
binaryVersion.FinalizeVersion(),
312+
emulationVersion.FinalizeVersion(),
309313
[]coordinationv1.CoordinatedLeaseStrategy{coordinationv1.OldestEmulationVersion},
310314
)
311315
if err != nil {

cmd/kube-scheduler/app/server.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,8 @@ func Run(ctx context.Context, cc *schedulerserverconfig.CompletedConfig, sched *
223223
// Start lease candidate controller for coordinated leader election
224224
leaseCandidate, waitForSync, err := leaderelection.NewCandidate(
225225
cc.Client,
226-
cc.LeaderElection.Lock.Identity(),
227226
metav1.NamespaceSystem,
227+
cc.LeaderElection.Lock.Identity(),
228228
"kube-scheduler",
229229
binaryVersion.FinalizeVersion(),
230230
emulationVersion.FinalizeVersion(),

pkg/controlplane/controller/leaderelection/election.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -113,7 +113,7 @@ func pickBestStrategy(candidates []*v1alpha1.LeaseCandidate) (v1.CoordinatedLeas
113113

114114
sorted := topologicalSortWithOneRoot(graph)
115115
if sorted == nil {
116-
return nilStrategy, fmt.Errorf("Invalid strategy")
116+
return nilStrategy, fmt.Errorf("invalid strategy")
117117
}
118118

119119
return sorted[0], nil

pkg/controlplane/controller/leaderelection/leaderelection_controller.go

Lines changed: 33 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -40,11 +40,11 @@ import (
4040
)
4141

4242
const (
43-
controllerName = "leader-election-controller"
44-
ElectedByAnnotationName = "coordination.k8s.io/elected-by" // Value should be set to controllerName
43+
controllerName = "leader-election-controller"
4544

4645
// Requeue interval is the interval at which a Lease is requeued to verify that it is being renewed properly.
47-
requeueInterval = 5 * time.Second
46+
defaultRequeueInterval = 5 * time.Second
47+
noRequeue = 0
4848
defaultLeaseDurationSeconds int32 = 5
4949

5050
electionDuration = 5 * time.Second
@@ -158,10 +158,10 @@ func (c *Controller) processNextElectionItem(ctx context.Context) bool {
158158
return false
159159
}
160160

161-
completed, err := c.reconcileElectionStep(ctx, key)
161+
intervalForRequeue, err := c.reconcileElectionStep(ctx, key)
162162
utilruntime.HandleError(err)
163-
if completed {
164-
defer c.queue.AddAfter(key, requeueInterval)
163+
if intervalForRequeue != noRequeue {
164+
defer c.queue.AddAfter(key, intervalForRequeue)
165165
}
166166
c.queue.Done(key)
167167
return true
@@ -237,22 +237,25 @@ func (c *Controller) electionNeeded(candidates []*v1alpha1.LeaseCandidate, lease
237237
// PingTime + electionDuration > time.Now: We just asked all candidates to ack and are still waiting for response
238238
// PingTime + electionDuration < time.Now: Candidate has not responded within the appropriate PingTime. Continue the election.
239239
// RenewTime + 5 seconds > time.Now: All candidates acked in the last 5 seconds, continue the election.
240-
func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.NamespacedName) (requeue bool, err error) {
240+
func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.NamespacedName) (requeue time.Duration, err error) {
241241
now := time.Now()
242242

243243
candidates, err := c.listAdmissableCandidates(leaseNN)
244244
if err != nil {
245-
return true, err
245+
return defaultRequeueInterval, err
246246
} else if len(candidates) == 0 {
247-
return false, nil
247+
return noRequeue, nil
248248
}
249-
klog.V(4).Infof("reconcileElectionStep %q %q, candidates: %d", leaseNN.Namespace, leaseNN.Name, len(candidates))
249+
klog.V(4).Infof("reconcileElectionStep %s, candidates: %d", leaseNN, len(candidates))
250250

251251
// Check if an election is really needed by looking at the current lease
252252
// and set of candidates
253253
needElection, err := c.electionNeeded(candidates, leaseNN)
254-
if !needElection || err != nil {
255-
return needElection, err
254+
if !needElection {
255+
return noRequeue, err
256+
}
257+
if err != nil {
258+
return defaultRequeueInterval, err
256259
}
257260

258261
fastTrackElection := false
@@ -263,15 +266,15 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
263266
if candidate.Spec.PingTime != nil {
264267
if candidate.Spec.PingTime.Add(electionDuration).After(now) {
265268
// continue waiting for the election to timeout
266-
return false, nil
269+
return noRequeue, nil
267270
} else {
268271
// election timed out without ack. Clear and start election.
269272
fastTrackElection = true
270273
clone := candidate.DeepCopy()
271274
clone.Spec.PingTime = nil
272275
_, err := c.leaseCandidateClient.LeaseCandidates(clone.Namespace).Update(ctx, clone, metav1.UpdateOptions{})
273276
if err != nil {
274-
return false, err
277+
return noRequeue, err
275278
}
276279
break
277280
}
@@ -294,10 +297,10 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
294297
clone.Spec.PingTime = &metav1.MicroTime{Time: time.Now()}
295298
_, err := c.leaseCandidateClient.LeaseCandidates(clone.Namespace).Update(ctx, clone, metav1.UpdateOptions{})
296299
if err != nil {
297-
return false, err
300+
return noRequeue, err
298301
}
299302
}
300-
return true, nil
303+
return defaultRequeueInterval, nil
301304
}
302305
}
303306

@@ -308,22 +311,22 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
308311
}
309312
}
310313
if len(ackedCandidates) == 0 {
311-
return false, fmt.Errorf("no available candidates")
314+
return noRequeue, fmt.Errorf("no available candidates")
312315
}
313316

314317
strategy, err := pickBestStrategy(ackedCandidates)
315318
if err != nil {
316-
return false, err
319+
return noRequeue, err
317320
}
318321

319322
if strategy != v1.OldestEmulationVersion {
320323
klog.V(2).Infof("strategy %s is not recognized by CLE.", strategy)
321-
return false, nil
324+
return noRequeue, nil
322325
}
323326
electee := pickBestLeaderOldestEmulationVersion(ackedCandidates)
324327

325328
if electee == nil {
326-
return false, fmt.Errorf("should not happen, could not find suitable electee")
329+
return noRequeue, fmt.Errorf("should not happen, could not find suitable electee")
327330
}
328331

329332
electeeName := electee.Name
@@ -332,9 +335,6 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
332335
ObjectMeta: metav1.ObjectMeta{
333336
Namespace: leaseNN.Namespace,
334337
Name: leaseNN.Name,
335-
Annotations: map[string]string{
336-
ElectedByAnnotationName: controllerName,
337-
},
338338
},
339339
Spec: v1.LeaseSpec{
340340
HolderIdentity: &electeeName,
@@ -346,50 +346,47 @@ func (c *Controller) reconcileElectionStep(ctx context.Context, leaseNN types.Na
346346
_, err = c.leaseClient.Leases(leaseNN.Namespace).Create(ctx, leaderLease, metav1.CreateOptions{})
347347
// If the create was successful, then we can return here.
348348
if err == nil {
349-
klog.Infof("Created lease %q %q for %q", leaseNN.Namespace, leaseNN.Name, electee.Name)
350-
return true, nil
349+
klog.Infof("Created lease %s for %q", leaseNN, electee.Name)
350+
return defaultRequeueInterval, nil
351351
}
352352

353353
// If there was an error, return
354354
if !apierrors.IsAlreadyExists(err) {
355-
return false, err
355+
return noRequeue, err
356356
}
357357

358358
existingLease, err := c.leaseClient.Leases(leaseNN.Namespace).Get(ctx, leaseNN.Name, metav1.GetOptions{})
359359
if err != nil {
360-
return false, err
360+
return noRequeue, err
361361
}
362362
leaseClone := existingLease.DeepCopy()
363363

364364
// Update the Lease if it either does not have a holder or is expired
365365
isExpired := isLeaseExpired(existingLease)
366366
if leaseClone.Spec.HolderIdentity == nil || *leaseClone.Spec.HolderIdentity == "" || (isExpired && *leaseClone.Spec.HolderIdentity != electeeName) {
367-
klog.Infof("lease %q %q is expired, resetting it and setting holder to %q", leaseNN.Namespace, leaseNN.Name, electee.Name)
367+
klog.Infof("lease %s is expired, resetting it and setting holder to %q", leaseNN, electee.Name)
368368
leaseClone.Spec.Strategy = &strategy
369369
leaseClone.Spec.PreferredHolder = nil
370-
if leaseClone.ObjectMeta.Annotations == nil {
371-
leaseClone.ObjectMeta.Annotations = make(map[string]string)
372-
}
373-
leaseClone.ObjectMeta.Annotations[ElectedByAnnotationName] = controllerName
374370
leaseClone.Spec.HolderIdentity = &electeeName
375371

376372
leaseClone.Spec.RenewTime = &metav1.MicroTime{Time: time.Now()}
377373
leaseClone.Spec.LeaseDurationSeconds = ptr.To(defaultLeaseDurationSeconds)
378374
leaseClone.Spec.AcquireTime = nil
379375
_, err = c.leaseClient.Leases(leaseNN.Namespace).Update(ctx, leaseClone, metav1.UpdateOptions{})
380376
if err != nil {
381-
return false, err
377+
return time.Until(leaseClone.Spec.RenewTime.Time), err
382378
}
383379
} else if leaseClone.Spec.HolderIdentity != nil && *leaseClone.Spec.HolderIdentity != electeeName {
384-
klog.Infof("lease %q %q already exists for holder %q but should be held by %q, marking preferredHolder", leaseNN.Namespace, leaseNN.Name, *leaseClone.Spec.HolderIdentity, electee.Name)
380+
klog.Infof("lease %s already exists for holder %q but should be held by %q, marking preferredHolder", leaseNN, *leaseClone.Spec.HolderIdentity, electee.Name)
385381
leaseClone.Spec.PreferredHolder = &electeeName
386382
leaseClone.Spec.Strategy = &strategy
387383
_, err = c.leaseClient.Leases(leaseNN.Namespace).Update(ctx, leaseClone, metav1.UpdateOptions{})
388384
if err != nil {
389-
return false, err
385+
return noRequeue, err
390386
}
387+
return time.Until(leaseClone.Spec.RenewTime.Time), nil
391388
}
392-
return true, nil
389+
return defaultRequeueInterval, nil
393390
}
394391

395392
func (c *Controller) listAdmissableCandidates(leaseNN types.NamespacedName) ([]*v1alpha1.LeaseCandidate, error) {

pkg/controlplane/controller/leaderelection/leaderelection_controller_test.go

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,6 @@ func TestReconcileElectionStep(t *testing.T) {
123123
ObjectMeta: metav1.ObjectMeta{
124124
Namespace: "default",
125125
Name: "component-A",
126-
Annotations: map[string]string{
127-
ElectedByAnnotationName: controllerName,
128-
},
129126
},
130127
Spec: v1.LeaseSpec{
131128
HolderIdentity: ptr.To("component-identity-1"),
@@ -197,9 +194,6 @@ func TestReconcileElectionStep(t *testing.T) {
197194
ObjectMeta: metav1.ObjectMeta{
198195
Namespace: "default",
199196
Name: "component-A",
200-
Annotations: map[string]string{
201-
ElectedByAnnotationName: controllerName,
202-
},
203197
},
204198
Spec: v1.LeaseSpec{
205199
HolderIdentity: ptr.To("component-identity-expired"),
@@ -320,7 +314,7 @@ func TestReconcileElectionStep(t *testing.T) {
320314
cache.WaitForCacheSync(ctx.Done(), controller.leaseCandidateInformer.Informer().HasSynced)
321315
requeue, err := controller.reconcileElectionStep(ctx, tc.leaseNN)
322316

323-
if requeue != tc.expectedRequeue {
317+
if (requeue != 0) != tc.expectedRequeue {
324318
t.Errorf("reconcileElectionStep() requeue = %v, want %v", requeue, tc.expectedRequeue)
325319
}
326320
if tc.expectedError && err == nil {
@@ -404,9 +398,6 @@ func TestController(t *testing.T) {
404398
ObjectMeta: metav1.ObjectMeta{
405399
Namespace: "kube-system",
406400
Name: "component-A",
407-
Annotations: map[string]string{
408-
ElectedByAnnotationName: controllerName,
409-
},
410401
},
411402
Spec: v1.LeaseSpec{
412403
HolderIdentity: ptr.To("component-identity-1"),
@@ -463,9 +454,6 @@ func TestController(t *testing.T) {
463454
ObjectMeta: metav1.ObjectMeta{
464455
Namespace: "kube-system",
465456
Name: "component-A",
466-
Annotations: map[string]string{
467-
ElectedByAnnotationName: controllerName,
468-
},
469457
},
470458
Spec: v1.LeaseSpec{
471459
HolderIdentity: ptr.To("component-identity-1"),
@@ -482,9 +470,6 @@ func TestController(t *testing.T) {
482470
ObjectMeta: metav1.ObjectMeta{
483471
Namespace: "kube-system",
484472
Name: "component-A",
485-
Annotations: map[string]string{
486-
ElectedByAnnotationName: controllerName,
487-
},
488473
},
489474
Spec: v1alpha1.LeaseCandidateSpec{},
490475
},
@@ -510,9 +495,6 @@ func TestController(t *testing.T) {
510495
ObjectMeta: metav1.ObjectMeta{
511496
Namespace: "kube-system",
512497
Name: "component-A",
513-
Annotations: map[string]string{
514-
ElectedByAnnotationName: controllerName,
515-
},
516498
},
517499
Spec: v1.LeaseSpec{
518500
HolderIdentity: ptr.To("component-identity-1"),
@@ -529,9 +511,6 @@ func TestController(t *testing.T) {
529511
ObjectMeta: metav1.ObjectMeta{
530512
Namespace: "kube-system",
531513
Name: "component-A",
532-
Annotations: map[string]string{
533-
ElectedByAnnotationName: controllerName,
534-
},
535514
},
536515
Spec: v1alpha1.LeaseCandidateSpec{},
537516
},
@@ -567,9 +546,6 @@ func TestController(t *testing.T) {
567546
ObjectMeta: metav1.ObjectMeta{
568547
Namespace: "kube-system",
569548
Name: "component-A",
570-
Annotations: map[string]string{
571-
ElectedByAnnotationName: controllerName,
572-
},
573549
},
574550
Spec: v1.LeaseSpec{
575551
HolderIdentity: ptr.To("component-identity-2"),

staging/src/k8s.io/client-go/tools/leaderelection/leaderelection.go

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ type LeaderElectionConfig struct {
161161
Name string
162162

163163
// Coordinated will use the Coordinated Leader Election feature
164+
// WARNING: Coordinated leader election is ALPHA.
164165
Coordinated bool
165166
}
166167

@@ -293,6 +294,7 @@ func (le *LeaderElector) renew(ctx context.Context) {
293294
return
294295
}
295296
le.metrics.leaderOff(le.config.Name)
297+
klog.Infof("failed to renew lease %v: %v", desc, err)
296298
cancel()
297299
}, le.config.RetryPeriod, ctx.Done())
298300

@@ -354,23 +356,23 @@ func (le *LeaderElector) tryCoordinatedRenew(ctx context.Context) bool {
354356

355357
le.observedRawRecord = oldLeaderElectionRawRecord
356358
}
357-
hasExpired := le.observedTime.Add(time.Second * time.Duration(oldLeaderElectionRecord.LeaseDurationSeconds)).Before(now.Time)
358359

360+
hasExpired := le.observedTime.Add(time.Second * time.Duration(oldLeaderElectionRecord.LeaseDurationSeconds)).Before(now.Time)
359361
if hasExpired {
360362
klog.Infof("lock has expired: %v", le.config.Lock.Describe())
361363
return false
362364
}
363365

364366
if !le.IsLeader() {
365-
klog.V(4).Infof("lock is held by %v and has not yet expired: %v", oldLeaderElectionRecord.HolderIdentity, le.config.Lock.Describe())
367+
klog.V(6).Infof("lock is held by %v and has not yet expired: %v", oldLeaderElectionRecord.HolderIdentity, le.config.Lock.Describe())
366368
return false
367369
}
368370

369371
// 2b. If the lease has been marked as "end of term", don't renew it
370372
if le.IsLeader() && oldLeaderElectionRecord.PreferredHolder != "" {
371373
klog.V(4).Infof("lock is marked as 'end of term': %v", le.config.Lock.Describe())
372374
// TODO: Instead of letting lease expire, the holder may deleted it directly
373-
// This will not be compatible with all controllers, so it needs to be opt-in behavior..
375+
// This will not be compatible with all controllers, so it needs to be opt-in behavior.
374376
// We must ensure all code guarded by this lease has successfully completed
375377
// prior to releasing or there may be two processes
376378
// simultaneously acting on the critical path.

0 commit comments

Comments
 (0)