当容器达到内存限制时系统负载较高

当容器达到内存限制时系统负载较高

我的服务器最近崩溃了,因为 GitLab docker/nomad 容器达到了其定义的内存限制 (10G)。当达到限制时,容器 100% 的 cpu 时间都花在内核空间上。 (容器仅限于 4 个 cpu 核心。)最终主机锁定并且对 ssh 连接没有响应:

最后几分钟

内核日志没有表明任何 OOM 终止。我还注意到磁盘 io 激增,但我无法解释。

我尝试创建一个较小的示例,没有任何现有的 GitLab 数据,也没有 Nomad:

config=$(cat <<'EOS'
external_url 'https://xxxxxxxxx'
nginx['listen_port'] = 80
nginx['listen_https'] = false
nginx['proxy_set_headers'] = {
 'Host' => '$http_host_with_default',
 'X-Real-IP' => '$remote_addr',
 'X-Forwarded-For' => '$proxy_add_x_forwarded_for',
 'X-Forwarded-Proto' => 'https',
 'X-Forwarded-Ssl' => 'on',
 'Upgrade' => '$http_upgrade',
 'Connection' => '$connection_upgrade'
}
EOS
)

# Started with
docker run --rm -d --memory="5G" \
    --name testgitlab \
    --publish 10.0.0.1:9001:80 \
    -e "GITLAB_SSL=true" \
    -e "GITLAB_OMNIBUS_CONFIG=$config" \
    gitlab/gitlab-ce:latest

同样的事情也发生了。当容器达到 100% 系统负载时,我立即停止了容器(这次没有 cpu 限制): 格拉法纳截图

起初我以为这是 GitLab 中的一个错误,但我在自己的笔记本电脑上尝试了同样的操作,当达到内存限制时,OOM 杀手立即杀死了一个容器进程。这个问题在我用来运行 GitLab 容器的旧服务器上也从未出现过。

本文中提到的所有系统都没有任何特殊的 docker 设置,禁用了交换,仅修改了网络子系统中的 sysctl 设置。

  • 旧服务器:Debian 10
    • 来自buster-backports 的内核 (5.10.0-0.bpo.9-amd64)
    • 文件系统:md-raid 1 上的 btrfs(2x nvme ssd)
  • 当前服务器:Debian 11
    • Bullseye 内核 (5.10.0-9-amd64)bullseye-backports (5.14.0-0.bpo.2-amd64) 内核。两个内核都会出现问题。
    • 文件系统:btrfs on lvm on md-raid 1 (2x nvme ssds)
  • 我的笔记本电脑:Arch
    • 内核:5.15.5-arch1-1
    • 文件系统:lvm 上的 ext4、nvme ssd 上

当 GitLab 达到内存限制时,如何避免主机冻结?为什么它只影响我当前的服务器?

更新:我可以使用 sonatype/nexus 容器重现此行为。所以这不是 GitLab 的事情。

更新2:我注意到页面缓存未命中次数激增。或许原因是什么,只是cgroups?但为什么我的旧服务器或笔记本电脑没有受到影响?

更新3:当使用 mdraid1+lvm+btrfs 启动虚拟机时,我可以重现它!进一步调查...

答案1

听起来像是记忆在颠簸。容器内存不足,因此需要使用交换空间。写入交换空间会导致较高的内核和磁盘活动,因为内存交换是内核的功能,并且它会交换到磁盘。

相关内容