github.com/cilium/cilium@v1.16.2/operator/identitygc/heartbeat.go (about) 1 // SPDX-License-Identifier: Apache-2.0 2 // Copyright Authors of Cilium 3 4 package identitygc 5 6 import ( 7 "time" 8 9 "github.com/cilium/cilium/pkg/lock" 10 "github.com/cilium/cilium/pkg/logging" 11 "github.com/cilium/cilium/pkg/logging/logfields" 12 ) 13 14 var ( 15 log = logging.DefaultLogger.WithField(logfields.LogSubsys, "identity-heartbeat") 16 ) 17 18 // heartbeatStore keeps track of the heartbeat of identities 19 type heartbeatStore struct { 20 mutex lock.RWMutex 21 lastLifesign map[string]time.Time 22 firstRun time.Time 23 timeout time.Duration 24 } 25 26 // newHeartbeatStore returns a new identity heartbeat store 27 func newHeartbeatStore(timeout time.Duration) *heartbeatStore { 28 i := &heartbeatStore{ 29 timeout: timeout, 30 lastLifesign: map[string]time.Time{}, 31 firstRun: time.Now(), 32 } 33 return i 34 } 35 36 // markAlive marks an identity as alive 37 func (i *heartbeatStore) markAlive(identity string, t time.Time) { 38 log.WithField(logfields.Identity, identity).Debug("Marking identity alive") 39 i.mutex.Lock() 40 i.lastLifesign[identity] = t 41 i.mutex.Unlock() 42 } 43 44 // isAlive returns true if the identity is still alive 45 func (i *heartbeatStore) isAlive(identity string) bool { 46 i.mutex.RLock() 47 defer i.mutex.RUnlock() 48 49 lifesign, ok := i.lastLifesign[identity] 50 if ok { 51 // A lifesign has been recorded, check if the lifesign is older 52 // than the stale period 53 if time.Since(lifesign) < i.timeout { 54 return true 55 } 56 } else { 57 // No lifesign has ever been recorded. If the operator has not 58 // been up for longer than the stale period, then the identity 59 // is still considered alive 60 log.Debugf("No lifesign exists %s > %s", time.Since(i.firstRun), i.timeout) 61 if time.Since(i.firstRun) < i.timeout { 62 return true 63 } 64 } 65 66 return false 67 } 68 69 // delete deletes an identity from the store 70 func (i *heartbeatStore) delete(identity string) { 71 log.WithField(logfields.Identity, identity).Debug("Deleting identity in heartbeat lifesign table") 72 i.mutex.Lock() 73 defer i.mutex.Unlock() 74 delete(i.lastLifesign, identity) 75 } 76 77 // gc removes all lifesign entries which have exceeded the heartbeat by a large 78 // amount. This happens when the CiliumIdentity is deleted before the 79 // CiliumEndpoint that refers to it. In that case, the lifesign entry will 80 // continue to exist. Remove it once has not been updated for a long time. 81 func (i *heartbeatStore) gc() { 82 i.mutex.Lock() 83 defer i.mutex.Unlock() 84 85 for identity, lifesign := range i.lastLifesign { 86 if time.Since(lifesign) > 10*i.timeout { 87 log.WithField(logfields.Identity, identity).Debug("Removing unused heartbeat entry") 88 delete(i.lastLifesign, identity) 89 } 90 } 91 }