长话短说

长话短说

我们正在 AWS EC2 内的 Centos7 之上构建的 Jenkins 实例中构建或运行 Docker 容器。我们有 2 个 t2.medium 实例,配有 2 个 CPU 和 3.5 GB 可用内存。
在一种情况下,我们在另一个容器中构建容器,我们只是拉动它们并运行(不同的容器)。

我们开始出现错误

open /var/lib/docker/overlay/<sha>-init/merged/dev/console: cannot allocate memory

我们journalctl得到

page allocation failure: order:4

运行页面缓存转储可以暂时解决该问题

echo 1 > /proc/sys/vm/drop_caches

所以我注意到,在运行 docker 任务时,Dirty内存块会出现峰值(正如它应该的那样)并Mapped在其之后跳转。然而,DirectMap4k相对接近这个跳跃。

例如:
闲置机

cat /proc/meminfo | grep -P "(Dirty|Mapped|DirectMap4k)"
Dirty:               104 kB
Mapped:            45696 kB
DirectMap4k:      100352 kB

主动机

cat /proc/meminfo | grep -P "(Dirty|Mapped|DirectMap4k)"
Dirty:             72428 kB
Mapped:            70192 kB
DirectMap4k:      100352 kB

因此,这台机器需要一些时间才能开始失败,而相同的机器会报告DirectMap4k: 77824 kB并因此定期失败(它还必须处理构建更复杂的容器),但是sysctl vm相同的。

docker 容器的构建/启动会引发内存不足错误,而问题是需要对内核进行哪些调整才能使其稳定。


Docker版本

Client:
 Version:      17.06.0-ce
 API version:  1.30
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:20:36 2017
 OS/Arch:      linux/amd64

Server:
 Version:      17.06.0-ce
 API version:  1.30 (minimum version 1.12)
 Go version:   go1.8.3
 Git commit:   02c1d87
 Built:        Fri Jun 23 21:21:56 2017
 OS/Arch:      linux/amd64
 Experimental: false

核心3.10.0-327.10.1.el7.x86_64

系统控制虚拟机

vm.admin_reserve_kbytes = 8192
vm.block_dump = 0
vm.dirty_background_bytes = 0
vm.dirty_background_ratio = 10
vm.dirty_bytes = 0
vm.dirty_expire_centisecs = 3000
vm.dirty_ratio = 30
vm.dirty_writeback_centisecs = 500
vm.drop_caches = 1
vm.extfrag_threshold = 500
vm.hugepages_treat_as_movable = 0
vm.hugetlb_shm_group = 0
vm.laptop_mode = 0
vm.legacy_va_layout = 0
vm.lowmem_reserve_ratio = 256   256     32
vm.max_map_count = 65530
vm.memory_failure_early_kill = 0
vm.memory_failure_recovery = 1
vm.min_free_kbytes = 67584
vm.min_slab_ratio = 5
vm.min_unmapped_ratio = 1
vm.mmap_min_addr = 4096
vm.nr_hugepages = 0
vm.nr_hugepages_mempolicy = 0
vm.nr_overcommit_hugepages = 0
vm.nr_pdflush_threads = 0
vm.numa_zonelist_order = default
vm.oom_dump_tasks = 1
vm.oom_kill_allocating_task = 0
vm.overcommit_kbytes = 0
vm.overcommit_memory = 0
vm.overcommit_ratio = 50
vm.page-cluster = 3
vm.panic_on_oom = 0
vm.percpu_pagelist_fraction = 0
vm.stat_interval = 1
vm.swappiness = 30
vm.user_reserve_kbytes = 108990
vm.vfs_cache_pressure = 100
vm.zone_reclaim_mode = 0

答案1

长话短说

sudo su
sysctl -w vm.swappiness=10

解释

我创建了一个测试场景,可以重现此错误 10/10 次。这只是通过命令行直接构建一个更大的镜像,而不是通过 CI。

正如所提到的,我知道的解决方法是

echo 1 > /proc/sys/vm/drop_caches

所以我试图将其与DirectMap价值观联系起来。由于我了解到这些值代表 TLB 负载并且无法直接调整,因此我查找了使用它们的首选项值,这就是交换性。

RHLE 7 文档解释交换性

⁠交换性

swappiness 值范围从 0 到 100,控制系统支持匿名内存或页面缓存的程度。高值可以提高文件系统性能,同时积极地将不太活跃的进程从 RAM 中交换出来。较低的值可以避免将进程交换出内存,这通常会以 I/O 性能为代价来减少延迟。默认值为 60。

警告
设置 swappiness==0 将非常积极地避免换出,这会增加在强内存和 I/O 压力下 OOM 杀死的风险。

因此减少它可以降低对内存缓存页面的依赖。默认情况下,我们使用的 EC2 Centos 7 映像将其设置为 30,因此将其减少到 10 可使大型映像成功构建 10/10 倍。

相关内容