긴 이야기 짧게

긴 이야기 짧게

AWS EC2 내부의 Centos7을 기반으로 구축된 Jenkins 인스턴스에서 Docker 컨테이너를 구축하거나 실행하고 있습니다. 2개의 CPU와 3.5GB의 여유 메모리를 갖춘 2개의 t2.medium 인스턴스가 있습니다.
어떤 경우에는 다른 컨테이너 안에 컨테이너를 만들고 그냥 끌어서 실행합니다(다른 컨테이너).

오류가 발생하기 시작했습니다.

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

그래서 나는 도커 작업을 실행할 때 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마찬가지입니다.

도커 컨테이너를 빌드/실행하면 메모리 부족 오류가 발생하며 문제는 커널을 안정적으로 만들기 위해 어떤 조정이 필요한지입니다.


도커 버전

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 부하를 나타내며 직접 조정할 수 없다는 것을 알고 있으므로 이를 사용하기 위한 선호값인 교환성(commutativity)을 찾아보았습니다.

RHLE 7 문서에서는 교환성을 설명합니다.:

⁠ 교환성

swappiness 값의 범위는 0에서 100까지이며 시스템이 익명 메모리 또는 페이지 캐시를 지원하는 정도를 제어합니다. 높은 값은 파일 시스템 성능을 향상시키는 동시에 덜 활동적인 프로세스를 RAM에서 적극적으로 교체합니다. 값이 낮을수록 메모리에서 프로세스를 교체하는 것을 방지할 수 있으며, 이는 일반적으로 I/O 성능을 희생하면서 대기 시간을 줄입니다. 기본값은 60입니다.

경고하다
swappiness==0으로 설정하면 스왑 아웃을 매우 적극적으로 방지하므로 강력한 메모리 및 I/O 압력으로 인해 OOM 종료 위험이 높아집니다.

따라서 이를 줄이면 메모리 내 캐시 페이지에 대한 의존도가 줄어듭니다. 우리가 사용하고 있는 EC2 Centos 7 이미지는 기본적으로 30으로 설정되어 있으므로 10으로 줄이면 대형 이미지가 10/10배 더 성공적으로 빌드됩니다.

관련 정보