...

Source file src/k8s.io/kubernetes/pkg/kubelet/server/stats/fs_resource_analyzer.go

Documentation: k8s.io/kubernetes/pkg/kubelet/server/stats

     1  /*
     2  Copyright 2016 The Kubernetes Authors.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8      http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package stats
    18  
    19  import (
    20  	"sync"
    21  	"sync/atomic"
    22  	"time"
    23  
    24  	"k8s.io/apimachinery/pkg/types"
    25  	"k8s.io/apimachinery/pkg/util/wait"
    26  	"k8s.io/client-go/tools/record"
    27  
    28  	"k8s.io/klog/v2"
    29  )
    30  
    31  type statCache map[types.UID]*volumeStatCalculator
    32  
    33  // fsResourceAnalyzerInterface is for embedding fs functions into ResourceAnalyzer
    34  type fsResourceAnalyzerInterface interface {
    35  	GetPodVolumeStats(uid types.UID) (PodVolumeStats, bool)
    36  }
    37  
    38  // fsResourceAnalyzer provides stats about fs resource usage
    39  type fsResourceAnalyzer struct {
    40  	statsProvider     Provider
    41  	calcPeriod        time.Duration
    42  	cachedVolumeStats atomic.Value
    43  	startOnce         sync.Once
    44  	eventRecorder     record.EventRecorder
    45  }
    46  
    47  var _ fsResourceAnalyzerInterface = &fsResourceAnalyzer{}
    48  
    49  // newFsResourceAnalyzer returns a new fsResourceAnalyzer implementation
    50  func newFsResourceAnalyzer(statsProvider Provider, calcVolumePeriod time.Duration, eventRecorder record.EventRecorder) *fsResourceAnalyzer {
    51  	r := &fsResourceAnalyzer{
    52  		statsProvider: statsProvider,
    53  		calcPeriod:    calcVolumePeriod,
    54  		eventRecorder: eventRecorder,
    55  	}
    56  	r.cachedVolumeStats.Store(make(statCache))
    57  	return r
    58  }
    59  
    60  // Start eager background caching of volume stats.
    61  func (s *fsResourceAnalyzer) Start() {
    62  	s.startOnce.Do(func() {
    63  		if s.calcPeriod <= 0 {
    64  			klog.InfoS("Volume stats collection disabled")
    65  			return
    66  		}
    67  		klog.InfoS("Starting FS ResourceAnalyzer")
    68  		go wait.Forever(func() { s.updateCachedPodVolumeStats() }, s.calcPeriod)
    69  	})
    70  }
    71  
    72  // updateCachedPodVolumeStats calculates and caches the PodVolumeStats for every Pod known to the kubelet.
    73  func (s *fsResourceAnalyzer) updateCachedPodVolumeStats() {
    74  	oldCache := s.cachedVolumeStats.Load().(statCache)
    75  	newCache := make(statCache)
    76  
    77  	// Copy existing entries to new map, creating/starting new entries for pods missing from the cache
    78  	for _, pod := range s.statsProvider.GetPods() {
    79  		if value, found := oldCache[pod.GetUID()]; !found {
    80  			newCache[pod.GetUID()] = newVolumeStatCalculator(s.statsProvider, s.calcPeriod, pod, s.eventRecorder).StartOnce()
    81  		} else {
    82  			newCache[pod.GetUID()] = value
    83  		}
    84  	}
    85  
    86  	// Stop entries for pods that have been deleted
    87  	for uid, entry := range oldCache {
    88  		if _, found := newCache[uid]; !found {
    89  			entry.StopOnce()
    90  		}
    91  	}
    92  
    93  	// Update the cache reference
    94  	s.cachedVolumeStats.Store(newCache)
    95  }
    96  
    97  // GetPodVolumeStats returns the PodVolumeStats for a given pod.  Results are looked up from a cache that
    98  // is eagerly populated in the background, and never calculated on the fly.
    99  func (s *fsResourceAnalyzer) GetPodVolumeStats(uid types.UID) (PodVolumeStats, bool) {
   100  	cache := s.cachedVolumeStats.Load().(statCache)
   101  	statCalc, found := cache[uid]
   102  	if !found {
   103  		// TODO: Differentiate between stats being empty
   104  		// See issue #20679
   105  		return PodVolumeStats{}, false
   106  	}
   107  	return statCalc.GetLatest()
   108  }
   109  

View as plain text