stats: get mem limit from the cgroup

b25b330306 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 <gscrivan@redhat.com>
This commit is contained in:
Giuseppe Scrivano 2023-05-19 11:54:08 +02:00
parent a58ea23b17
commit 7c53a463b2
No known key found for this signature in database
GPG Key ID: 67E38F7A8BA21772
2 changed files with 37 additions and 10 deletions

View File

@ -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 {

View File

@ -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))
})
})