乐趣区

关于云计算:正确监控容器-OOMKill-的指标译

最近在 Splunk 工作不久,一个共事在 Slack 上找到我,问起我之前一篇对于《Kubernetes 指标》的博文。

他的问题是对于 OOMKiller 应用是容器里哪个 “memory usage“的指标来决定是否应该杀死一个容器。我在那篇文章中提出的论断是。

你可能认为用 container_memory_usage_bytes 来跟踪内存利用率很容易,然而,这个指标也包含缓存(想想文件系统缓存)数据,这些数据在内存压力下可能会被驱赶。更好的指标是container_memory_working_set_bytes,因为这是 OOM 杀手关注的。

这是这篇文章中最外围的阐述,所以我决定我须要模仿这次行为。让咱们看看 OOMKiller 在察看哪些指标。

我做了一个小东西,它会一直地分配内存,直到 OOMKiller 参加进来并杀死 pod 中的容器。


package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {memoryTicker := time.NewTicker(time.Millisecond * 5)
    leak := make(map[int][]byte)
    i := 0

    go func() {
        for range memoryTicker.C {leak[i] = make([]byte, 1024)
            i++
        }
    }()
    
    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8081", nil)
}

见它部署在 minikube 中,并将内存申请和限度都设置为 128MB,咱们能够看到 container_memory_usage_bytescontainer_memory_working_set_bytes简直 1:1 地互相跟踪。当它们都达到容器上设置的极限时,OOMKiller 就会杀死容器,过程从新开始。

因为 container_memory_usage_bytes 也跟踪过程所应用的文件系统缓存,所以我又优化了下小工具,以便将数据间接写到文件系统上的一个文件。

package main

import (
    "fmt"
    "net/http"
    "time"

    "github.com/prometheus/client_golang/prometheus/promhttp"
)

func main() {memoryTicker := time.NewTicker(time.Millisecond * 5)
    leak := make(map[int][]byte)
    i := 0

    go func() {
        for range memoryTicker.C {leak[i] = make([]byte, 1024)
            i++
        }
    }()

    fileTicker := time.NewTicker(time.Millisecond * 5)
    go func() {os.Create("/tmp/file")
        buffer := make([]byte, 1024)
        defer f.Close()

        for range fileTicker.C {f.Write(buffer)
            f.Sync()}
    }()

    http.Handle("/metrics", promhttp.Handler())
    http.ListenAndServe(":8081", nil)
}

在引入文件系统缓存后,咱们开始看到 container_memory_usage_bytescontainer_memory_working_set_bytes 开始呈现分叉

当初乏味的是,容器依然不容许应用超过容器极限的内存量,然而 OOMKiller container_memory_working_set_bytes达到内存极限时才会杀死容器。

这种行为的另一个乏味的方面是,container_memory_usage_bytes在容器的内存极限时达到了顶点,然而数据还是持续在往磁盘写入。

如果咱们再看一下 container_memory_cache,咱们会发现,在container_memory_usage_bytes 达到极限之前,应用的缓存量继续减少,而后开始缩小。

从这个试验中, 咱们能够看到,container_memory_usage_bytes的确占用了一些正在被缓存的文件系统页面。咱们还能够看到,OOMKiller正在追踪 container_memory_working_set_bytes。这是有情理的,因为共享文件系统的缓存页能够在任何时候在内存中被驱赶。 咱们仅仅因为应用磁盘 I / O 而杀死过程是没有意义的。**

本文由博客群发一文多发等经营工具平台 OpenWrite 公布

退出移动版