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  }