Skip to content

Commit e9d9a82

Browse files
authored
Merge pull request kubernetes#124101 from haircommander/process_stats-with-pid-fix
kubelet: fix PID based eviction
2 parents 9edabd6 + 0979ba9 commit e9d9a82

File tree

7 files changed

+82
-16
lines changed

7 files changed

+82
-16
lines changed

pkg/kubelet/eviction/helpers.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -738,7 +738,6 @@ func process(stats statsFunc) cmpFunc {
738738

739739
p1Process := processUsage(p1Stats.ProcessStats)
740740
p2Process := processUsage(p2Stats.ProcessStats)
741-
// prioritize evicting the pod which has the larger consumption of process
742741
return int(p2Process - p1Process)
743742
}
744743
}

pkg/kubelet/stats/cadvisor_stats_provider.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ func (p *cadvisorStatsProvider) ListPodStats(_ context.Context) ([]statsapi.PodS
139139
}
140140
podStats.Containers = append(podStats.Containers, *containerStat)
141141
}
142+
// Either way, collect process stats
143+
podStats.ProcessStats = mergeProcessStats(podStats.ProcessStats, cadvisorInfoToProcessStats(&cinfo))
142144
}
143145

144146
// Add each PodStats to the result.
@@ -154,7 +156,7 @@ func (p *cadvisorStatsProvider) ListPodStats(_ context.Context) ([]statsapi.PodS
154156
podStats.CPU = cpu
155157
podStats.Memory = memory
156158
podStats.Swap = cadvisorInfoToSwapStats(podInfo)
157-
podStats.ProcessStats = cadvisorInfoToProcessStats(podInfo)
159+
// ProcessStats were accumulated as the containers were iterated.
158160
}
159161

160162
status, found := p.statusProvider.GetPodStatus(podUID)

pkg/kubelet/stats/cri_stats_provider.go

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,6 @@ func (p *criStatsProvider) listPodStatsPartiallyFromCRI(ctx context.Context, upd
211211
p.addPodNetworkStats(ps, podSandboxID, caInfos, cs, containerNetworkStats[podSandboxID])
212212
p.addPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs)
213213
p.addSwapStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs)
214-
p.addProcessStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs)
215214

216215
// If cadvisor stats is available for the container, use it to populate
217216
// container stats
@@ -220,7 +219,9 @@ func (p *criStatsProvider) listPodStatsPartiallyFromCRI(ctx context.Context, upd
220219
klog.V(5).InfoS("Unable to find cadvisor stats for container", "containerID", containerID)
221220
} else {
222221
p.addCadvisorContainerStats(cs, &caStats)
222+
p.addProcessStats(ps, &caStats)
223223
}
224+
224225
ps.Containers = append(ps.Containers, *cs)
225226
}
226227
// cleanup outdated caches.
@@ -584,16 +585,11 @@ func (p *criStatsProvider) addSwapStats(
584585

585586
func (p *criStatsProvider) addProcessStats(
586587
ps *statsapi.PodStats,
587-
podUID types.UID,
588-
allInfos map[string]cadvisorapiv2.ContainerInfo,
589-
cs *statsapi.ContainerStats,
588+
container *cadvisorapiv2.ContainerInfo,
590589
) {
591-
// try get process stats from cadvisor only.
592-
info := getCadvisorPodInfoFromPodUID(podUID, allInfos)
593-
if info != nil {
594-
ps.ProcessStats = cadvisorInfoToProcessStats(info)
595-
return
596-
}
590+
processStats := cadvisorInfoToProcessStats(container)
591+
// Sum up all of the process stats for each of the containers to obtain the cumulative pod level process count
592+
ps.ProcessStats = mergeProcessStats(ps.ProcessStats, processStats)
597593
}
598594

599595
func (p *criStatsProvider) makeContainerStats(

pkg/kubelet/stats/helper.go

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -168,6 +168,31 @@ func cadvisorInfoToProcessStats(info *cadvisorapiv2.ContainerInfo) *statsapi.Pro
168168
return &statsapi.ProcessStats{ProcessCount: uint64Ptr(num)}
169169
}
170170

171+
func mergeProcessStats(first *statsapi.ProcessStats, second *statsapi.ProcessStats) *statsapi.ProcessStats {
172+
if first == nil && second == nil {
173+
return nil
174+
}
175+
176+
if first == nil {
177+
return second
178+
}
179+
if second == nil {
180+
return first
181+
}
182+
183+
firstProcessCount := uint64(0)
184+
if first.ProcessCount != nil {
185+
firstProcessCount = *first.ProcessCount
186+
}
187+
188+
secondProcessCount := uint64(0)
189+
if second.ProcessCount != nil {
190+
secondProcessCount = *second.ProcessCount
191+
}
192+
193+
return &statsapi.ProcessStats{ProcessCount: uint64Ptr(firstProcessCount + secondProcessCount)}
194+
}
195+
171196
// cadvisorInfoToNetworkStats returns the statsapi.NetworkStats converted from
172197
// the container info from cadvisor.
173198
func cadvisorInfoToNetworkStats(info *cadvisorapiv2.ContainerInfo) *statsapi.NetworkStats {

pkg/kubelet/stats/helper_test.go

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,12 @@ import (
2222

2323
cadvisorapiv1 "github.com/google/cadvisor/info/v1"
2424
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
25+
"github.com/google/go-cmp/cmp"
2526
"github.com/stretchr/testify/assert"
2627

2728
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2829
statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
30+
"k8s.io/utils/ptr"
2931
)
3032

3133
func TestCustomMetrics(t *testing.T) {
@@ -97,3 +99,44 @@ func TestCustomMetrics(t *testing.T) {
9799
Value: 2.1,
98100
})
99101
}
102+
103+
func TestMergeProcessStats(t *testing.T) {
104+
for _, tc := range []struct {
105+
desc string
106+
first *statsapi.ProcessStats
107+
second *statsapi.ProcessStats
108+
expected *statsapi.ProcessStats
109+
}{
110+
{
111+
desc: "both nil",
112+
first: nil,
113+
second: nil,
114+
expected: nil,
115+
},
116+
{
117+
desc: "first non-nil, second not",
118+
first: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](100)},
119+
second: nil,
120+
expected: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](100)},
121+
},
122+
{
123+
desc: "first nil, second non-nil",
124+
first: nil,
125+
second: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](100)},
126+
expected: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](100)},
127+
},
128+
{
129+
desc: "both non nill",
130+
first: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](100)},
131+
second: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](100)},
132+
expected: &statsapi.ProcessStats{ProcessCount: ptr.To[uint64](200)},
133+
},
134+
} {
135+
t.Run(tc.desc, func(t *testing.T) {
136+
got := mergeProcessStats(tc.first, tc.second)
137+
if diff := cmp.Diff(tc.expected, got); diff != "" {
138+
t.Fatalf("Unexpected diff on process stats (-want,+got):\n%s", diff)
139+
}
140+
})
141+
}
142+
}

test/e2e_node/eviction_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -475,6 +475,7 @@ var _ = SIGDescribe("PriorityPidEvictionOrdering", framework.WithSlow(), framewo
475475

476476
highPriorityClassName := f.BaseName + "-high-priority"
477477
highPriority := int32(999999999)
478+
processes := 30000
478479

479480
ginkgo.Context(fmt.Sprintf(testContextFmt, expectedNodeCondition), func() {
480481
tempSetCurrentKubeletConfig(f, func(ctx context.Context, initialConfig *kubeletconfig.KubeletConfiguration) {
@@ -497,15 +498,15 @@ var _ = SIGDescribe("PriorityPidEvictionOrdering", framework.WithSlow(), framewo
497498
specs := []podEvictSpec{
498499
{
499500
evictionPriority: 2,
500-
pod: pidConsumingPod("fork-bomb-container-with-low-priority", 12000),
501+
pod: pidConsumingPod("fork-bomb-container-with-low-priority", processes),
501502
},
502503
{
503504
evictionPriority: 0,
504505
pod: innocentPod(),
505506
},
506507
{
507508
evictionPriority: 1,
508-
pod: pidConsumingPod("fork-bomb-container-with-high-priority", 12000),
509+
pod: pidConsumingPod("fork-bomb-container-with-high-priority", processes),
509510
},
510511
}
511512
specs[1].pod.Spec.PriorityClassName = highPriorityClassName
@@ -524,7 +525,7 @@ var _ = SIGDescribe("PriorityPidEvictionOrdering", framework.WithSlow(), framewo
524525
specs := []podEvictSpec{
525526
{
526527
evictionPriority: 1,
527-
pod: pidConsumingPod("fork-bomb-container", 30000),
528+
pod: pidConsumingPod("fork-bomb-container", processes),
528529
wantPodDisruptionCondition: ptr.To(v1.DisruptionTarget),
529530
},
530531
}

test/e2e_node/summary_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,7 @@ var _ = SIGDescribe("Summary API", framework.WithNodeConformance(), func() {
259259
"InodesUsed": bounded(0, 1e8),
260260
}),
261261
"ProcessStats": ptrMatchAllFields(gstruct.Fields{
262-
"ProcessCount": bounded(0, 1e8),
262+
"ProcessCount": bounded(1, 1e8),
263263
}),
264264
})
265265

0 commit comments

Comments
 (0)