Fix cgroupv2 mem usage calculation to match docker cli
"cache" memory stat no longer exists in cgroupv2.
docker cli subtracts "inactive_file" for the overall mem usage
calculation, so do the same for cgroupv2.
closes
@@ -27,7 +27,7 @@ import (
// dockerStatsToContainerStats returns a new object of the ContainerStats object from docker stats.
func dockerStatsToContainerStats(dockerStats *types.StatsJSON) (*ContainerStats, error) {
cpuUsage := dockerStats.CPUStats.CPUUsage.TotalUsage / numCores
- memoryUsage := dockerStats.MemoryStats.Usage - dockerStats.MemoryStats.Stats["cache"]
+ memoryUsage := getMemUsage(dockerStats.MemoryStats)
storageReadBytes, storageWriteBytes := getStorageStats(dockerStats)
networkStats := getNetworkStats(dockerStats)
return &ContainerStats{
@@ -40,6 +40,21 @@ func dockerStatsToContainerStats(dockerStats *types.StatsJSON) (*ContainerStats,
}, nil
}
+func getMemUsage(mem types.MemoryStats) uint64 {
+ if config.CgroupV2 {
+ // for cgroupv2 systems, mem usage calculation uses the same method that the docker cli uses
+ // https://github.com/docker/cli/blob/e198123693b1aaa724041fff602c7d75c8fe4b57/cli/command/container/stats_helpers.go#L227-L249
+ // see https://github.com/aws/amazon-ecs-agent/issues/3323
+ if v, ok := mem.Stats["inactive_file"]; ok && v < mem.Usage {
+ return mem.Usage - v
+ }
+ }
+ if v, ok := mem.Stats["cache"]; ok && v < mem.Usage {
+ return mem.Usage - v
+ }
+ return mem.Usage
+}
+
func validateDockerStats(dockerStats *types.StatsJSON) error {
if config.CgroupV2 {
// PercpuUsage is not available in cgroupv2
