具有大量可用内存的永久交换

具有大量可用内存的永久交换

我们有一台运行 Debian 4.0.5(内核 4.0.0-2)的 Linux 服务器,安装了 32G RAM 并配置了 16G Swap。该系统使用 lxc 容器进行划分,但这在这里并不重要。该问题存在于不同容器的内部和外部。

这是一个典型的free -h

              total        used        free      shared  buff/cache   available
Mem:            28G        2.1G         25G         15M        936M         26G
Swap:           15G        1.4G         14G

/proc/meminfo

Committed_AS:   12951172 kB

因此,即使分配的所有内容实际上都被立即使用,仍然有大量的可用内存。然而,系统甚至会立即对正在运行的进程进行分页。

这在 Gitlab 中最为显着,这是一个使用 Unicorn 的 Rails 应用程序:新分叉的 Unicorn 工作线程会立即交换,当收到请求时,需要以约 1400kB/s 的速度从磁盘读取(数据来自iotop),并会遇到超时(目前为 30 秒) ,以使其及时重新启动。正常请求在完全加载到内存之前不应花费超过 5 秒,从而立即被杀死。请注意,这只是一个示例,我已经看到这种情况发生在 redis、amavis、postgres、mysql、java(openjdk) 等上。

否则系统处于低负载情况,CPU 利用率约为 5%,平均负载约为 2(在 8 个内核上)。

我们尝试过的(排名不分先后):

  1. swapoff -a: 800M左右失败仍然交换
  2. 使用 减少交换性(逐步)sysctl vm.swappiness=NN。这似乎根本没有影响,我们降到了 0%,但仍然存在完全相同的行为
  3. 停止非必要的服务(Gitlab,一个基于 Jetty 的网络应用程序......),释放约。 8G 已提交但未映射的内存,并将 Comfilled_AS 减少到大约 5G。一点变化都没有。
  4. 使用 清除系统缓存sync && echo 3 > /proc/sys/vm/drop_caches。这会释放内存,但对交换情况没有任何作用。
  5. 上述的组合

重新启动机器以通过 fstab 完全禁用交换作为测试并不是真正的选择,因为某些服务存在可用性问题并且需要计划停机时间,而不是“四处寻找”......而且我们真的不想禁用交换作为倒退。

我不明白为什么这里会发生任何交换。有什么想法可能会发生什么吗?


这个问题已经存在了一段时间了,但它首先出现在高IO负载(长时间的后台数据处理任务)期间,所以我无法确定具体的事件。这个任务已经完成几天了,问题仍然存在,因此这个问题。

答案1

记住我是怎么说的:

该系统使用 lxc 容器进行划分,但这在这里并不重要。

好吧,事实证明做过事情。或者更确切地说,处于 lxc 核心的 cgroup 很重要。

主机只能看到内核升级时的重新启动。那么,最后使用的内核是什么? 3.19,两个月前被 4.0.5 取代,昨天被 4.1.3 取代。昨天发生了什么?左、右、中的进程被 memkilled。经检查/var/log/kern.log,受影响的进程位于内存为512M的cgroup中。等等,512M?这是不对的(当预期要求约为 4G 时!)。事实证明,这正是我们几个月前设置时在 lxc 配置中配置的内容。

所以,3.19 完全忽略了 cgroup 的内存限制;如果 cgroup 需要的数量超过允许的数量,4.0.5 总是进行分页(这是这个问题的核心问题),并且只有 4.1.3 执行完整的 memkiller-sweep。

主机系统的交换性对此没有影响,因为它从来没有接近物理内存不足的情况。

解决方案:

对于临时更改,您可以直接修改 cgroup,例如调用名为box1cgroup 的lxc 容器lxc/box1,并且您可以执行(作为主机中的 root):

$ echo 8G > /sys/fs/cgroup/memory/lxc/box1/memory.limit_in_bytes

永久的解决方案是正确配置容器/var/lb/lxc/...

lxc.cgroup.memory.limit_in_bytes = 8G

故事的道德启示:始终检查您的配置。即使您认为这不可能是问题(并且内核中存在不同的错误/不一致实际上会失败)。

相关内容