你好,我知道Docker容器正在使用主机的内核(这就是为什么容器被认为是轻量级虚拟机)这里是源代码。然而,在阅读了docker文档的运行时选项部分后,我遇到了一个名为--kernel-memory
的选项。医生说
The maximum amount of kernel memory the container can use.
我不明白它的作用。我猜每个容器都会在主机的内核空间中分配一些内存。如果是这样,那么原因是什么,用户进程在内核空间中分配内存不是很容易吗?
整个CPU/内存限制的东西是使用cgroups
。您可以在/sys/fs/cgroup/memory/docker/<container ID>
(内存)或/sys/fs/cgroup/cpu/docker/<container ID>
(cpu)下找到docker run
执行的所有设置(每个参数或每个默认值)。
所以--kernel-memory
:
阅读:cat memory.kmem.limit_in_bytes
写:sudo -s
echo 2167483648 > memory.kmem.limit_in_bytes
以及基准测试memory.kmem.max_usage_in_bytes
和memory.kmem.usage_in_bytes
,它显示了(相当不言自明的)当前使用率和总体最高使用率。
CGroup docs about Kernel Memory
对于功能,我建议阅读CGroups V1的内核文档,而不是docker文档:
2.7内核内存扩展(CONFIG_MEMCG_KMEM)
使用内核内存扩展,内存控制器能够限制系统使用的内核内存量。内核内存为与用户内存根本不同,因为它不能交换输出,这使得系统有可能因消耗过多而关闭这宝贵的资源。[. .]
使用的内存为积累成记忆。Usage_in_bytes,或在单独的计数器中当它有意义的时候。(目前仅适用于tcp)。主要的"kmem"计数器被输入到主计数器,所以kmem电荷也会显示出来从用户计数器。
目前内核内存没有软限制。这是未来当达到这些限制时触发板回收的工作。
和
2.7.2常用用例因为"kmem"计数器被馈送给主用户计数器kernel内存永远不可能完全独立于用户内存而受到限制。说"U"为用户限制,";k &;"内核极限。有三个设置限制的可能方法:
U != 0, K = unlimited:
This is the standard memcg limitation mechanism already present before kmem
accounting. Kernel memory is completely ignored.
U != 0, K < U:
Kernel memory is a subset of the user memory. This setup is useful in
deployments where the total amount of memory per-cgroup is overcommited.
Overcommiting kernel memory limits is definitely not recommended, since the
box can still run out of non-reclaimable memory.
In this case, the admin could set up K so that the sum of all groups is
never greater than the total memory, and freely set U at the cost of his
QoS.
WARNING: In the current implementation, memory reclaim will NOT be
triggered for a cgroup when it hits K while staying below U, which makes
this setup impractical.
U != 0, K >= U:
Since kmem charges will also be fed to the user counter and reclaim will be
triggered for the cgroup for both kinds of memory. This setup gives the
admin a unified view of memory, and it is also useful for people who just
want to track kernel memory usage.
拙劣的总结
给定一个正在运行的容器,--memory="2g" --memory-swap="2g" --oom-kill-disable
使用
cat memory.kmem.max_usage_in_bytes
10747904
10mb的Kernel-Memory处于正常状态。对我来说限制它是有意义的,比方说内核内存为20mb。然后它应该杀死或限制容器以保护宿主。但是由于事实,有-根据文档-不可能回收内存和OOM杀手开始杀死主机上的进程,然后即使有足够的空闲内存(根据此:https://github.com/docker/for-linux/issues/1001)对我来说,使用它是相当不实际的。
在这种情况下,将其设置为>= memory.limit_in_bytes
的引号选项也没有真正的帮助。
弃用
--kernel-memory
在v20.10中已弃用,因为有人(=Linux Kernel)也实现了所有这些。
那么我们能做什么呢?ULimit
Docker API暴露HostConfig|Ulimit
,它写/etc/security/limits.conf
。对于docker运行应该是--ulimit <type>=<soft>:<hard>
。使用cat /etc/security/limits.conf
或man setrlimit
查看类别,您可以尝试通过使用--ulimit nproc=500:500
生成无限进程来保护系统免于填充内核内存,但要小心,nproc
适用于用户而不是容器,因此计数在一起。
为了防止DDoS(有意或无意),我建议至少限制nofile
和nproc
。也许有人能进一步说明……
sysctl:
docker run --sysctl
可以更改消息队列和共享内存上的内核变量,也可以更改网络,例如docker run --sysctl net.ipv4.tcp_max_orphans=
用于孤儿tcp连接,在我的系统上默认为131072,并且每个内核内存使用64kb:故障或dos时Bang 8gb。也许有人能进一步说明……