笔者在工作中使用Memory类型的Emptydir,而这引发了意想不到的问题。
本文探讨Memory类型的Emptydir对Pod和节点的影响。
2.1 两者简介
共享内存 /dev/shm 是 Linux 系统中用于实现内存共享的临时文件系统,基于 tmpfs(临时文件系统) 实现。对于 Linux 系统,默认情况 /dev/shm 大小最大可以用到物理内存的一半。主要用途包括进程间通信(IPC),某些高性能应用(如数据库、科学计算等)使用共享内存来高速访问数据。
内存类型的 EmptyDir 是基于 tmpfs 实现的,这就意味着数据都存储在内存中。这种类型的卷适用于需要高速读写的场景,例如缓存数据、临时文件等。同一个 Pod 内的多个 container 可以通过挂载同一个 EmptyDir 来进行快速的数据交换或协同工作。当你在 Kubernetes 中使用 Memory 类型的 EmptyDir 卷时,Kubernetes 会在 tmpfs 上创建一个新的挂载点,而不是直接使用 /dev/shm 。
2.2 两者对比
虽然两者都利用了 tmpfs 来实现内存中的高性能数据读写,但 Memory 类型的 EmptyDir 相当于一个独立的内存分区,不与 /dev/shm
共享直接路径,但技术实现原理相似。
先给结论,后面有验证过程
测试项1:Pod调度除了计算Resource-Request外,是否会计算MemoryTypeEmprtDir使用的内存大小?
结论:MemoryTypeEmprtDir并不影响节点剩余可用内存,调度时也不会考虑MemoryTypeEmprtDir的大小,这会造成Pod"偷偷使用了"Node内存,从而产生了一个隐患点。
测试项2:Pod的Memory-Limit是否能限制MemoryTypeEmprtDir使用的内存大小?
结论:可以限制,当MemoryTypeEmprtDir使用量+程序Memory使用量>MemoryLimit,会触发OOM事件,业务进程被杀死。
4.1 节点规格
准备一个Kubernetes集群,本文所用节点规格(8C16G)
4.2 测试所用Yaml
Pod调度时除了计算内存request外,是否会计算EmptyDir内存的大小?
5.1 从节点剩余资源,分析EmptyDir对调度的影响
创建4.2中的Yaml,pod内存Request 1G,内存Limit 1G,MemoryEmptyDir 2G
Pod调度前:节点内存申请量:3.31G,节点剩余申请量:9.15G
Pod调度后:节点内存申请量:4.31G,节点剩余申请量:8.15G
可以看到类型为tmpfs的1G内存被Pod使用。
5.2 设置超大MemoryTypeEmptyDir,查看Pod是否能正常运行
把MemoryTypeEmptyDir修改为20G,依然可以在16G节点上运行
5.3 测试项1-验证结论
结论:节点的剩余可用Mem不会计算MemoryTypeEmptyDir的大小,所以不影响调度
Pod-Limit 是否可以限制 MemoryTypeEmptyDir的使用大小?
6.1 从Pod指标观测MemoryTypeEmptyDir使用量是否被统计
进入容器,向EmptyDir中写入数据。
从截图中可以看出,容器的Cgroup统计中包含了MemoryTypeEmptyDir的使用量。
Pod的监控指标中也包含MemoryTypeEmptyDir的使用量。
6.2 持续向EmptyDir中写入,是否会被Pod-Mem-Limit的限制?是否会造成容器OOM?
使用下面的Yaml,通过stress命令模拟应用程序使用内存
再向MemoryTypeEmptyDir中写入,使其超过Pod-Mem-Limit
可以从dmesg中查看到容器的OOM信息
6.3 测试项2-验证结论
MemoryTypeEmptyDir使用的内存会被统计到。当Pod使用的总内存大于Limit,会触发OOM事件,业务进程被杀死。