From 7c53a463b2f0c2659f0671615e768211b2ce7cbf Mon Sep 17 00:00:00 2001 From: Giuseppe Scrivano Date: Fri, 19 May 2023 11:54:08 +0200 Subject: [PATCH] stats: get mem limit from the cgroup b25b330306782019d7aaf7618cd4598a9ae87250 introduced this behaviour. It was fine at the time because we didn't support "container update", so the limit could not be changed at runtime. Since it is not possible to change the memory limit at runtime, read the limit as reported from the cgroup. https://github.com/containers/crun/pull/1217 is required for crun. Closes: https://github.com/containers/podman/issues/18621 Signed-off-by: Giuseppe Scrivano --- libpod/stats_linux.go | 12 ++---------- test/e2e/stats_test.go | 35 +++++++++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 10 deletions(-) diff --git a/libpod/stats_linux.go b/libpod/stats_linux.go index 5eb0449383..e84d85c33f 100644 --- a/libpod/stats_linux.go +++ b/libpod/stats_linux.go @@ -5,7 +5,6 @@ package libpod import ( "fmt" - "math" "strings" "syscall" "time" @@ -59,7 +58,7 @@ func (c *Container) getPlatformContainerStats(stats *define.ContainerStats, prev // calc the average cpu usage for the time the container is running stats.AvgCPU = calculateCPUPercent(cgroupStats, 0, now, uint64(c.state.StartedTime.UnixNano())) stats.MemUsage = cgroupStats.MemoryStats.Usage.Usage - stats.MemLimit = c.getMemLimit() + stats.MemLimit = c.getMemLimit(cgroupStats.MemoryStats.Usage.Limit) stats.MemPerc = (float64(stats.MemUsage) / float64(stats.MemLimit)) * 100 stats.PIDs = 0 if conState == define.ContainerStateRunning || conState == define.ContainerStatePaused { @@ -83,14 +82,7 @@ func (c *Container) getPlatformContainerStats(stats *define.ContainerStats, prev } // getMemory limit returns the memory limit for a container -func (c *Container) getMemLimit() uint64 { - memLimit := uint64(math.MaxUint64) - - resources := c.LinuxResources() - if resources != nil && resources.Memory != nil && resources.Memory.Limit != nil { - memLimit = uint64(*resources.Memory.Limit) - } - +func (c *Container) getMemLimit(memLimit uint64) uint64 { si := &syscall.Sysinfo_t{} err := syscall.Sysinfo(si) if err != nil { diff --git a/test/e2e/stats_test.go b/test/e2e/stats_test.go index c738250b0e..656ef30c4e 100644 --- a/test/e2e/stats_test.go +++ b/test/e2e/stats_test.go @@ -3,6 +3,7 @@ package integration import ( "fmt" "strconv" + "strings" "time" . "github.com/containers/podman/v4/test/utils" @@ -181,6 +182,9 @@ var _ = Describe("Podman stats", func() { // Regression test for #8265 It("podman stats with custom memory limits", func() { + if strings.Contains(podmanTest.OCIRuntime, "crun") { + Skip("Test requires crun > 1.8.4") + } // Run three containers. One with a memory limit. Make sure // that the limits are different and the limited one has a // lower limit. @@ -229,4 +233,35 @@ var _ = Describe("Podman stats", func() { session.WaitWithDefaultTimeout() Expect(session).Should(Exit(0)) }) + + It("podman stats show cgroup memory limit", func() { + if strings.Contains(podmanTest.OCIRuntime, "crun") { + Skip("Test requires crun > 1.8.4") + } + ctrWithLimit := "with-limit" + + session := podmanTest.Podman([]string{"run", "-d", "--name", ctrWithLimit, "--memory", "50m", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrWithLimit}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + limit, err := strconv.Atoi(session.OutputToString()) + Expect(err).ToNot(HaveOccurred()) + Expect(limit).To(BeNumerically("==", 50*1024*1024)) + + session = podmanTest.Podman([]string{"container", "update", ctrWithLimit, "--memory", "100m"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"stats", "--no-stream", "--format", "{{.MemLimit}}", ctrWithLimit}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + limit, err = strconv.Atoi(session.OutputToString()) + Expect(err).ToNot(HaveOccurred()) + Expect(limit).To(BeNumerically("==", 100*1024*1024)) + }) })