mirror of
https://github.com/optim-enterprises-bv/kubernetes.git
synced 2025-11-02 03:08:15 +00:00
Process only CPU and memory stats when Kubelete stats API is called with
only_cpu_and_memory parameter. Before all stats were processed and removed before returning.
This commit is contained in:
@@ -51,6 +51,7 @@ import (
|
||||
api "k8s.io/kubernetes/pkg/apis/core"
|
||||
runtimeapi "k8s.io/kubernetes/pkg/kubelet/apis/cri/runtime/v1alpha2"
|
||||
statsapi "k8s.io/kubernetes/pkg/kubelet/apis/stats/v1alpha1"
|
||||
|
||||
// Do some initialization to decode the query parameters correctly.
|
||||
_ "k8s.io/kubernetes/pkg/apis/core/install"
|
||||
"k8s.io/kubernetes/pkg/kubelet/cm"
|
||||
@@ -255,13 +256,17 @@ func (fk *fakeKubelet) ListVolumesForPod(podUID types.UID) (map[string]volume.Vo
|
||||
return map[string]volume.Volume{}, true
|
||||
}
|
||||
|
||||
func (_ *fakeKubelet) RootFsStats() (*statsapi.FsStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) ListPodStats() ([]statsapi.PodStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) ImageFsStats() (*statsapi.FsStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) RlimitStats() (*statsapi.RlimitStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) RootFsStats() (*statsapi.FsStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) ListPodStats() ([]statsapi.PodStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) ListPodCPUAndMemoryStats() ([]statsapi.PodStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) ImageFsStats() (*statsapi.FsStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) RlimitStats() (*statsapi.RlimitStats, error) { return nil, nil }
|
||||
func (_ *fakeKubelet) GetCgroupStats(cgroupName string, updateStats bool) (*statsapi.ContainerStats, *statsapi.NetworkStats, error) {
|
||||
return nil, nil, nil
|
||||
}
|
||||
func (_ *fakeKubelet) GetCgroupCPUAndMemoryStats(cgroupName string, updateStats bool) (*statsapi.ContainerStats, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
type fakeAuth struct {
|
||||
authenticateFunc func(*http.Request) (user.Info, bool, error)
|
||||
|
||||
@@ -43,6 +43,8 @@ type StatsProvider interface {
|
||||
//
|
||||
// ListPodStats returns the stats of all the containers managed by pods.
|
||||
ListPodStats() ([]statsapi.PodStats, error)
|
||||
// ListPodCPUAndMemoryStats returns the CPU and memory stats of all the containers managed by pods.
|
||||
ListPodCPUAndMemoryStats() ([]statsapi.PodStats, error)
|
||||
// ImageFsStats returns the stats of the image filesystem.
|
||||
ImageFsStats() (*statsapi.FsStats, error)
|
||||
|
||||
@@ -51,6 +53,9 @@ type StatsProvider interface {
|
||||
// GetCgroupStats returns the stats and the networking usage of the cgroup
|
||||
// with the specified cgroupName.
|
||||
GetCgroupStats(cgroupName string, updateStats bool) (*statsapi.ContainerStats, *statsapi.NetworkStats, error)
|
||||
// GetCgroupCPUAndMemoryStats returns the CPU and memory stats of the cgroup with the specified cgroupName.
|
||||
GetCgroupCPUAndMemoryStats(cgroupName string, updateStats bool) (*statsapi.ContainerStats, error)
|
||||
|
||||
// RootFsStats returns the stats of the node root filesystem.
|
||||
RootFsStats() (*statsapi.FsStats, error)
|
||||
|
||||
|
||||
@@ -91,30 +91,33 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error)
|
||||
}
|
||||
|
||||
func (sp *summaryProviderImpl) GetCPUAndMemoryStats() (*statsapi.Summary, error) {
|
||||
summary, err := sp.Get(false)
|
||||
// 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, err
|
||||
return nil, fmt.Errorf("failed to get node info: %v", err)
|
||||
}
|
||||
summary.Node.Network = nil
|
||||
summary.Node.Fs = nil
|
||||
summary.Node.Runtime = nil
|
||||
summary.Node.Rlimit = nil
|
||||
for i := 0; i < len(summary.Node.SystemContainers); i++ {
|
||||
summary.Node.SystemContainers[i].Accelerators = nil
|
||||
summary.Node.SystemContainers[i].Rootfs = nil
|
||||
summary.Node.SystemContainers[i].Logs = nil
|
||||
summary.Node.SystemContainers[i].UserDefinedMetrics = nil
|
||||
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)
|
||||
}
|
||||
for i := 0; i < len(summary.Pods); i++ {
|
||||
summary.Pods[i].Network = nil
|
||||
summary.Pods[i].VolumeStats = nil
|
||||
summary.Pods[i].EphemeralStorage = nil
|
||||
for j := 0; j < len(summary.Pods[i].Containers); j++ {
|
||||
summary.Pods[i].Containers[j].Accelerators = nil
|
||||
summary.Pods[i].Containers[j].Rootfs = nil
|
||||
summary.Pods[i].Containers[j].Logs = nil
|
||||
summary.Pods[i].Containers[j].UserDefinedMetrics = nil
|
||||
}
|
||||
|
||||
podStats, err := sp.provider.ListPodCPUAndMemoryStats()
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to list pod stats: %v", err)
|
||||
}
|
||||
return summary, nil
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@@ -53,3 +53,30 @@ func (sp *summaryProviderImpl) GetSystemContainersStats(nodeConfig cm.NodeConfig
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
func (sp *summaryProviderImpl) GetSystemContainersCPUAndMemoryStats(nodeConfig cm.NodeConfig, podStats []statsapi.PodStats, updateStats bool) (stats []statsapi.ContainerStats) {
|
||||
systemContainers := map[string]struct {
|
||||
name string
|
||||
forceStatsUpdate bool
|
||||
}{
|
||||
statsapi.SystemContainerKubelet: {nodeConfig.KubeletCgroupsName, false},
|
||||
statsapi.SystemContainerRuntime: {nodeConfig.RuntimeCgroupsName, false},
|
||||
statsapi.SystemContainerMisc: {nodeConfig.SystemCgroupsName, false},
|
||||
statsapi.SystemContainerPods: {sp.provider.GetPodCgroupRoot(), updateStats},
|
||||
}
|
||||
for sys, cont := range systemContainers {
|
||||
// skip if cgroup name is undefined (not all system containers are required)
|
||||
if cont.name == "" {
|
||||
continue
|
||||
}
|
||||
s, err := sp.provider.GetCgroupCPUAndMemoryStats(cont.name, cont.forceStatsUpdate)
|
||||
if err != nil {
|
||||
glog.Errorf("Failed to get system container stats for %q: %v", cont.name, err)
|
||||
continue
|
||||
}
|
||||
s.Name = sys
|
||||
stats = append(stats, *s)
|
||||
}
|
||||
|
||||
return stats
|
||||
}
|
||||
|
||||
@@ -27,11 +27,16 @@ import (
|
||||
)
|
||||
|
||||
func (sp *summaryProviderImpl) GetSystemContainersStats(nodeConfig cm.NodeConfig, podStats []statsapi.PodStats, updateStats bool) (stats []statsapi.ContainerStats) {
|
||||
stats = append(stats, sp.getSystemPodsStats(nodeConfig, podStats, updateStats))
|
||||
stats = append(stats, sp.getSystemPodsCPUAndMemoryStats(nodeConfig, podStats, updateStats))
|
||||
return stats
|
||||
}
|
||||
|
||||
func (sp *summaryProviderImpl) getSystemPodsStats(nodeConfig cm.NodeConfig, podStats []statsapi.PodStats, updateStats bool) statsapi.ContainerStats {
|
||||
func (sp *summaryProviderImpl) GetSystemContainersCPUAndMemoryStats(nodeConfig cm.NodeConfig, podStats []statsapi.PodStats, updateStats bool) (stats []statsapi.ContainerStats) {
|
||||
stats = append(stats, sp.getSystemPodsCPUAndMemoryStats(nodeConfig, podStats, updateStats))
|
||||
return stats
|
||||
}
|
||||
|
||||
func (sp *summaryProviderImpl) getSystemPodsCPUAndMemoryStats(nodeConfig cm.NodeConfig, podStats []statsapi.PodStats, updateStats bool) statsapi.ContainerStats {
|
||||
now := metav1.NewTime(time.Now())
|
||||
podsSummary := statsapi.ContainerStats{
|
||||
StartTime: now,
|
||||
|
||||
@@ -33,15 +33,6 @@ import (
|
||||
)
|
||||
|
||||
var (
|
||||
podStats = []statsapi.PodStats{
|
||||
{
|
||||
PodRef: statsapi.PodReference{Name: "test-pod", Namespace: "test-namespace", UID: "UID_test-pod"},
|
||||
StartTime: metav1.NewTime(time.Now()),
|
||||
Containers: []statsapi.ContainerStats{*getContainerStats()},
|
||||
Network: getNetworkStats(),
|
||||
VolumeStats: []statsapi.VolumeStats{*getVolumeStats()},
|
||||
},
|
||||
}
|
||||
imageFsStats = getFsStats()
|
||||
rootFsStats = getFsStats()
|
||||
node = &v1.Node{ObjectMeta: metav1.ObjectMeta{Name: "test-node"}}
|
||||
@@ -50,8 +41,23 @@ var (
|
||||
SystemCgroupsName: "/misc",
|
||||
KubeletCgroupsName: "/kubelet",
|
||||
}
|
||||
cgroupRoot = "/kubepods"
|
||||
cgroupStatsMap = map[string]struct {
|
||||
cgroupRoot = "/kubepods"
|
||||
rlimitStats = getRlimitStats()
|
||||
)
|
||||
|
||||
func TestSummaryProviderGetStats(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
podStats := []statsapi.PodStats{
|
||||
{
|
||||
PodRef: statsapi.PodReference{Name: "test-pod", Namespace: "test-namespace", UID: "UID_test-pod"},
|
||||
StartTime: metav1.NewTime(time.Now()),
|
||||
Containers: []statsapi.ContainerStats{*getContainerStats()},
|
||||
Network: getNetworkStats(),
|
||||
VolumeStats: []statsapi.VolumeStats{*getVolumeStats()},
|
||||
},
|
||||
}
|
||||
cgroupStatsMap := map[string]struct {
|
||||
cs *statsapi.ContainerStats
|
||||
ns *statsapi.NetworkStats
|
||||
}{
|
||||
@@ -61,11 +67,6 @@ var (
|
||||
"/kubelet": {cs: getContainerStats(), ns: getNetworkStats()},
|
||||
"/pods": {cs: getContainerStats(), ns: getNetworkStats()},
|
||||
}
|
||||
rlimitStats = getRlimitStats()
|
||||
)
|
||||
|
||||
func TestSummaryProviderGetStats(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
mockStatsProvider := new(statstest.StatsProvider)
|
||||
mockStatsProvider.
|
||||
@@ -133,20 +134,34 @@ func TestSummaryProviderGetStats(t *testing.T) {
|
||||
func TestSummaryProviderGetCPUAndMemoryStats(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
podStats := []statsapi.PodStats{
|
||||
{
|
||||
PodRef: statsapi.PodReference{Name: "test-pod", Namespace: "test-namespace", UID: "UID_test-pod"},
|
||||
StartTime: metav1.NewTime(time.Now()),
|
||||
Containers: []statsapi.ContainerStats{*getContainerStats()},
|
||||
},
|
||||
}
|
||||
cgroupStatsMap := map[string]struct {
|
||||
cs *statsapi.ContainerStats
|
||||
}{
|
||||
"/": {cs: getVolumeCPUAndMemoryStats()},
|
||||
"/runtime": {cs: getVolumeCPUAndMemoryStats()},
|
||||
"/misc": {cs: getVolumeCPUAndMemoryStats()},
|
||||
"/kubelet": {cs: getVolumeCPUAndMemoryStats()},
|
||||
"/pods": {cs: getVolumeCPUAndMemoryStats()},
|
||||
}
|
||||
|
||||
mockStatsProvider := new(statstest.StatsProvider)
|
||||
mockStatsProvider.
|
||||
On("GetNode").Return(node, nil).
|
||||
On("GetNodeConfig").Return(nodeConfig).
|
||||
On("GetPodCgroupRoot").Return(cgroupRoot).
|
||||
On("ListPodStats").Return(podStats, nil).
|
||||
On("ImageFsStats").Return(imageFsStats, nil).
|
||||
On("RootFsStats").Return(rootFsStats, nil).
|
||||
On("RlimitStats").Return(rlimitStats, nil).
|
||||
On("GetCgroupStats", "/", false).Return(cgroupStatsMap["/"].cs, cgroupStatsMap["/"].ns, nil).
|
||||
On("GetCgroupStats", "/runtime", false).Return(cgroupStatsMap["/runtime"].cs, cgroupStatsMap["/runtime"].ns, nil).
|
||||
On("GetCgroupStats", "/misc", false).Return(cgroupStatsMap["/misc"].cs, cgroupStatsMap["/misc"].ns, nil).
|
||||
On("GetCgroupStats", "/kubelet", false).Return(cgroupStatsMap["/kubelet"].cs, cgroupStatsMap["/kubelet"].ns, nil).
|
||||
On("GetCgroupStats", "/kubepods", false).Return(cgroupStatsMap["/pods"].cs, cgroupStatsMap["/pods"].ns, nil)
|
||||
On("ListPodCPUAndMemoryStats").Return(podStats, nil).
|
||||
On("GetCgroupCPUAndMemoryStats", "/", false).Return(cgroupStatsMap["/"].cs, nil).
|
||||
On("GetCgroupCPUAndMemoryStats", "/runtime", false).Return(cgroupStatsMap["/runtime"].cs, nil).
|
||||
On("GetCgroupCPUAndMemoryStats", "/misc", false).Return(cgroupStatsMap["/misc"].cs, nil).
|
||||
On("GetCgroupCPUAndMemoryStats", "/kubelet", false).Return(cgroupStatsMap["/kubelet"].cs, nil).
|
||||
On("GetCgroupCPUAndMemoryStats", "/kubepods", false).Return(cgroupStatsMap["/pods"].cs, nil)
|
||||
|
||||
provider := NewSummaryProvider(mockStatsProvider)
|
||||
summary, err := provider.GetCPUAndMemoryStats()
|
||||
@@ -201,6 +216,15 @@ func getContainerStats() *statsapi.ContainerStats {
|
||||
f.Fuzz(v)
|
||||
return v
|
||||
}
|
||||
func getVolumeCPUAndMemoryStats() *statsapi.ContainerStats {
|
||||
f := fuzz.New().NilChance(0)
|
||||
v := &statsapi.ContainerStats{}
|
||||
f.Fuzz(&v.Name)
|
||||
f.Fuzz(&v.StartTime)
|
||||
f.Fuzz(v.CPU)
|
||||
f.Fuzz(v.Memory)
|
||||
return v
|
||||
}
|
||||
|
||||
func getVolumeStats() *statsapi.VolumeStats {
|
||||
f := fuzz.New().NilChance(0)
|
||||
|
||||
@@ -64,6 +64,29 @@ func (_m *StatsProvider) GetCgroupStats(cgroupName string, updateStats bool) (*v
|
||||
return r0, r1, r2
|
||||
}
|
||||
|
||||
// GetCgroupCPUAndMemoryStats provides a mock function with given fields: cgroupName, updateStats
|
||||
func (_m *StatsProvider) GetCgroupCPUAndMemoryStats(cgroupName string, updateStats bool) (*v1alpha1.ContainerStats, error) {
|
||||
ret := _m.Called(cgroupName, updateStats)
|
||||
|
||||
var r0 *v1alpha1.ContainerStats
|
||||
if rf, ok := ret.Get(0).(func(string, bool) *v1alpha1.ContainerStats); ok {
|
||||
r0 = rf(cgroupName, updateStats)
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).(*v1alpha1.ContainerStats)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func(string, bool) error); ok {
|
||||
r1 = rf(cgroupName, updateStats)
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// GetPodByCgroupfs provides the pod that maps to the specified cgroup, as well
|
||||
// as whether the pod was found.
|
||||
func (_m *StatsProvider) GetPodByCgroupfs(cgroupfs string) (*corev1.Pod, bool) {
|
||||
@@ -252,6 +275,29 @@ func (_m *StatsProvider) ListPodStats() ([]v1alpha1.PodStats, error) {
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListPodCPUAndMemoryStats provides a mock function with given fields:
|
||||
func (_m *StatsProvider) ListPodCPUAndMemoryStats() ([]v1alpha1.PodStats, error) {
|
||||
ret := _m.Called()
|
||||
|
||||
var r0 []v1alpha1.PodStats
|
||||
if rf, ok := ret.Get(0).(func() []v1alpha1.PodStats); ok {
|
||||
r0 = rf()
|
||||
} else {
|
||||
if ret.Get(0) != nil {
|
||||
r0 = ret.Get(0).([]v1alpha1.PodStats)
|
||||
}
|
||||
}
|
||||
|
||||
var r1 error
|
||||
if rf, ok := ret.Get(1).(func() error); ok {
|
||||
r1 = rf()
|
||||
} else {
|
||||
r1 = ret.Error(1)
|
||||
}
|
||||
|
||||
return r0, r1
|
||||
}
|
||||
|
||||
// ListVolumesForPod provides a mock function with given fields: podUID
|
||||
func (_m *StatsProvider) ListVolumesForPod(podUID types.UID) (map[string]volume.Volume, bool) {
|
||||
ret := _m.Called(podUID)
|
||||
|
||||
Reference in New Issue
Block a user