@@ -194,28 +194,36 @@ func (c *vaultClient) isTracked(id string) bool {
194
194
return ok
195
195
}
196
196
197
+ // isRunning returns true if the client is running.
198
+ func (c * vaultClient ) isRunning () bool {
199
+ c .lock .RLock ()
200
+ defer c .lock .RUnlock ()
201
+ return c .running
202
+ }
203
+
197
204
// Starts the renewal loop of vault client
198
205
func (c * vaultClient ) Start () {
206
+ c .lock .Lock ()
207
+ defer c .lock .Unlock ()
208
+
199
209
if ! c .config .IsEnabled () || c .running {
200
210
return
201
211
}
202
212
203
- c .lock .Lock ()
204
213
c .running = true
205
- c .lock .Unlock ()
206
214
207
215
go c .run ()
208
216
}
209
217
210
218
// Stops the renewal loop of vault client
211
219
func (c * vaultClient ) Stop () {
220
+ c .lock .Lock ()
221
+ defer c .lock .Unlock ()
222
+
212
223
if ! c .config .IsEnabled () || ! c .running {
213
224
return
214
225
}
215
226
216
- c .lock .Lock ()
217
- defer c .lock .Unlock ()
218
-
219
227
c .running = false
220
228
close (c .stopCh )
221
229
}
@@ -235,7 +243,7 @@ func (c *vaultClient) DeriveToken(alloc *structs.Allocation, taskNames []string)
235
243
if ! c .config .IsEnabled () {
236
244
return nil , fmt .Errorf ("vault client not enabled" )
237
245
}
238
- if ! c .running {
246
+ if ! c .isRunning () {
239
247
return nil , fmt .Errorf ("vault client is not running" )
240
248
}
241
249
@@ -421,21 +429,9 @@ func (c *vaultClient) renew(req *vaultClientRenewalRequest) error {
421
429
}
422
430
}
423
431
424
- duration := leaseDuration / 2
425
- switch {
426
- case leaseDuration < 30 :
427
- // Don't bother about introducing randomness if the
428
- // leaseDuration is too small.
429
- default :
430
- // Give a breathing space of 20 seconds
431
- min := 10
432
- max := leaseDuration - min
433
- rand .Seed (time .Now ().Unix ())
434
- duration = min + rand .Intn (max - min )
435
- }
436
-
437
432
// Determine the next renewal time
438
- next := time .Now ().Add (time .Duration (duration ) * time .Second )
433
+ renewalDuration := renewalTime (rand .Intn , leaseDuration )
434
+ next := time .Now ().Add (renewalDuration )
439
435
440
436
fatal := false
441
437
if renewalErr != nil &&
@@ -445,7 +441,7 @@ func (c *vaultClient) renew(req *vaultClientRenewalRequest) error {
445
441
strings .Contains (renewalErr .Error (), "permission denied" )) {
446
442
fatal = true
447
443
} else if renewalErr != nil {
448
- c .logger .Debug ("renewal error details" , "req.increment" , req .increment , "lease_duration" , leaseDuration , "duration " , duration )
444
+ c .logger .Debug ("renewal error details" , "req.increment" , req .increment , "lease_duration" , leaseDuration , "renewal_duration " , renewalDuration )
449
445
c .logger .Error ("error during renewal of lease or token failed due to a non-fatal error; retrying" ,
450
446
"error" , renewalErr , "period" , next )
451
447
}
@@ -517,7 +513,7 @@ func (c *vaultClient) run() {
517
513
}
518
514
519
515
var renewalCh <- chan time.Time
520
- for c .config .IsEnabled () && c .running {
516
+ for c .config .IsEnabled () && c .isRunning () {
521
517
// Fetches the candidate for next renewal
522
518
renewalReq , renewalTime := c .nextRenewal ()
523
519
if renewalTime .IsZero () {
@@ -728,3 +724,31 @@ func (h *vaultDataHeapImp) Pop() interface{} {
728
724
* h = old [0 : n - 1 ]
729
725
return entry
730
726
}
727
+
728
+ // randIntn is the function in math/rand needed by renewalTime. A type is used
729
+ // to ease deterministic testing.
730
+ type randIntn func (int ) int
731
+
732
+ // renewalTime returns when a token should be renewed given its leaseDuration
733
+ // and a randomizer to provide jitter.
734
+ //
735
+ // Leases < 1m will be not jitter.
736
+ func renewalTime (dice randIntn , leaseDuration int ) time.Duration {
737
+ // Start trying to renew at half the lease duration to allow ample time
738
+ // for latency and retries.
739
+ renew := leaseDuration / 2
740
+
741
+ // Don't bother about introducing randomness if the
742
+ // leaseDuration is too small.
743
+ const cutoff = 30
744
+ if renew < cutoff {
745
+ return time .Duration (renew ) * time .Second
746
+ }
747
+
748
+ // jitter is the amount +/- to vary the renewal time
749
+ const jitter = 10
750
+ min := renew - jitter
751
+ renew = min + dice (jitter * 2 )
752
+
753
+ return time .Duration (renew ) * time .Second
754
+ }
0 commit comments