共计 1951 个字符,预计需要花费 5 分钟才能阅读完成。
最近在 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_bytes
和container_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_bytes
和 container_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 公布