klet.resourceAnalyzer = serverstats.NewResourceAnalyzer(klet, kubeCfg.VolumeStatsAggPeriod.Duration)
// NewResourceAnalyzer returns a new ResourceAnalyzer func NewResourceAnalyzer(statsProvider Provider, calVolumeFrequency time.Duration) ResourceAnalyzer { fsAnalyzer := newFsResourceAnalyzer(statsProvider, calVolumeFrequency) summaryProvider := NewSummaryProvider(statsProvider) return &resourceAnalyzer{fsAnalyzer, summaryProvider} }
// NewSummaryProvider returns a SummaryProvider using the stats provided by the // specified statsProvider. func NewSummaryProvider(statsProvider Provider) SummaryProvider { kubeletCreationTime := metav1.Now() bootTime, err := util.GetBootTime() if err != nil { // bootTime will be zero if we encounter an error getting the boot time. klog.Warningf("Error getting system boot time. Node metrics will have an incorrect start time: %v", err) }
return &summaryProviderImpl{
kubeletCreationTime: kubeletCreationTime,
systemBootTime: metav1.NewTime(bootTime),
provider: statsProvider,
}
}
And then accesses using the stats provider we use:
c (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error) { // TODO(timstclair): Consider returning a best-effort response if any of // the following errors occur. node, err := sp.provider.GetNode() if err != nil { return nil, fmt.Errorf("failed to get node info: %v", err) } nodeConfig := sp.provider.GetNodeConfig() rootStats, networkStats, err := sp.provider.GetCgroupStats("/", updateStats) if err != nil { return nil, fmt.Errorf("failed to get root cgroup stats: %v", err) } rootFsStats, err := sp.provider.RootFsStats() if err != nil { return nil, fmt.Errorf("failed to get rootFs stats: %v", err) } imageFsStats, err := sp.provider.ImageFsStats() if err != nil { return nil, fmt.Errorf("failed to get imageFs stats: %v", err) } var podStats []statsapi.PodStats if updateStats { podStats, err = sp.provider.ListPodStatsAndUpdateCPUNanoCoreUsage() } else { podStats, err = sp.provider.ListPodStats() } if err != nil { return nil, fmt.Errorf("failed to list pod stats: %v", err) }
rlimit, err := sp.provider.RlimitStats()
if err != nil {
return nil, fmt.Errorf("failed to get rlimit stats: %v", err)
}
nodeStats := statsapi.NodeStats{
NodeName: node.Name,
CPU: rootStats.CPU,
Memory: rootStats.Memory,
Network: networkStats,
StartTime: sp.systemBootTime,
Fs: rootFsStats,
Runtime: &statsapi.RuntimeStats{ImageFs: imageFsStats},
Rlimit: rlimit,
SystemContainers: sp.GetSystemContainersStats(nodeConfig, podStats, updateStats),
}
summary := statsapi.Summary{
Node: nodeStats,
Pods: podStats,
}
return &summary, nil
}
--> So, Kubelet also exposes /metrics/resource/v1apha.
With this we get the CRI based stats, but we don't get Pod Level information. While we can try to add in the fture, this is a good starting point.
Weirdly, CPU value seems unexpected relative to what is calculated/grabbed from CAdvisor metrics.