Swap 空间是一块磁盘空间。当内存写满时可以把不常用的数据暂时写到 Swap 空间。这样内存空间就可以释放。
好处是可以应对瞬时突发的内存增大需求,不至于因为内存一时不够而触发 OOM Killer。
那么容器可以使用 Swap 空间吗?可以的
swappiness 参数
如果你使用过 Swap 空间,那么你可能配置过 proc 文件系统下的 swappiness 参数 (/proc/sys/vm/swappiness)。它可以决定系统将会有多频繁地使用交换分区。
较高的值会使得内核更频繁地使用交换分区,。swappiness 的取值范围是 0--100,缺省值 60。
在有磁盘文件访问时,Linux 会尽量把系统的空闲内存用作 Page Cache 来提高文件的读写性能。在没有打开 Swap 空间的情况下,一旦内存不够,就只能把 Page Cache 释放,而 RSS 内存是不能释放的。
RSS 里的内存大部分都是没有对应磁盘文件的内存,比如用 malloc() 申请到的内存,这种内存也被称为匿名内存。可以写入 Swap 空间的就是这些匿名内存。
在内存紧张时,Linux 怎么决定是先释放 Page Cache,还是先把匿名内存释放并写入到 Swap 空间里呢?
- 如果系统先把 Page Cache 都释放了,那么一旦节点里有频繁的文件读写操作,系统的性能就会下降。
- 如果 Linux 系统先把匿名内存都释放并写入到 Swap,一旦这些被释放的匿名内存马上需要使用,又需要从 Swap 空间读回到内存中,这样又会让 Swap(其实也是磁盘)的读写频繁,导致系统性能下降。
我们需要平衡 Page Cache 的释放和匿名内存的释放,而 swappiness就是用来定义这个平衡的参数。
swappiness 的范围是 0 到 100,但它不是一个百分比,更像是一个权重。用来定义 Page Cache 内存和匿名内存的释放的一个比例。

这个比例是 anon_prio: file_prio,这里 anon_prio 的值就等于 swappiness。下面我们分三个情况做讨论:
- 当 swappiness 的值是 100 时,匿名内存和 Page Cache 内存的释放比 例就是 100: 100,也就是等比例释放了。
- swappiness 缺省值是 60 时,匿名内存和 Page Cache 内存的释放比例就是 60 : 140,Page Cache 内存的释放要优先于匿名内存。
- swappiness 的值是 0 时,Linux 是不允许匿名内存写入 Swap 空间了吗?
当空闲内存少于内存一个 zone 的"high water mark"中的值时,Linux 还是会做内存交换,也就是把匿名内存写入到 Swap 空间后释放内存。
zone 是 Linux 划分物理内存的一个区域,里面有 3 个水位线(water mark),水位线可以用来警示空闲内存的紧张程度。
memory group和swappiness
运行容器,使用了 Memory Cgroup 后,swappiness 怎么工作呢?
Memory Cgroup 控制组下有一个 memory.swappiness 参数。可以控制这个控制组下面匿名内存和 page cache 的回收,取值的范围和工作方式和全局的 swappiness 差不多。在 Memory Cgorup 的控制组里,如果设置了 memory.swappiness 参数,它就会覆盖全局的 swappiness。
不过有一点不同:当 memory.swappiness = 0 时,对匿名页的回收是始终禁止的,始终不使用 Swap 空间,而当容器申请的内存超过 memory.limit_in_bytes 之后,就发生了 OOM Kill。
有了"memory.swappiness = 0"的配置和功能,就可以在同一个宿主机上,容器 A 上运行着需要使用 Swap 空间的应用,而别的容器不需要使用 Swap 空间。
重点总结
只要在宿主机节点上打开 Swap 空间,容器就可以用到 Swap 的。但同一个宿主机上,对于不需要使用 swap 的容器,它的 Memory Cgroups 的限制也失去了作用。
针对这个问题,我们学习了 swappiness 参数。当系统需要回收内存时,是优先释放 Page Cache 中的内存,还是优先释放匿名内存(写入 Swap)。
swappiness 的取值范围在 0 到 100 之间:
值为 100, 释放 Page Cache 和匿名内存是同等优先级的。
值为 60,缺省值,Page Cache 的释放优先级高于匿名内存的释放。
值为 0,当系统中空闲内存低于一个临界值时,仍然会释放匿名内存并把页面写入 Swap 空间。
swappiness 参数除了在 proc 文件系统下有个全局的值外,在每个 Memory Cgroup 控制组里也有一个 memory.swappiness
控制组里的 swappiness 参数值为 0 时,可以让控制组里的内存停止写入 Swap。这样需要使用 Swap 和不需要 Swap 的容器就可以在同一个宿主机上同时运行