web-dev-qa-db-ja.com

Dockerは「メモリを割り当てられません」-仮想メモリのチューニング

AWS EC2内のCentos7の上に構築されたJenkinsインスタンスでDockerコンテナーを構築または実行しています。 2つのCPUと3.5 Gbの利用可能なメモリを搭載したt2.mediumボックスの2つのインスタンスがあります。
一度に別のコンテナを構築する場合は、それらをプルして実行するだけです(異なるコンテナ)。

エラーが発生し始めました

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

sysctl vm

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
3
JackLeo

TL; DR

Sudo su
sysctl -w vm.swappiness=10

説明

このエラーを10/10回再現できるテストシナリオを作成しました。これは、CIではなくコマンドラインを介して直接、より大きなイメージを構築するだけです。

前述の回避策は、私が知っていた

echo 1 > /proc/sys/vm/drop_caches

だから私はそれをDirectMapの値に関連づけようとしました。これらの値はTLBの負荷を表すものであり、直接調整できないことを知ったので、それらを使用するために設定値を調べましたが、それがスワップです。

RHLE 7ドキュメントはスワップを説明します

⁠swappiness

0から100の範囲のswappiness値は、システムが匿名メモリまたはページキャッシュを優先する度合いを制御します。高い値を指定すると、アクティブでないプロセスをRAMから積極的にスワップしながら、ファイルシステムのパフォーマンスが向上します。値を小さくすると、メモリからプロセスをスワップすることが回避されます。これにより、通常、I/Oパフォーマンスを犠牲にして待ち時間が短縮されます。デフォルト値は60です。

[〜#〜]警告[〜#〜]
swappiness == 0を設定すると、スワップアウトが非常に積極的に回避され、強いメモリおよびI/Oプレッシャーの下でOOMが強制終了するリスクが増加します。

したがって、この値を小さくすると、メモリキャッシュページへの依存度が低くなります。デフォルトでは、使用するEC2 Centos 7イメージは30に設定されているため、10に削減すると、大きなイメージが10/10回正常にビルドされました。

3
JackLeo