我的服务器最近崩溃了,因为 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
听起来像是记忆在颠簸。容器内存不足,因此需要使用交换空间。写入交换空间会导致较高的内核和磁盘活动,因为内存交换是内核的功能,并且它会交换到磁盘。