mirror of https://github.com/k3s-io/k3s
152 lines
4.9 KiB
Go
152 lines
4.9 KiB
Go
/*
|
|
Copyright 2016 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 stats
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"k8s.io/klog"
|
|
|
|
rsystem "github.com/opencontainers/runc/libcontainer/system"
|
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
|
|
statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
|
"k8s.io/kubernetes/pkg/kubelet/util"
|
|
)
|
|
|
|
type SummaryProvider interface {
|
|
// Get provides a new Summary with the stats from Kubelet,
|
|
// and will update some stats if updateStats is true
|
|
Get(updateStats bool) (*statsapi.Summary, error)
|
|
// GetCPUAndMemoryStats provides a new Summary with the CPU and memory stats from Kubelet,
|
|
GetCPUAndMemoryStats() (*statsapi.Summary, error)
|
|
}
|
|
|
|
// summaryProviderImpl implements the SummaryProvider interface.
|
|
type summaryProviderImpl struct {
|
|
// kubeletCreationTime is the time at which the summaryProvider was created.
|
|
kubeletCreationTime metav1.Time
|
|
// systemBootTime is the time at which the system was started
|
|
systemBootTime metav1.Time
|
|
|
|
provider StatsProvider
|
|
}
|
|
|
|
var _ SummaryProvider = &summaryProviderImpl{}
|
|
|
|
// NewSummaryProvider returns a SummaryProvider using the stats provided by the
|
|
// specified statsProvider.
|
|
func NewSummaryProvider(statsProvider StatsProvider) 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,
|
|
}
|
|
}
|
|
|
|
func (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 {
|
|
if !rsystem.RunningInUserNS() {
|
|
return nil, fmt.Errorf("failed to get root cgroup stats: %v", err)
|
|
}
|
|
// if we are in userns, cgroups might not be available
|
|
klog.Errorf("failed to get root cgroup stats: %v", err)
|
|
rootStats = &statsapi.ContainerStats{}
|
|
networkStats = &statsapi.NetworkStats{}
|
|
}
|
|
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)
|
|
}
|
|
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
|
|
}
|
|
|
|
func (sp *summaryProviderImpl) GetCPUAndMemoryStats() (*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, err := sp.provider.GetCgroupCPUAndMemoryStats("/", false)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to get root cgroup stats: %v", err)
|
|
}
|
|
|
|
podStats, err := sp.provider.ListPodCPUAndMemoryStats()
|
|
if err != nil {
|
|
return nil, fmt.Errorf("failed to list pod stats: %v", err)
|
|
}
|
|
|
|
nodeStats := statsapi.NodeStats{
|
|
NodeName: node.Name,
|
|
CPU: rootStats.CPU,
|
|
Memory: rootStats.Memory,
|
|
StartTime: rootStats.StartTime,
|
|
SystemContainers: sp.GetSystemContainersCPUAndMemoryStats(nodeConfig, podStats, false),
|
|
}
|
|
summary := statsapi.Summary{
|
|
Node: nodeStats,
|
|
Pods: podStats,
|
|
}
|
|
return &summary, nil
|
|
}
|