k8s.io/kubernetes@v1.29.3/pkg/kubelet/server/stats/summary.go (about) 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 //go:generate mockgen -source=summary.go -destination=testing/mock_summary_provider.go -package=testing SummaryProvider 18 package stats 19 20 import ( 21 "context" 22 "fmt" 23 24 "k8s.io/klog/v2" 25 26 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 27 statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1" 28 "k8s.io/kubernetes/pkg/kubelet/util" 29 ) 30 31 // SummaryProvider provides summaries of the stats from Kubelet. 32 type SummaryProvider interface { 33 // Get provides a new Summary with the stats from Kubelet, 34 // and will update some stats if updateStats is true 35 Get(ctx context.Context, updateStats bool) (*statsapi.Summary, error) 36 // GetCPUAndMemoryStats provides a new Summary with the CPU and memory stats from Kubelet, 37 GetCPUAndMemoryStats(ctx context.Context) (*statsapi.Summary, error) 38 } 39 40 // summaryProviderImpl implements the SummaryProvider interface. 41 type summaryProviderImpl struct { 42 // kubeletCreationTime is the time at which the summaryProvider was created. 43 kubeletCreationTime metav1.Time 44 // systemBootTime is the time at which the system was started 45 systemBootTime metav1.Time 46 47 provider Provider 48 } 49 50 var _ SummaryProvider = &summaryProviderImpl{} 51 52 // NewSummaryProvider returns a SummaryProvider using the stats provided by the 53 // specified statsProvider. 54 func NewSummaryProvider(statsProvider Provider) SummaryProvider { 55 kubeletCreationTime := metav1.Now() 56 bootTime, err := util.GetBootTime() 57 if err != nil { 58 // bootTime will be zero if we encounter an error getting the boot time. 59 klog.InfoS("Error getting system boot time. Node metrics will have an incorrect start time", "err", err) 60 } 61 62 return &summaryProviderImpl{ 63 kubeletCreationTime: kubeletCreationTime, 64 systemBootTime: metav1.NewTime(bootTime), 65 provider: statsProvider, 66 } 67 } 68 69 func (sp *summaryProviderImpl) Get(ctx context.Context, updateStats bool) (*statsapi.Summary, error) { 70 // TODO(timstclair): Consider returning a best-effort response if any of 71 // the following errors occur. 72 node, err := sp.provider.GetNode() 73 if err != nil { 74 return nil, fmt.Errorf("failed to get node info: %v", err) 75 } 76 nodeConfig := sp.provider.GetNodeConfig() 77 rootStats, networkStats, err := sp.provider.GetCgroupStats("/", updateStats) 78 if err != nil { 79 return nil, fmt.Errorf("failed to get root cgroup stats: %v", err) 80 } 81 rootFsStats, err := sp.provider.RootFsStats() 82 if err != nil { 83 return nil, fmt.Errorf("failed to get rootFs stats: %v", err) 84 } 85 imageFsStats, containerFsStats, err := sp.provider.ImageFsStats(ctx) 86 if err != nil { 87 return nil, fmt.Errorf("failed to get imageFs stats: %v", err) 88 } 89 var podStats []statsapi.PodStats 90 if updateStats { 91 podStats, err = sp.provider.ListPodStatsAndUpdateCPUNanoCoreUsage(ctx) 92 } else { 93 podStats, err = sp.provider.ListPodStats(ctx) 94 } 95 if err != nil { 96 return nil, fmt.Errorf("failed to list pod stats: %v", err) 97 } 98 99 rlimit, err := sp.provider.RlimitStats() 100 if err != nil { 101 return nil, fmt.Errorf("failed to get rlimit stats: %v", err) 102 } 103 104 nodeStats := statsapi.NodeStats{ 105 NodeName: node.Name, 106 CPU: rootStats.CPU, 107 Memory: rootStats.Memory, 108 Swap: rootStats.Swap, 109 Network: networkStats, 110 StartTime: sp.systemBootTime, 111 Fs: rootFsStats, 112 Runtime: &statsapi.RuntimeStats{ContainerFs: containerFsStats, ImageFs: imageFsStats}, 113 Rlimit: rlimit, 114 SystemContainers: sp.GetSystemContainersStats(nodeConfig, podStats, updateStats), 115 } 116 summary := statsapi.Summary{ 117 Node: nodeStats, 118 Pods: podStats, 119 } 120 return &summary, nil 121 } 122 123 func (sp *summaryProviderImpl) GetCPUAndMemoryStats(ctx context.Context) (*statsapi.Summary, error) { 124 // TODO(timstclair): Consider returning a best-effort response if any of 125 // the following errors occur. 126 node, err := sp.provider.GetNode() 127 if err != nil { 128 return nil, fmt.Errorf("failed to get node info: %v", err) 129 } 130 nodeConfig := sp.provider.GetNodeConfig() 131 rootStats, err := sp.provider.GetCgroupCPUAndMemoryStats("/", false) 132 if err != nil { 133 return nil, fmt.Errorf("failed to get root cgroup stats: %v", err) 134 } 135 136 podStats, err := sp.provider.ListPodCPUAndMemoryStats(ctx) 137 if err != nil { 138 return nil, fmt.Errorf("failed to list pod stats: %v", err) 139 } 140 141 nodeStats := statsapi.NodeStats{ 142 NodeName: node.Name, 143 CPU: rootStats.CPU, 144 Memory: rootStats.Memory, 145 Swap: rootStats.Swap, 146 StartTime: rootStats.StartTime, 147 SystemContainers: sp.GetSystemContainersCPUAndMemoryStats(nodeConfig, podStats, false), 148 } 149 summary := statsapi.Summary{ 150 Node: nodeStats, 151 Pods: podStats, 152 } 153 return &summary, nil 154 }