Jeremy Schneider:为什么Postgres会破坏Kubernetes的container_memory_working_set_bytes指标

Jeremy Schneider:为什么Postgres会破坏Kubernetes的container_memory_working_set_bytes指标

💡 原文英文,约1500词,阅读约需6分钟。
📝

内容提要

Kubernetes的container_memory_working_set_bytes指标对PostgreSQL内存使用不准确,因为它忽略活动页缓存。测试显示,该指标在数据库OOM崩溃前无法预警。更可靠的方法是排除所有页缓存(active和inactive),并监控shmem和anon指标。建议使用pgnodemx扩展计算正确指标,并考虑降低shared_buffers设置。

🔎

延伸解读

指标失真的根源

container_memory_working_set_bytes 的计算方式为 current 减去 inactive_file,即只排除非活动页缓存。但 Postgres 的 shared_buffers 属于 shmem,且活动页缓存(active_file)也可能占用大量内存。当数据库负载较高时,活动页缓存和 shmem 会显著增加,导致该指标严重低估实际内存使用,无法反映即将发生的 OOM 风险。

OOM 的后果与预防

在 Kubernetes 中,Postgres 一旦触发 OOM,会导致数据库崩溃并重启,造成服务中断。文章测试表明,当 shared_buffers 较大时,OOM 可能在排序操作中更早发生。建议在设置内存限制时,考虑降低 shared_buffers 的值,以留出更多余量给工作内存和页缓存,降低崩溃风险。

更可靠的监控指标

文章推荐使用 current 减去所有页缓存(active_file + inactive_file)作为核心指标,并额外监控 shmem 和 anon。这些指标能更准确反映 Postgres 的真实内存压力。可通过 pgnodemx 扩展在 CloudNativePG 中实现自定义监控查询,或使用 /proc/pid/statm 中的 resident - shared 进行高频采集。

Q&A

为什么Kubernetes的container_memory_working_set_bytes指标对PostgreSQL不准确?

因为该指标只排除了inactive文件页缓存,而PostgreSQL的shared_buffers(共享缓冲区)属于shmem,且活动页缓存(active file)也被计入,导致指标无法准确反映实际内存压力,甚至可能掩盖即将发生的OOM风险。

如何正确监控PostgreSQL在Kubernetes中的内存使用?

建议排除所有页缓存(active和inactive),使用current - (inactive_file + active_file)作为核心指标,同时监控shmem和anon指标。也可以使用pgnodemx扩展在CloudNativePG中实现正确计算。

PostgreSQL在Kubernetes中OOM崩溃前,container_memory_working_set_bytes指标有何表现?

在测试中,当数据库因OOM崩溃时,该指标并未提前预警,甚至可能显示内存使用较低,无法反映真实的内存压力,导致无法预测崩溃。

为什么降低shared_buffers设置有助于避免PostgreSQL在Kubernetes中的OOM?

因为shared_buffers分配的是shmem,内核无法回收,降低其大小可以减少不可回收的内存占用,从而降低OOM风险。测试中,将shared_buffers从128MB降至32MB后,数据库能处理更多排序行而不崩溃。

Linux的MGLRU(Multi-Gen LRU)对Kubernetes内存指标有何影响?

MGLRU改变了页缓存的活动页分类方式,可能导致container_memory_working_set_bytes指标更不准确,因为活动页的判定与之前不同。测试显示,MGLRU下活动页较少,但具体影响需进一步研究。

除了container_memory_working_set_bytes,还有哪些指标可以用于监控PostgreSQL内存压力?

可以监控shmem(反映shared_buffers)和anon(反映工作内存),以及PSI(pressure stall information)和/proc/pid/statm中的resident - shared值,这些能更准确反映内存压力。

🏷️

标签

➡️

继续阅读