Linux内存管理的机制
OOM Killer
在 Linux 系统里如果内存不足时,会杀死一个正在运行的进程来释放一些内存,如果进程是容器处于OOM Killer 。
为什么还要去杀死正在运行的进程呢?
Linux允许进程申请超过实际物理内存上限的内存。因为 malloc() 申请的是内存的虚拟地址,系统只是给了程序一个地址范围,并没有得到真正的物理内存。
在发生 OOM 的时候,Linux 到底是根据什么标准来选择被杀的进程呢?
在 Linux 内核里有一个 oom_badness() 函数,就是它定义了选择进程的标准。
Memory Cgroup
限制cgroup 之中的进程所能使用的内存大小,Memory Cgroup 里都不会对内核的内存做限制(比如页表,slab 等)。只限制用户态相关的两个内存类型,RSS(Resident Set Size) 和 Page Cache。
如何限制memory cgroup 的内存大小?
memory.limit_in_bytes:一个控制组里所有进程可使用内存的最大值
memory.oom_control,当控制组中的进程内存使用达到上限值时,这个参数能够决定会不会触发 OOM Killer
memory.swappiness,设置和显示当前的swappiness
Linux 内存类型
内核需要分配内存给页表,内核栈,还有 slab,也就是内核各种数据结构的 Cache Pool;
用户态进程内存:
1:RSS 内存包含了进程的代码段内存,栈内存,堆内存,共享库的内存
2:文件读写的 Page Cache,是一种为了提高磁盘文件读写性能的机制。
Linux 的内存管理有一种内存页面回收机制(page frame reclaim),会根据系统里空闲物理内存是否低于某个阈值(wartermark),来决定是否启动内存的回收。内存回收的算法会根据不同类型的内存以及内存的最近最少用原则,就是 LRU(Least Recently Used)算法决定哪些内存页面先被释放。因为 Page Cache 的内存页面只是起到 Cache 作用,自然是会被优先释放的。
swap
Swap 是一块磁盘空间,当内存写满的时候,就可以把内存中不常用的数据暂时写到这个 Swap 空间上。
1、在容器中要用到 Swap,需要在宿主机节点上打开 Swap 空间
2、通过swappiness 参数值,在系统里有 Swap 空间之后,当系统需要回收内存的时候,是优先释放 Page Cache 中的内存,还是优先释放匿名内存
Kubernetes 管理内存机制
资源配额(Resource Quota): 资源配额可以设置命名空间中容器的内存使用限制。这可以帮助防止容器占用过多的内存资源,从而保护整个集群的稳定性。
资源限制(Resource Limit): 在容器的 PodSpec 中,可以设置容器的资源限制,包括内存限制。这样可以确保容器不会使用超过限制的内存量。
内存请求和分配(Memory Requests and Allocation): 在容器的 PodSpec 中,可以设置容器的内存请求。这将告诉 Kubernetes 调度器容器所需的内存量。Kubernetes 调度器会根据节点的可用资源和容器的请求进行调度决策,以确保容器可以获得足够的内存。
内存回收(Memory Reclamation): Kubernetes 提供了内存回收机制来处理容器释放未使用的内存。当容器不再需要内存时,Kubernetes 可以将其回收以供其他容器使用。
内存回收时的内存使用量的锁定
1、保障 Pod 间内存回收的公平性,当整机内存资源紧张时,优先从内存超用(Usage > Request)的 Pod 中回收内存(Memory QoS 支持为这类Pod设置主动内存回收的水位线,将内存使用限制在水位线附近),约束破坏者以避免整机资源质量的下降。
2、当 Pod 的内存用量接近 Limit 时,优先在后台异步回收一部分内存,缓解直接内存回收带来的性能影响。
3、节点内存资源紧张时,优先保障 Guaranteed/Burstable Pod 的内存运行质量。Memory QoS 功能通过启用全局最低水位线分级和内核 memcg QoS,当整机内存资源紧张时,优先从 BE 容器中回收内存,降低全局内存回收对 LS 容器的影响;也支持优先回收超用的的内存资源,保障内存资源的公平性。