Merge pull request #67829 from krzysztof-jastrzebski/cpuandmemory
Add "only_cpu_and_memory" GET parameter to /stats/summary http handler in kubele
This commit is contained in:
		| @@ -1011,6 +1011,10 @@ func (f *fakeSummaryProvider) Get(updateStats bool) (*statsapi.Summary, error) { | |||||||
| 	return f.result, nil | 	return f.result, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (f *fakeSummaryProvider) GetCPUAndMemoryStats() (*statsapi.Summary, error) { | ||||||
|  | 	return f.result, nil | ||||||
|  | } | ||||||
|  |  | ||||||
| // newPodStats returns a pod stat where each container is using the specified working set | // newPodStats returns a pod stat where each container is using the specified working set | ||||||
| // each pod must have a Name, UID, Namespace | // each pod must have a Name, UID, Namespace | ||||||
| func newPodStats(pod *v1.Pod, containerWorkingSetBytes int64) statsapi.PodStats { | func newPodStats(pod *v1.Pod, containerWorkingSetBytes int64) statsapi.PodStats { | ||||||
|   | |||||||
| @@ -192,10 +192,23 @@ func (h *handler) handleStats(request *restful.Request, response *restful.Respon | |||||||
| } | } | ||||||
|  |  | ||||||
| // Handles stats summary requests to /stats/summary | // Handles stats summary requests to /stats/summary | ||||||
|  | // If "only_cpu_and_memory" GET param is true then only cpu and memory is returned in response. | ||||||
| func (h *handler) handleSummary(request *restful.Request, response *restful.Response) { | func (h *handler) handleSummary(request *restful.Request, response *restful.Response) { | ||||||
|  | 	onlyCPUAndMemory := false | ||||||
|  | 	request.Request.ParseForm() | ||||||
|  | 	if onlyCluAndMemoryParam, found := request.Request.Form["only_cpu_and_memory"]; found && | ||||||
|  | 		len(onlyCluAndMemoryParam) == 1 && onlyCluAndMemoryParam[0] == "true" { | ||||||
|  | 		onlyCPUAndMemory = true | ||||||
|  | 	} | ||||||
|  | 	var summary *statsapi.Summary | ||||||
|  | 	var err error | ||||||
|  | 	if onlyCPUAndMemory { | ||||||
|  | 		summary, err = h.summaryProvider.GetCPUAndMemoryStats() | ||||||
|  | 	} else { | ||||||
| 		// external calls to the summary API use cached stats | 		// external calls to the summary API use cached stats | ||||||
| 		forceStatsUpdate := false | 		forceStatsUpdate := false | ||||||
| 	summary, err := h.summaryProvider.Get(forceStatsUpdate) | 		summary, err = h.summaryProvider.Get(forceStatsUpdate) | ||||||
|  | 	} | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
| 		handleError(response, "/stats/summary", err) | 		handleError(response, "/stats/summary", err) | ||||||
| 	} else { | 	} else { | ||||||
|   | |||||||
| @@ -26,6 +26,8 @@ type SummaryProvider interface { | |||||||
| 	// Get provides a new Summary with the stats from Kubelet, | 	// Get provides a new Summary with the stats from Kubelet, | ||||||
| 	// and will update some stats if updateStats is true | 	// and will update some stats if updateStats is true | ||||||
| 	Get(updateStats bool) (*statsapi.Summary, error) | 	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. | // summaryProviderImpl implements the SummaryProvider interface. | ||||||
| @@ -87,3 +89,32 @@ func (sp *summaryProviderImpl) Get(updateStats bool) (*statsapi.Summary, error) | |||||||
| 	} | 	} | ||||||
| 	return &summary, nil | 	return &summary, nil | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func (sp *summaryProviderImpl) GetCPUAndMemoryStats() (*statsapi.Summary, error) { | ||||||
|  | 	summary, err := sp.Get(false) | ||||||
|  | 	if err != nil { | ||||||
|  | 		return nil, 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 | ||||||
|  | 	} | ||||||
|  | 	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 | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 	return summary, nil | ||||||
|  | } | ||||||
|   | |||||||
| @@ -32,7 +32,6 @@ import ( | |||||||
| 	statstest "k8s.io/kubernetes/pkg/kubelet/server/stats/testing" | 	statstest "k8s.io/kubernetes/pkg/kubelet/server/stats/testing" | ||||||
| ) | ) | ||||||
|  |  | ||||||
| func TestSummaryProvider(t *testing.T) { |  | ||||||
| var ( | var ( | ||||||
| 	podStats = []statsapi.PodStats{ | 	podStats = []statsapi.PodStats{ | ||||||
| 		{ | 		{ | ||||||
| @@ -65,6 +64,7 @@ func TestSummaryProvider(t *testing.T) { | |||||||
| 	rlimitStats = getRlimitStats() | 	rlimitStats = getRlimitStats() | ||||||
| ) | ) | ||||||
|  |  | ||||||
|  | func TestSummaryProviderGetStats(t *testing.T) { | ||||||
| 	assert := assert.New(t) | 	assert := assert.New(t) | ||||||
|  |  | ||||||
| 	mockStatsProvider := new(statstest.StatsProvider) | 	mockStatsProvider := new(statstest.StatsProvider) | ||||||
| @@ -130,6 +130,64 @@ func TestSummaryProvider(t *testing.T) { | |||||||
| 	assert.Equal(summary.Pods, podStats) | 	assert.Equal(summary.Pods, podStats) | ||||||
| } | } | ||||||
|  |  | ||||||
|  | func TestSummaryProviderGetCPUAndMemoryStats(t *testing.T) { | ||||||
|  | 	assert := assert.New(t) | ||||||
|  |  | ||||||
|  | 	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) | ||||||
|  |  | ||||||
|  | 	provider := NewSummaryProvider(mockStatsProvider) | ||||||
|  | 	summary, err := provider.GetCPUAndMemoryStats() | ||||||
|  | 	assert.NoError(err) | ||||||
|  |  | ||||||
|  | 	assert.Equal(summary.Node.NodeName, "test-node") | ||||||
|  | 	assert.Equal(summary.Node.StartTime, cgroupStatsMap["/"].cs.StartTime) | ||||||
|  | 	assert.Equal(summary.Node.CPU, cgroupStatsMap["/"].cs.CPU) | ||||||
|  | 	assert.Equal(summary.Node.Memory, cgroupStatsMap["/"].cs.Memory) | ||||||
|  | 	assert.Nil(summary.Node.Network) | ||||||
|  | 	assert.Nil(summary.Node.Fs) | ||||||
|  | 	assert.Nil(summary.Node.Runtime) | ||||||
|  |  | ||||||
|  | 	assert.Equal(len(summary.Node.SystemContainers), 4) | ||||||
|  | 	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{ | ||||||
|  | 		Name:      "kubelet", | ||||||
|  | 		StartTime: cgroupStatsMap["/kubelet"].cs.StartTime, | ||||||
|  | 		CPU:       cgroupStatsMap["/kubelet"].cs.CPU, | ||||||
|  | 		Memory:    cgroupStatsMap["/kubelet"].cs.Memory, | ||||||
|  | 	}) | ||||||
|  | 	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{ | ||||||
|  | 		Name:      "misc", | ||||||
|  | 		StartTime: cgroupStatsMap["/misc"].cs.StartTime, | ||||||
|  | 		CPU:       cgroupStatsMap["/misc"].cs.CPU, | ||||||
|  | 		Memory:    cgroupStatsMap["/misc"].cs.Memory, | ||||||
|  | 	}) | ||||||
|  | 	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{ | ||||||
|  | 		Name:      "runtime", | ||||||
|  | 		StartTime: cgroupStatsMap["/runtime"].cs.StartTime, | ||||||
|  | 		CPU:       cgroupStatsMap["/runtime"].cs.CPU, | ||||||
|  | 		Memory:    cgroupStatsMap["/runtime"].cs.Memory, | ||||||
|  | 	}) | ||||||
|  | 	assert.Contains(summary.Node.SystemContainers, statsapi.ContainerStats{ | ||||||
|  | 		Name:      "pods", | ||||||
|  | 		StartTime: cgroupStatsMap["/pods"].cs.StartTime, | ||||||
|  | 		CPU:       cgroupStatsMap["/pods"].cs.CPU, | ||||||
|  | 		Memory:    cgroupStatsMap["/pods"].cs.Memory, | ||||||
|  | 	}) | ||||||
|  | 	assert.Equal(summary.Pods, podStats) | ||||||
|  | } | ||||||
|  |  | ||||||
| func getFsStats() *statsapi.FsStats { | func getFsStats() *statsapi.FsStats { | ||||||
| 	f := fuzz.New().NilChance(0) | 	f := fuzz.New().NilChance(0) | ||||||
| 	v := &statsapi.FsStats{} | 	v := &statsapi.FsStats{} | ||||||
|   | |||||||
| @@ -636,6 +636,7 @@ type fakeResourceAnalyzer struct { | |||||||
|  |  | ||||||
| func (o *fakeResourceAnalyzer) Start()                                           {} | func (o *fakeResourceAnalyzer) Start()                                           {} | ||||||
| func (o *fakeResourceAnalyzer) Get(bool) (*statsapi.Summary, error)              { return nil, nil } | func (o *fakeResourceAnalyzer) Get(bool) (*statsapi.Summary, error)              { return nil, nil } | ||||||
|  | func (o *fakeResourceAnalyzer) GetCPUAndMemoryStats() (*statsapi.Summary, error) { return nil, nil } | ||||||
| func (o *fakeResourceAnalyzer) GetPodVolumeStats(uid types.UID) (serverstats.PodVolumeStats, bool) { | func (o *fakeResourceAnalyzer) GetPodVolumeStats(uid types.UID) (serverstats.PodVolumeStats, bool) { | ||||||
| 	return o.podVolumeStats, true | 	return o.podVolumeStats, true | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 k8s-ci-robot
					k8s-ci-robot