mirror of
https://github.com/kubernetes-sigs/prometheus-adapter.git
synced 2026-04-07 10:17:51 +00:00
Update custom-metrics-apiserver and metrics-server
This commit is contained in:
parent
4c673534f2
commit
b480e45a67
915 changed files with 63694 additions and 106514 deletions
8
vendor/k8s.io/apiserver/pkg/storage/cacher/cacher.go
generated
vendored
8
vendor/k8s.io/apiserver/pkg/storage/cacher/cacher.go
generated
vendored
|
|
@ -100,6 +100,10 @@ type Config struct {
|
|||
// needs to process an incoming event.
|
||||
IndexerFuncs storage.IndexerFuncs
|
||||
|
||||
// Indexers is used to accelerate the list operation, falls back to regular list
|
||||
// operation if no indexer found.
|
||||
Indexers *cache.Indexers
|
||||
|
||||
// NewFunc is a function that creates new empty object storing a object of type Type.
|
||||
NewFunc func() runtime.Object
|
||||
|
||||
|
|
@ -367,7 +371,7 @@ func NewCacherFromConfig(config Config) (*Cacher, error) {
|
|||
}
|
||||
|
||||
watchCache := newWatchCache(
|
||||
config.CacheCapacity, config.KeyFunc, cacher.processEvent, config.GetAttrsFunc, config.Versioner)
|
||||
config.CacheCapacity, config.KeyFunc, cacher.processEvent, config.GetAttrsFunc, config.Versioner, config.Indexers)
|
||||
listerWatcher := NewCacherListerWatcher(config.Storage, config.ResourcePrefix, config.NewListFunc)
|
||||
reflectorName := "storage/cacher.go:" + config.ResourcePrefix
|
||||
|
||||
|
|
@ -701,7 +705,7 @@ func (c *Cacher) List(ctx context.Context, key string, resourceVersion string, p
|
|||
}
|
||||
filter := filterWithAttrsFunction(key, pred)
|
||||
|
||||
objs, readResourceVersion, err := c.watchCache.WaitUntilFreshAndList(listRV, trace)
|
||||
objs, readResourceVersion, err := c.watchCache.WaitUntilFreshAndList(listRV, pred.MatcherIndex(), trace)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
48
vendor/k8s.io/apiserver/pkg/storage/cacher/watch_cache.go
generated
vendored
48
vendor/k8s.io/apiserver/pkg/storage/cacher/watch_cache.go
generated
vendored
|
|
@ -82,6 +82,35 @@ func storeElementKey(obj interface{}) (string, error) {
|
|||
return elem.Key, nil
|
||||
}
|
||||
|
||||
func storeElementObject(obj interface{}) (runtime.Object, error) {
|
||||
elem, ok := obj.(*storeElement)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("not a storeElement: %v", obj)
|
||||
}
|
||||
return elem.Object, nil
|
||||
}
|
||||
|
||||
func storeElementIndexFunc(objIndexFunc cache.IndexFunc) cache.IndexFunc {
|
||||
return func(obj interface{}) (strings []string, e error) {
|
||||
seo, err := storeElementObject(obj)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return objIndexFunc(seo)
|
||||
}
|
||||
}
|
||||
|
||||
func storeElementIndexers(indexers *cache.Indexers) cache.Indexers {
|
||||
if indexers == nil {
|
||||
return cache.Indexers{}
|
||||
}
|
||||
ret := cache.Indexers{}
|
||||
for indexName, indexFunc := range *indexers {
|
||||
ret[indexName] = storeElementIndexFunc(indexFunc)
|
||||
}
|
||||
return ret
|
||||
}
|
||||
|
||||
// watchCache implements a Store interface.
|
||||
// However, it depends on the elements implementing runtime.Object interface.
|
||||
//
|
||||
|
|
@ -116,7 +145,7 @@ type watchCache struct {
|
|||
// history" i.e. from the moment just after the newest cached watched event.
|
||||
// It is necessary to effectively allow clients to start watching at now.
|
||||
// NOTE: We assume that <store> is thread-safe.
|
||||
store cache.Store
|
||||
store cache.Indexer
|
||||
|
||||
// ResourceVersion up to which the watchCache is propagated.
|
||||
resourceVersion uint64
|
||||
|
|
@ -143,7 +172,8 @@ func newWatchCache(
|
|||
keyFunc func(runtime.Object) (string, error),
|
||||
eventHandler func(*watchCacheEvent),
|
||||
getAttrsFunc func(runtime.Object) (labels.Set, fields.Set, error),
|
||||
versioner storage.Versioner) *watchCache {
|
||||
versioner storage.Versioner,
|
||||
indexers *cache.Indexers) *watchCache {
|
||||
wc := &watchCache{
|
||||
capacity: capacity,
|
||||
keyFunc: keyFunc,
|
||||
|
|
@ -151,7 +181,7 @@ func newWatchCache(
|
|||
cache: make([]*watchCacheEvent, capacity),
|
||||
startIndex: 0,
|
||||
endIndex: 0,
|
||||
store: cache.NewStore(storeElementKey),
|
||||
store: cache.NewIndexer(storeElementKey, storeElementIndexers(indexers)),
|
||||
resourceVersion: 0,
|
||||
listResourceVersion: 0,
|
||||
eventHandler: eventHandler,
|
||||
|
|
@ -319,12 +349,22 @@ func (w *watchCache) waitUntilFreshAndBlock(resourceVersion uint64, trace *utilt
|
|||
}
|
||||
|
||||
// WaitUntilFreshAndList returns list of pointers to <storeElement> objects.
|
||||
func (w *watchCache) WaitUntilFreshAndList(resourceVersion uint64, trace *utiltrace.Trace) ([]interface{}, uint64, error) {
|
||||
func (w *watchCache) WaitUntilFreshAndList(resourceVersion uint64, matchValues []storage.MatchValue, trace *utiltrace.Trace) ([]interface{}, uint64, error) {
|
||||
err := w.waitUntilFreshAndBlock(resourceVersion, trace)
|
||||
defer w.RUnlock()
|
||||
if err != nil {
|
||||
return nil, 0, err
|
||||
}
|
||||
|
||||
// This isn't the place where we do "final filtering" - only some "prefiltering" is happening here. So the only
|
||||
// requirement here is to NOT miss anything that should be returned. We can return as many non-matching items as we
|
||||
// want - they will be filtered out later. The fact that we return less things is only further performance improvement.
|
||||
// TODO: if multiple indexes match, return the one with the fewest items, so as to do as much filtering as possible.
|
||||
for _, matchValue := range matchValues {
|
||||
if result, err := w.store.ByIndex(matchValue.IndexName, matchValue.Value); err == nil {
|
||||
return result, w.resourceVersion, nil
|
||||
}
|
||||
}
|
||||
return w.store.List(), w.resourceVersion, nil
|
||||
}
|
||||
|
||||
|
|
|
|||
21
vendor/k8s.io/apiserver/pkg/storage/etcd3/metrics/metrics.go
generated
vendored
21
vendor/k8s.io/apiserver/pkg/storage/etcd3/metrics/metrics.go
generated
vendored
|
|
@ -49,16 +49,6 @@ var (
|
|||
},
|
||||
[]string{"resource"},
|
||||
)
|
||||
|
||||
deprecatedEtcdRequestLatenciesSummary = compbasemetrics.NewSummaryVec(
|
||||
&compbasemetrics.SummaryOpts{
|
||||
Name: "etcd_request_latencies_summary",
|
||||
Help: "Etcd request latency summary in microseconds for each operation and object type.",
|
||||
StabilityLevel: compbasemetrics.ALPHA,
|
||||
DeprecatedVersion: "1.14.0",
|
||||
},
|
||||
[]string{"operation", "type"},
|
||||
)
|
||||
)
|
||||
|
||||
var registerMetrics sync.Once
|
||||
|
|
@ -69,9 +59,6 @@ func Register() {
|
|||
registerMetrics.Do(func() {
|
||||
legacyregistry.MustRegister(etcdRequestLatency)
|
||||
legacyregistry.MustRegister(objectCounts)
|
||||
|
||||
// TODO(danielqsj): Remove the following metrics, they are deprecated
|
||||
legacyregistry.MustRegister(deprecatedEtcdRequestLatenciesSummary)
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -83,19 +70,11 @@ func UpdateObjectCount(resourcePrefix string, count int64) {
|
|||
// RecordEtcdRequestLatency sets the etcd_request_duration_seconds metrics.
|
||||
func RecordEtcdRequestLatency(verb, resource string, startTime time.Time) {
|
||||
etcdRequestLatency.WithLabelValues(verb, resource).Observe(sinceInSeconds(startTime))
|
||||
deprecatedEtcdRequestLatenciesSummary.WithLabelValues(verb, resource).Observe(sinceInMicroseconds(startTime))
|
||||
}
|
||||
|
||||
// Reset resets the etcd_request_duration_seconds metric.
|
||||
func Reset() {
|
||||
etcdRequestLatency.Reset()
|
||||
|
||||
deprecatedEtcdRequestLatenciesSummary.Reset()
|
||||
}
|
||||
|
||||
// sinceInMicroseconds gets the time since the specified start in microseconds.
|
||||
func sinceInMicroseconds(start time.Time) float64 {
|
||||
return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds())
|
||||
}
|
||||
|
||||
// sinceInSeconds gets the time since the specified start in seconds.
|
||||
|
|
|
|||
30
vendor/k8s.io/apiserver/pkg/storage/etcd3/store.go
generated
vendored
30
vendor/k8s.io/apiserver/pkg/storage/etcd3/store.go
generated
vendored
|
|
@ -32,6 +32,7 @@ import (
|
|||
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/api/meta"
|
||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||
"k8s.io/apimachinery/pkg/conversion"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
|
|
@ -394,6 +395,8 @@ func (s *store) GetToList(ctx context.Context, key string, resourceVersion strin
|
|||
return fmt.Errorf("need ptr to slice: %v", err)
|
||||
}
|
||||
|
||||
newItemFunc := getNewItemFunc(listObj, v)
|
||||
|
||||
key = path.Join(s.pathPrefix, key)
|
||||
startTime := time.Now()
|
||||
getResp, err := s.client.KV.Get(ctx, key, s.getOps...)
|
||||
|
|
@ -410,7 +413,7 @@ func (s *store) GetToList(ctx context.Context, key string, resourceVersion strin
|
|||
if err != nil {
|
||||
return storage.NewInternalError(err.Error())
|
||||
}
|
||||
if err := appendListItem(v, data, uint64(getResp.Kvs[0].ModRevision), pred, s.codec, s.versioner); err != nil {
|
||||
if err := appendListItem(v, data, uint64(getResp.Kvs[0].ModRevision), pred, s.codec, s.versioner, newItemFunc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -418,6 +421,23 @@ func (s *store) GetToList(ctx context.Context, key string, resourceVersion strin
|
|||
return s.versioner.UpdateList(listObj, uint64(getResp.Header.Revision), "", nil)
|
||||
}
|
||||
|
||||
func getNewItemFunc(listObj runtime.Object, v reflect.Value) func() runtime.Object {
|
||||
// For unstructured lists with a target group/version, preserve the group/version in the instantiated list items
|
||||
if unstructuredList, isUnstructured := listObj.(*unstructured.UnstructuredList); isUnstructured {
|
||||
if apiVersion := unstructuredList.GetAPIVersion(); len(apiVersion) > 0 {
|
||||
return func() runtime.Object {
|
||||
return &unstructured.Unstructured{Object: map[string]interface{}{"apiVersion": apiVersion}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise just instantiate an empty item
|
||||
elem := v.Type().Elem()
|
||||
return func() runtime.Object {
|
||||
return reflect.New(elem).Interface().(runtime.Object)
|
||||
}
|
||||
}
|
||||
|
||||
func (s *store) Count(key string) (int64, error) {
|
||||
key = path.Join(s.pathPrefix, key)
|
||||
startTime := time.Now()
|
||||
|
|
@ -525,6 +545,8 @@ func (s *store) List(ctx context.Context, key, resourceVersion string, pred stor
|
|||
options = append(options, clientv3.WithLimit(pred.Limit))
|
||||
}
|
||||
|
||||
newItemFunc := getNewItemFunc(listObj, v)
|
||||
|
||||
var returnedRV, continueRV int64
|
||||
var continueKey string
|
||||
switch {
|
||||
|
|
@ -609,7 +631,7 @@ func (s *store) List(ctx context.Context, key, resourceVersion string, pred stor
|
|||
return storage.NewInternalErrorf("unable to transform key %q: %v", kv.Key, err)
|
||||
}
|
||||
|
||||
if err := appendListItem(v, data, uint64(kv.ModRevision), pred, s.codec, s.versioner); err != nil {
|
||||
if err := appendListItem(v, data, uint64(kv.ModRevision), pred, s.codec, s.versioner, newItemFunc); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
|
@ -832,8 +854,8 @@ func decode(codec runtime.Codec, versioner storage.Versioner, value []byte, objP
|
|||
}
|
||||
|
||||
// appendListItem decodes and appends the object (if it passes filter) to v, which must be a slice.
|
||||
func appendListItem(v reflect.Value, data []byte, rev uint64, pred storage.SelectionPredicate, codec runtime.Codec, versioner storage.Versioner) error {
|
||||
obj, _, err := codec.Decode(data, nil, reflect.New(v.Type().Elem()).Interface().(runtime.Object))
|
||||
func appendListItem(v reflect.Value, data []byte, rev uint64, pred storage.SelectionPredicate, codec runtime.Codec, versioner storage.Versioner, newItemFunc func() runtime.Object) error {
|
||||
obj, _, err := codec.Decode(data, nil, newItemFunc())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
21
vendor/k8s.io/apiserver/pkg/storage/etcd3/watcher.go
generated
vendored
21
vendor/k8s.io/apiserver/pkg/storage/etcd3/watcher.go
generated
vendored
|
|
@ -25,7 +25,7 @@ import (
|
|||
"strings"
|
||||
"sync"
|
||||
|
||||
apierrs "k8s.io/apimachinery/pkg/api/errors"
|
||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
"k8s.io/apimachinery/pkg/runtime"
|
||||
"k8s.io/apimachinery/pkg/watch"
|
||||
"k8s.io/apiserver/pkg/storage"
|
||||
|
|
@ -191,6 +191,15 @@ func (wc *watchChan) sync() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
// logWatchChannelErr checks whether the error is about mvcc revision compaction which is regarded as warning
|
||||
func logWatchChannelErr(err error) {
|
||||
if !strings.Contains(err.Error(), "mvcc: required revision has been compacted") {
|
||||
klog.Errorf("watch chan error: %v", err)
|
||||
} else {
|
||||
klog.Warningf("watch chan error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// startWatching does:
|
||||
// - get current objects if initialRev=0; set initialRev to current rev
|
||||
// - watch on given key and send events to process.
|
||||
|
|
@ -211,14 +220,14 @@ func (wc *watchChan) startWatching(watchClosedCh chan struct{}) {
|
|||
if wres.Err() != nil {
|
||||
err := wres.Err()
|
||||
// If there is an error on server (e.g. compaction), the channel will return it before closed.
|
||||
klog.Errorf("watch chan error: %v", err)
|
||||
logWatchChannelErr(err)
|
||||
wc.sendError(err)
|
||||
return
|
||||
}
|
||||
for _, e := range wres.Events {
|
||||
parsedEvent, err := parseEvent(e)
|
||||
if err != nil {
|
||||
klog.Errorf("watch chan error: %v", err)
|
||||
logWatchChannelErr(err)
|
||||
wc.sendError(err)
|
||||
return
|
||||
}
|
||||
|
|
@ -332,10 +341,10 @@ func (wc *watchChan) transform(e *event) (res *watch.Event) {
|
|||
|
||||
func transformErrorToEvent(err error) *watch.Event {
|
||||
err = interpretWatchError(err)
|
||||
if _, ok := err.(apierrs.APIStatus); !ok {
|
||||
err = apierrs.NewInternalError(err)
|
||||
if _, ok := err.(apierrors.APIStatus); !ok {
|
||||
err = apierrors.NewInternalError(err)
|
||||
}
|
||||
status := err.(apierrs.APIStatus).Status()
|
||||
status := err.(apierrors.APIStatus).Status()
|
||||
return &watch.Event{
|
||||
Type: watch.Error,
|
||||
Object: &status,
|
||||
|
|
|
|||
8
vendor/k8s.io/apiserver/pkg/storage/interfaces.go
generated
vendored
8
vendor/k8s.io/apiserver/pkg/storage/interfaces.go
generated
vendored
|
|
@ -87,6 +87,12 @@ var Everything = SelectionPredicate{
|
|||
Field: fields.Everything(),
|
||||
}
|
||||
|
||||
// MatchValue defines a pair (<index name>, <value for that index>).
|
||||
type MatchValue struct {
|
||||
IndexName string
|
||||
Value string
|
||||
}
|
||||
|
||||
// Pass an UpdateFunc to Interface.GuaranteedUpdate to make an update
|
||||
// that is guaranteed to succeed.
|
||||
// See the comment for GuaranteedUpdate for more details.
|
||||
|
|
@ -218,7 +224,7 @@ type Interface interface {
|
|||
// err := s.GuaranteedUpdate(
|
||||
// "myKey", &MyType{}, true,
|
||||
// func(input runtime.Object, res ResponseMeta) (runtime.Object, *uint64, error) {
|
||||
// // Before each incovation of the user defined function, "input" is reset to
|
||||
// // Before each invocation of the user defined function, "input" is reset to
|
||||
// // current contents for "myKey" in database.
|
||||
// curr := input.(*MyType) // Guaranteed to succeed.
|
||||
//
|
||||
|
|
|
|||
29
vendor/k8s.io/apiserver/pkg/storage/selection_predicate.go
generated
vendored
29
vendor/k8s.io/apiserver/pkg/storage/selection_predicate.go
generated
vendored
|
|
@ -74,6 +74,7 @@ type SelectionPredicate struct {
|
|||
Label labels.Selector
|
||||
Field fields.Selector
|
||||
GetAttrs AttrFunc
|
||||
IndexLabels []string
|
||||
IndexFields []string
|
||||
Limit int64
|
||||
Continue string
|
||||
|
|
@ -128,3 +129,31 @@ func (s *SelectionPredicate) MatchesSingle() (string, bool) {
|
|||
func (s *SelectionPredicate) Empty() bool {
|
||||
return s.Label.Empty() && s.Field.Empty()
|
||||
}
|
||||
|
||||
// For any index defined by IndexFields, if a matcher can match only (a subset)
|
||||
// of objects that return <value> for a given index, a pair (<index name>, <value>)
|
||||
// wil be returned.
|
||||
func (s *SelectionPredicate) MatcherIndex() []MatchValue {
|
||||
var result []MatchValue
|
||||
for _, field := range s.IndexFields {
|
||||
if value, ok := s.Field.RequiresExactMatch(field); ok {
|
||||
result = append(result, MatchValue{IndexName: FieldIndex(field), Value: value})
|
||||
}
|
||||
}
|
||||
for _, label := range s.IndexLabels {
|
||||
if value, ok := s.Label.RequiresExactMatch(label); ok {
|
||||
result = append(result, MatchValue{IndexName: LabelIndex(label), Value: value})
|
||||
}
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
// LabelIndex add prefix for label index.
|
||||
func LabelIndex(label string) string {
|
||||
return "l:" + label
|
||||
}
|
||||
|
||||
// FiledIndex add prefix for field index.
|
||||
func FieldIndex(field string) string {
|
||||
return "f:" + field
|
||||
}
|
||||
|
|
|
|||
42
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go
generated
vendored
42
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/envelope.go
generated
vendored
|
|
@ -31,11 +31,9 @@ import (
|
|||
"golang.org/x/crypto/cryptobyte"
|
||||
)
|
||||
|
||||
// defaultCacheSize is the number of decrypted DEKs which would be cached by the transformer.
|
||||
const defaultCacheSize = 1000
|
||||
|
||||
func init() {
|
||||
value.RegisterMetrics()
|
||||
registerMetrics()
|
||||
}
|
||||
|
||||
// Service allows encrypting and decrypting data using an external Key Management Service.
|
||||
|
|
@ -54,6 +52,9 @@ type envelopeTransformer struct {
|
|||
|
||||
// baseTransformerFunc creates a new transformer for encrypting the data with the DEK.
|
||||
baseTransformerFunc func(cipher.Block) value.Transformer
|
||||
|
||||
cacheSize int
|
||||
cacheEnabled bool
|
||||
}
|
||||
|
||||
// NewEnvelopeTransformer returns a transformer which implements a KEK-DEK based envelope encryption scheme.
|
||||
|
|
@ -61,22 +62,30 @@ type envelopeTransformer struct {
|
|||
// the data items they encrypt. A cache (of size cacheSize) is maintained to store the most recently
|
||||
// used decrypted DEKs in memory.
|
||||
func NewEnvelopeTransformer(envelopeService Service, cacheSize int, baseTransformerFunc func(cipher.Block) value.Transformer) (value.Transformer, error) {
|
||||
if cacheSize == 0 {
|
||||
cacheSize = defaultCacheSize
|
||||
}
|
||||
cache, err := lru.New(cacheSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var (
|
||||
cache *lru.Cache
|
||||
err error
|
||||
)
|
||||
|
||||
if cacheSize > 0 {
|
||||
cache, err = lru.New(cacheSize)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
return &envelopeTransformer{
|
||||
envelopeService: envelopeService,
|
||||
transformers: cache,
|
||||
baseTransformerFunc: baseTransformerFunc,
|
||||
cacheEnabled: cacheSize > 0,
|
||||
cacheSize: cacheSize,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// TransformFromStorage decrypts data encrypted by this transformer using envelope encryption.
|
||||
func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Context) ([]byte, bool, error) {
|
||||
recordArrival(fromStorageLabel, time.Now())
|
||||
|
||||
// Read the 16 bit length-of-DEK encoded at the start of the encrypted DEK. 16 bits can
|
||||
// represent a maximum key length of 65536 bytes. We are using a 256 bit key, whose
|
||||
// length cannot fit in 8 bits (1 byte). Thus, we use 16 bits (2 bytes) to store the length.
|
||||
|
|
@ -91,7 +100,9 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co
|
|||
// Look up the decrypted DEK from cache or Envelope.
|
||||
transformer := t.getTransformer(encKey)
|
||||
if transformer == nil {
|
||||
value.RecordCacheMiss()
|
||||
if t.cacheEnabled {
|
||||
value.RecordCacheMiss()
|
||||
}
|
||||
key, err := t.envelopeService.Decrypt(encKey)
|
||||
if err != nil {
|
||||
// Do NOT wrap this err using fmt.Errorf() or similar functions
|
||||
|
|
@ -99,6 +110,7 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co
|
|||
// record the metric.
|
||||
return nil, false, err
|
||||
}
|
||||
|
||||
transformer, err = t.addTransformer(encKey, key)
|
||||
if err != nil {
|
||||
return nil, false, err
|
||||
|
|
@ -110,6 +122,7 @@ func (t *envelopeTransformer) TransformFromStorage(data []byte, context value.Co
|
|||
|
||||
// TransformToStorage encrypts data to be written to disk using envelope encryption.
|
||||
func (t *envelopeTransformer) TransformToStorage(data []byte, context value.Context) ([]byte, error) {
|
||||
recordArrival(toStorageLabel, time.Now())
|
||||
newKey, err := generateKey(32)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -153,12 +166,19 @@ func (t *envelopeTransformer) addTransformer(encKey []byte, key []byte) (value.T
|
|||
transformer := t.baseTransformerFunc(block)
|
||||
// Use base64 of encKey as the key into the cache because hashicorp/golang-lru
|
||||
// cannot hash []uint8.
|
||||
t.transformers.Add(base64.StdEncoding.EncodeToString(encKey), transformer)
|
||||
if t.cacheEnabled {
|
||||
t.transformers.Add(base64.StdEncoding.EncodeToString(encKey), transformer)
|
||||
dekCacheFillPercent.Set(float64(t.transformers.Len()) / float64(t.cacheSize))
|
||||
}
|
||||
return transformer, nil
|
||||
}
|
||||
|
||||
// getTransformer fetches the transformer corresponding to encKey from cache, if it exists.
|
||||
func (t *envelopeTransformer) getTransformer(encKey []byte) value.Transformer {
|
||||
if !t.cacheEnabled {
|
||||
return nil
|
||||
}
|
||||
|
||||
_transformer, found := t.transformers.Get(base64.StdEncoding.EncodeToString(encKey))
|
||||
if found {
|
||||
return _transformer.(value.Transformer)
|
||||
|
|
|
|||
102
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/metrics.go
generated
vendored
Normal file
102
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/metrics.go
generated
vendored
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
Copyright 2020 The Kubernetes Authors.
|
||||
|
||||
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 envelope
|
||||
|
||||
import (
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"k8s.io/component-base/metrics"
|
||||
"k8s.io/component-base/metrics/legacyregistry"
|
||||
)
|
||||
|
||||
const (
|
||||
namespace = "apiserver"
|
||||
subsystem = "envelope_encryption"
|
||||
fromStorageLabel = "from_storage"
|
||||
toStorageLabel = "to_storage"
|
||||
)
|
||||
|
||||
/*
|
||||
* By default, all the following metrics are defined as falling under
|
||||
* ALPHA stability level https://github.com/kubernetes/enhancements/blob/master/keps/sig-instrumentation/20190404-kubernetes-control-plane-metrics-stability.md#stability-classes)
|
||||
*
|
||||
* Promoting the stability level of the metric is a responsibility of the component owner, since it
|
||||
* involves explicitly acknowledging support for the metric across multiple releases, in accordance with
|
||||
* the metric stability policy.
|
||||
*/
|
||||
var (
|
||||
lockLastFromStorage sync.Mutex
|
||||
lockLastToStorage sync.Mutex
|
||||
|
||||
lastFromStorage time.Time
|
||||
lastToStorage time.Time
|
||||
|
||||
dekCacheFillPercent = metrics.NewGauge(
|
||||
&metrics.GaugeOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "dek_cache_fill_percent",
|
||||
Help: "Percent of the cache slots currently occupied by cached DEKs.",
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
},
|
||||
)
|
||||
|
||||
dekCacheInterArrivals = metrics.NewHistogramVec(
|
||||
&metrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "dek_cache_inter_arrival_time_seconds",
|
||||
Help: "Time (in seconds) of inter arrival of transformation requests.",
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
Buckets: metrics.ExponentialBuckets(60, 2, 10),
|
||||
},
|
||||
[]string{"transformation_type"},
|
||||
)
|
||||
)
|
||||
|
||||
var registerMetricsFunc sync.Once
|
||||
|
||||
func registerMetrics() {
|
||||
registerMetricsFunc.Do(func() {
|
||||
legacyregistry.MustRegister(dekCacheFillPercent)
|
||||
legacyregistry.MustRegister(dekCacheInterArrivals)
|
||||
})
|
||||
}
|
||||
|
||||
func recordArrival(transformationType string, start time.Time) {
|
||||
switch transformationType {
|
||||
case fromStorageLabel:
|
||||
lockLastFromStorage.Lock()
|
||||
defer lockLastFromStorage.Unlock()
|
||||
|
||||
if lastFromStorage.IsZero() {
|
||||
lastFromStorage = start
|
||||
}
|
||||
dekCacheInterArrivals.WithLabelValues(transformationType).Observe(start.Sub(lastFromStorage).Seconds())
|
||||
lastFromStorage = start
|
||||
case toStorageLabel:
|
||||
lockLastToStorage.Lock()
|
||||
defer lockLastToStorage.Unlock()
|
||||
|
||||
if lastToStorage.IsZero() {
|
||||
lastToStorage = start
|
||||
}
|
||||
dekCacheInterArrivals.WithLabelValues(transformationType).Observe(start.Sub(lastToStorage).Seconds())
|
||||
lastToStorage = start
|
||||
}
|
||||
}
|
||||
2
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1/service.pb.go
generated
vendored
2
vendor/k8s.io/apiserver/pkg/storage/value/encrypt/envelope/v1beta1/service.pb.go
generated
vendored
|
|
@ -38,7 +38,7 @@ var _ = math.Inf
|
|||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion2 // please upgrade the proto package
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type VersionRequest struct {
|
||||
// Version of the KMS plugin API.
|
||||
|
|
|
|||
50
vendor/k8s.io/apiserver/pkg/storage/value/metrics.go
generated
vendored
50
vendor/k8s.io/apiserver/pkg/storage/value/metrics.go
generated
vendored
|
|
@ -53,20 +53,6 @@ var (
|
|||
},
|
||||
[]string{"transformation_type"},
|
||||
)
|
||||
deprecatedTransformerLatencies = metrics.NewHistogramVec(
|
||||
&metrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "transformation_latencies_microseconds",
|
||||
Help: "Latencies in microseconds of value transformation operations.",
|
||||
// In-process transformations (ex. AES CBC) complete on the order of 20 microseconds. However, when
|
||||
// external KMS is involved latencies may climb into milliseconds.
|
||||
Buckets: metrics.ExponentialBuckets(5, 2, 14),
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
DeprecatedVersion: "1.14.0",
|
||||
},
|
||||
[]string{"transformation_type"},
|
||||
)
|
||||
|
||||
transformerOperationsTotal = metrics.NewCounterVec(
|
||||
&metrics.CounterOpts{
|
||||
|
|
@ -79,18 +65,6 @@ var (
|
|||
[]string{"transformation_type", "transformer_prefix", "status"},
|
||||
)
|
||||
|
||||
deprecatedTransformerFailuresTotal = metrics.NewCounterVec(
|
||||
&metrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "transformation_failures_total",
|
||||
Help: "Total number of failed transformation operations.",
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
DeprecatedVersion: "1.15.0",
|
||||
},
|
||||
[]string{"transformation_type"},
|
||||
)
|
||||
|
||||
envelopeTransformationCacheMissTotal = metrics.NewCounter(
|
||||
&metrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
|
|
@ -111,17 +85,7 @@ var (
|
|||
StabilityLevel: metrics.ALPHA,
|
||||
},
|
||||
)
|
||||
deprecatedDataKeyGenerationLatencies = metrics.NewHistogram(
|
||||
&metrics.HistogramOpts{
|
||||
Namespace: namespace,
|
||||
Subsystem: subsystem,
|
||||
Name: "data_key_generation_latencies_microseconds",
|
||||
Help: "Latencies in microseconds of data encryption key(DEK) generation operations.",
|
||||
Buckets: metrics.ExponentialBuckets(5, 2, 14),
|
||||
StabilityLevel: metrics.ALPHA,
|
||||
DeprecatedVersion: "1.14.0",
|
||||
},
|
||||
)
|
||||
|
||||
dataKeyGenerationFailuresTotal = metrics.NewCounter(
|
||||
&metrics.CounterOpts{
|
||||
Namespace: namespace,
|
||||
|
|
@ -138,12 +102,9 @@ var registerMetrics sync.Once
|
|||
func RegisterMetrics() {
|
||||
registerMetrics.Do(func() {
|
||||
legacyregistry.MustRegister(transformerLatencies)
|
||||
legacyregistry.MustRegister(deprecatedTransformerLatencies)
|
||||
legacyregistry.MustRegister(transformerOperationsTotal)
|
||||
legacyregistry.MustRegister(deprecatedTransformerFailuresTotal)
|
||||
legacyregistry.MustRegister(envelopeTransformationCacheMissTotal)
|
||||
legacyregistry.MustRegister(dataKeyGenerationLatencies)
|
||||
legacyregistry.MustRegister(deprecatedDataKeyGenerationLatencies)
|
||||
legacyregistry.MustRegister(dataKeyGenerationFailuresTotal)
|
||||
})
|
||||
}
|
||||
|
|
@ -156,9 +117,6 @@ func RecordTransformation(transformationType, transformerPrefix string, start ti
|
|||
switch {
|
||||
case err == nil:
|
||||
transformerLatencies.WithLabelValues(transformationType).Observe(sinceInSeconds(start))
|
||||
deprecatedTransformerLatencies.WithLabelValues(transformationType).Observe(sinceInMicroseconds(start))
|
||||
default:
|
||||
deprecatedTransformerFailuresTotal.WithLabelValues(transformationType).Inc()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -175,12 +133,6 @@ func RecordDataKeyGeneration(start time.Time, err error) {
|
|||
}
|
||||
|
||||
dataKeyGenerationLatencies.Observe(sinceInSeconds(start))
|
||||
deprecatedDataKeyGenerationLatencies.Observe(sinceInMicroseconds(start))
|
||||
}
|
||||
|
||||
// sinceInMicroseconds gets the time since the specified start in microseconds.
|
||||
func sinceInMicroseconds(start time.Time) float64 {
|
||||
return float64(time.Since(start).Nanoseconds() / time.Microsecond.Nanoseconds())
|
||||
}
|
||||
|
||||
// sinceInSeconds gets the time since the specified start in seconds.
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue