diff --git a/pkg/kubelet/stats/cri_stats_provider.go b/pkg/kubelet/stats/cri_stats_provider.go index bdce37a4cc75..829fc2659f78 100644 --- a/pkg/kubelet/stats/cri_stats_provider.go +++ b/pkg/kubelet/stats/cri_stats_provider.go @@ -649,7 +649,7 @@ func (p *criStatsProvider) getAndUpdateContainerUsageNanoCores(stats *runtimeapi defer p.mutex.Unlock() cached, ok := p.cpuUsageCache[id] - if !ok || cached.stats.UsageCoreNanoSeconds == nil { + if !ok || cached.stats.UsageCoreNanoSeconds == nil || stats.Cpu.UsageCoreNanoSeconds.Value < cached.stats.UsageCoreNanoSeconds.Value { // Cannot compute the usage now, but update the cached stats anyway p.cpuUsageCache[id] = &cpuUsageRecord{stats: stats.Cpu, usageNanoCores: nil} return nil, nil diff --git a/pkg/kubelet/stats/cri_stats_provider_test.go b/pkg/kubelet/stats/cri_stats_provider_test.go index c55b37d5b4d5..70f5d17bf913 100644 --- a/pkg/kubelet/stats/cri_stats_provider_test.go +++ b/pkg/kubelet/stats/cri_stats_provider_test.go @@ -881,8 +881,32 @@ func TestGetContainerUsageNanoCores(t *testing.T) { }, expected: &value2, }, + { + desc: "should return nil if cpuacct is reset to 0 in a live container", + stats: &runtimeapi.ContainerStats{ + Attributes: &runtimeapi.ContainerAttributes{ + Id: "1", + }, + Cpu: &runtimeapi.CpuUsage{ + Timestamp: 2, + UsageCoreNanoSeconds: &runtimeapi.UInt64Value{ + Value: 0, + }, + }, + }, + cpuUsageCache: map[string]*cpuUsageRecord{ + "1": { + stats: &runtimeapi.CpuUsage{ + Timestamp: 1, + UsageCoreNanoSeconds: &runtimeapi.UInt64Value{ + Value: 10000000000, + }, + }, + }, + }, + expected: nil, + }, } - for _, test := range tests { provider := &criStatsProvider{cpuUsageCache: test.cpuUsageCache} // Before the update, the cached value should be nil