/
kvstore_watchdog.go
88 lines (80 loc) · 2.66 KB
/
kvstore_watchdog.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
// Copyright 2020 Authors of Cilium
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package main
import (
"strings"
"time"
"github.com/cilium/cilium/pkg/allocator"
"github.com/cilium/cilium/pkg/defaults"
"github.com/cilium/cilium/pkg/identity/cache"
"github.com/cilium/cilium/pkg/kvstore"
kvstoreallocator "github.com/cilium/cilium/pkg/kvstore/allocator"
)
// keyPathFromLockPath returns the path of the given key that contains a lease
// prefixed to its path.
func keyPathFromLockPath(k string) string {
// vendor/go.etcd.io/etcd/clientv3/concurrency/mutex.go:L46
i := strings.LastIndexByte(k, '/')
if i >= 0 {
return k[:i]
}
return k
}
// getOldestLeases returns the value that has the smaller revision for each
// 'path'. A 'path' shares the same common prefix for different locks.
func getOldestLeases(lockPaths map[string]kvstore.Value) map[string]kvstore.Value {
type LockValue struct {
kvstore.Value
keyPath string
}
oldestPaths := map[string]LockValue{}
for lockPath, v := range lockPaths {
keyPath := keyPathFromLockPath(lockPath)
oldestKeyPath, ok := oldestPaths[keyPath]
if !ok || v.ModRevision < oldestKeyPath.ModRevision {
// Store the oldest common path
oldestPaths[keyPath] = LockValue{
keyPath: lockPath,
Value: v,
}
}
}
oldestLeases := map[string]kvstore.Value{}
for _, v := range oldestPaths {
// Retrieve the oldest lock path
oldestLeases[v.keyPath] = v.Value
}
return oldestLeases
}
func startKvstoreWatchdog() {
log.Infof("Starting kvstore watchdog with %s interval...", defaults.LockLeaseTTL)
backend, err := kvstoreallocator.NewKVStoreBackend(cache.IdentitiesPath, "", nil, kvstore.Client())
if err != nil {
log.WithError(err).Fatal("Unable to initialize kvstore backend for identity garbage collection")
}
a := allocator.NewAllocatorForGC(backend)
keysToDelete := map[string]kvstore.Value{}
go func() {
for {
keysToDelete = getOldestLeases(keysToDelete)
keysToDelete2, err := a.RunLocksGC(keysToDelete)
if err != nil {
log.WithError(err).Warning("Unable to run security identity garbage collector")
} else {
keysToDelete = keysToDelete2
}
<-time.After(defaults.LockLeaseTTL)
}
}()
}