Skip to content

Commit 6bbaf8c

Browse files
committed
Extend CRI stats provider to support PSI
1 parent 77118d4 commit 6bbaf8c

File tree

4 files changed

+103
-2
lines changed

4 files changed

+103
-2
lines changed

pkg/kubelet/stats/cri_stats_provider.go

+79-2
Original file line numberDiff line numberDiff line change
@@ -33,11 +33,13 @@ import (
3333
"google.golang.org/grpc/status"
3434
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3535
"k8s.io/apimachinery/pkg/types"
36+
utilfeature "k8s.io/apiserver/pkg/util/feature"
3637
internalapi "k8s.io/cri-api/pkg/apis"
3738
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
3839
"k8s.io/klog/v2"
3940
statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
4041
kubetypes "k8s.io/kubelet/pkg/types"
42+
"k8s.io/kubernetes/pkg/features"
4143
"k8s.io/kubernetes/pkg/kubelet/cadvisor"
4244
"k8s.io/kubernetes/pkg/kubelet/server/stats"
4345
"k8s.io/utils/clock"
@@ -211,6 +213,7 @@ func (p *criStatsProvider) listPodStatsPartiallyFromCRI(ctx context.Context, upd
211213
p.addPodNetworkStats(ps, podSandboxID, caInfos, cs, containerNetworkStats[podSandboxID])
212214
p.addPodCPUMemoryStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs)
213215
p.addSwapStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs)
216+
p.addIOStats(ps, types.UID(podSandbox.Metadata.Uid), allInfos, cs)
214217

215218
// If cadvisor stats is available for the container, use it to populate
216219
// container stats
@@ -260,6 +263,7 @@ func (p *criStatsProvider) listPodStatsStrictlyFromCRI(ctx context.Context, upda
260263
addCRIPodCPUStats(ps, criSandboxStat)
261264
addCRIPodMemoryStats(ps, criSandboxStat)
262265
addCRIPodProcessStats(ps, criSandboxStat)
266+
addCRIPodIOStats(ps, criSandboxStat)
263267
makePodStorageStats(ps, rootFsInfo, p.resourceAnalyzer, p.hostStatsProvider, true)
264268
summarySandboxStats = append(summarySandboxStats, *ps)
265269
}
@@ -535,6 +539,7 @@ func (p *criStatsProvider) addPodCPUMemoryStats(
535539
usageNanoCores := getUint64Value(cs.CPU.UsageNanoCores) + getUint64Value(ps.CPU.UsageNanoCores)
536540
ps.CPU.UsageCoreNanoSeconds = &usageCoreNanoSeconds
537541
ps.CPU.UsageNanoCores = &usageNanoCores
542+
// Pod level PSI stats cannot be calculated from container level
538543
}
539544

540545
if cs.Memory != nil {
@@ -555,6 +560,7 @@ func (p *criStatsProvider) addPodCPUMemoryStats(
555560
ps.Memory.RSSBytes = &rSSBytes
556561
ps.Memory.PageFaults = &pageFaults
557562
ps.Memory.MajorPageFaults = &majorPageFaults
563+
// Pod level PSI stats cannot be calculated from container level
558564
}
559565
}
560566

@@ -564,14 +570,14 @@ func (p *criStatsProvider) addSwapStats(
564570
allInfos map[string]cadvisorapiv2.ContainerInfo,
565571
cs *statsapi.ContainerStats,
566572
) {
567-
// try get cpu and memory stats from cadvisor first.
573+
// try get swap stats from cadvisor first.
568574
podCgroupInfo := getCadvisorPodInfoFromPodUID(podUID, allInfos)
569575
if podCgroupInfo != nil {
570576
ps.Swap = cadvisorInfoToSwapStats(podCgroupInfo)
571577
return
572578
}
573579

574-
// Sum Pod cpu and memory stats from containers stats.
580+
// Sum Pod swap stats from containers stats.
575581
if cs.Swap != nil {
576582
if ps.Swap == nil {
577583
ps.Swap = &statsapi.SwapStats{Time: cs.Swap.Time}
@@ -583,6 +589,30 @@ func (p *criStatsProvider) addSwapStats(
583589
}
584590
}
585591

592+
func (p *criStatsProvider) addIOStats(
593+
ps *statsapi.PodStats,
594+
podUID types.UID,
595+
allInfos map[string]cadvisorapiv2.ContainerInfo,
596+
cs *statsapi.ContainerStats,
597+
) {
598+
if !utilfeature.DefaultFeatureGate.Enabled(features.KubeletPSI) {
599+
return
600+
}
601+
// try get IO stats from cadvisor first.
602+
podCgroupInfo := getCadvisorPodInfoFromPodUID(podUID, allInfos)
603+
if podCgroupInfo != nil {
604+
ps.IO = cadvisorInfoToIOStats(podCgroupInfo)
605+
return
606+
}
607+
608+
if cs.IO != nil {
609+
if ps.IO == nil {
610+
ps.IO = &statsapi.IOStats{Time: cs.IO.Time}
611+
}
612+
// Pod level PSI stats cannot be calculated from container level
613+
}
614+
}
615+
586616
func (p *criStatsProvider) addProcessStats(
587617
ps *statsapi.PodStats,
588618
container *cadvisorapiv2.ContainerInfo,
@@ -624,6 +654,7 @@ func (p *criStatsProvider) makeContainerStats(
624654
if usageNanoCores != nil {
625655
result.CPU.UsageNanoCores = usageNanoCores
626656
}
657+
result.CPU.PSI = makePSIStats(stats.Cpu.Psi)
627658
} else {
628659
result.CPU.Time = metav1.NewTime(time.Unix(0, time.Now().UnixNano()))
629660
result.CPU.UsageCoreNanoSeconds = uint64Ptr(0)
@@ -634,6 +665,7 @@ func (p *criStatsProvider) makeContainerStats(
634665
if stats.Memory.WorkingSetBytes != nil {
635666
result.Memory.WorkingSetBytes = &stats.Memory.WorkingSetBytes.Value
636667
}
668+
result.Memory.PSI = makePSIStats(stats.Memory.Psi)
637669
} else {
638670
result.Memory.Time = metav1.NewTime(time.Unix(0, time.Now().UnixNano()))
639671
result.Memory.WorkingSetBytes = uint64Ptr(0)
@@ -651,6 +683,15 @@ func (p *criStatsProvider) makeContainerStats(
651683
result.Swap.SwapUsageBytes = uint64Ptr(0)
652684
result.Swap.SwapAvailableBytes = uint64Ptr(0)
653685
}
686+
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPSI) {
687+
result.IO = &statsapi.IOStats{}
688+
if stats.Io != nil {
689+
result.IO.Time = metav1.NewTime(time.Unix(0, stats.Io.Timestamp))
690+
result.IO.PSI = makePSIStats(stats.Io.Psi)
691+
} else {
692+
result.IO.Time = metav1.NewTime(time.Unix(0, time.Now().UnixNano()))
693+
}
694+
}
654695
if stats.WritableLayer != nil {
655696
result.Rootfs.Time = metav1.NewTime(time.Unix(0, stats.WritableLayer.Timestamp))
656697
if stats.WritableLayer.UsedBytes != nil {
@@ -714,6 +755,7 @@ func (p *criStatsProvider) makeContainerCPUAndMemoryStats(
714755
if usageNanoCores != nil {
715756
result.CPU.UsageNanoCores = usageNanoCores
716757
}
758+
result.CPU.PSI = makePSIStats(stats.Cpu.Psi)
717759
} else {
718760
result.CPU.Time = metav1.NewTime(time.Unix(0, time.Now().UnixNano()))
719761
result.CPU.UsageCoreNanoSeconds = uint64Ptr(0)
@@ -724,6 +766,7 @@ func (p *criStatsProvider) makeContainerCPUAndMemoryStats(
724766
if stats.Memory.WorkingSetBytes != nil {
725767
result.Memory.WorkingSetBytes = &stats.Memory.WorkingSetBytes.Value
726768
}
769+
result.Memory.PSI = makePSIStats(stats.Memory.Psi)
727770
} else {
728771
result.Memory.Time = metav1.NewTime(time.Unix(0, time.Now().UnixNano()))
729772
result.Memory.WorkingSetBytes = uint64Ptr(0)
@@ -732,6 +775,33 @@ func (p *criStatsProvider) makeContainerCPUAndMemoryStats(
732775
return result
733776
}
734777

778+
func makePSIStats(stats *runtimeapi.PsiStats) *statsapi.PSIStats {
779+
if !utilfeature.DefaultFeatureGate.Enabled(features.KubeletPSI) {
780+
return nil
781+
}
782+
if stats == nil {
783+
return nil
784+
}
785+
result := &statsapi.PSIStats{}
786+
if stats.Full != nil {
787+
result.Full = statsapi.PSIData{
788+
Total: stats.Full.Total,
789+
Avg10: stats.Full.Avg10,
790+
Avg60: stats.Full.Avg60,
791+
Avg300: stats.Full.Avg300,
792+
}
793+
}
794+
if stats.Some != nil {
795+
result.Some = statsapi.PSIData{
796+
Total: stats.Some.Total,
797+
Avg10: stats.Some.Avg10,
798+
Avg60: stats.Some.Avg60,
799+
Avg300: stats.Some.Avg300,
800+
}
801+
}
802+
return result
803+
}
804+
735805
// getContainerUsageNanoCores first attempts to get the usage nano cores from the stats reported
736806
// by the CRI. If it is unable to, it gets the information from the cache instead.
737807
func (p *criStatsProvider) getContainerUsageNanoCores(stats *runtimeapi.ContainerStats) *uint64 {
@@ -910,6 +980,13 @@ func (p *criStatsProvider) addCadvisorContainerStats(
910980
if swap != nil {
911981
cs.Swap = swap
912982
}
983+
984+
if utilfeature.DefaultFeatureGate.Enabled(features.KubeletPSI) {
985+
io := cadvisorInfoToIOStats(caPodStats)
986+
if io != nil {
987+
cs.IO = io
988+
}
989+
}
913990
}
914991

915992
func (p *criStatsProvider) addCadvisorContainerCPUAndMemoryStats(

pkg/kubelet/stats/cri_stats_provider_linux.go

+18
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,10 @@ import (
2525

2626
cadvisorapiv2 "github.com/google/cadvisor/info/v2"
2727
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
utilfeature "k8s.io/apiserver/pkg/util/feature"
2829
runtimeapi "k8s.io/cri-api/pkg/apis/runtime/v1"
2930
statsapi "k8s.io/kubelet/pkg/apis/stats/v1alpha1"
31+
"k8s.io/kubernetes/pkg/features"
3032
)
3133

3234
func (p *criStatsProvider) addCRIPodContainerStats(criSandboxStat *runtimeapi.PodSandboxStats,
@@ -79,6 +81,7 @@ func addCRIPodMemoryStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandb
7981
RSSBytes: valueOfUInt64Value(criMemory.RssBytes),
8082
PageFaults: valueOfUInt64Value(criMemory.PageFaults),
8183
MajorPageFaults: valueOfUInt64Value(criMemory.MajorPageFaults),
84+
PSI: makePSIStats(criMemory.Psi),
8285
}
8386
}
8487

@@ -91,6 +94,21 @@ func addCRIPodCPUStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxS
9194
Time: metav1.NewTime(time.Unix(0, criCPU.Timestamp)),
9295
UsageNanoCores: valueOfUInt64Value(criCPU.UsageNanoCores),
9396
UsageCoreNanoSeconds: valueOfUInt64Value(criCPU.UsageCoreNanoSeconds),
97+
PSI: makePSIStats(criCPU.Psi),
98+
}
99+
}
100+
101+
func addCRIPodIOStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxStats) {
102+
if !utilfeature.DefaultFeatureGate.Enabled(features.KubeletPSI) {
103+
return
104+
}
105+
if criPodStat == nil || criPodStat.Linux == nil || criPodStat.Linux.Io == nil {
106+
return
107+
}
108+
criIO := criPodStat.Linux.Io
109+
ps.IO = &statsapi.IOStats{
110+
Time: metav1.NewTime(time.Unix(0, criIO.Timestamp)),
111+
PSI: makePSIStats(criIO.Psi),
94112
}
95113
}
96114

pkg/kubelet/stats/cri_stats_provider_others.go

+3
Original file line numberDiff line numberDiff line change
@@ -50,3 +50,6 @@ func addCRIPodCPUStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxS
5050

5151
func addCRIPodProcessStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxStats) {
5252
}
53+
54+
func addCRIPodIOStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxStats) {
55+
}

pkg/kubelet/stats/cri_stats_provider_windows.go

+3
Original file line numberDiff line numberDiff line change
@@ -236,6 +236,9 @@ func addCRIPodMemoryStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandb
236236
}
237237
}
238238

239+
func addCRIPodIOStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxStats) {
240+
}
241+
239242
func addCRIPodProcessStats(ps *statsapi.PodStats, criPodStat *runtimeapi.PodSandboxStats) {
240243
if criPodStat == nil || criPodStat.Windows == nil || criPodStat.Windows.Process == nil {
241244
return

0 commit comments

Comments
 (0)