news 2026/6/26 3:31:37

明明每个 Pod 都没写满,为什么还是被驱逐?emptyDir 监控与驱逐机制实战

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
明明每个 Pod 都没写满,为什么还是被驱逐?emptyDir 监控与驱逐机制实战

明明每个 Pod 都没写满,为什么还是被驱逐?emptyDir 监控与驱逐机制实战

在 Kubernetes 里,emptyDir是最常见、也最容易被低估的临时存储能力。它看起来只是“给 Pod 挂一个临时目录”,但一旦用在缓存、临时文件、构建产物、日志缓冲、模型中间结果等场景,就会直接牵涉到节点磁盘容量、Pod 驱逐、服务稳定性和资源调度公平性。

本文从实际场景出发,讲清楚:

  1. emptyDir到底适合什么场景;
  2. emptyDir.sizeLimit能限制什么,不能限制什么;
  3. 单个 Pod 超过sizeLimit为什么会被精准驱逐;
  4. 每个 Pod 都没超过自己的限制,但节点磁盘达到阈值时,为什么被驱逐的不一定是“最能写”的那个 Pod;
  5. 原生kubelet中未提供emptyDir的监控,如何设计一套可落地的 emptyDir 监控方案 (见 13节)

1. 一个真实且常见的问题

假设我们在一个节点上跑了很多业务 Pod,每个 Pod 都配置了emptyDir

volumes:-name:cacheemptyDir:sizeLimit:100Gi

业务方理解是:

每个 Pod 最多用 100Gi 临时目录,只要没超过 100Gi,就应该不会被驱逐,不会有问题。

但线上可能出现这样的情况:

PodemptyDir sizeLimit实际使用
pod-a100Gi80Gi
pod-b100Gi70Gi
pod-c100Gi60Gi
pod-d100Gi90Gi
pod-e100Gi75Gi

每个 Pod 都没超过自己的100Gi限制。

可是节点磁盘整体触发了 kubelet eviction threshold,节点出现:

nodefs.available below eviction threshold

然后 kubelet 开始驱逐 Pod。

更令人困惑的是:

被驱逐的 Pod 不一定是当前写得最多的那个,也不一定是最接近sizeLimit的那个。

这就是很多人第一次遇到emptyDir问题时最不理解的地方。


2. emptyDir 是什么?

emptyDir是 Kubernetes 提供的一种临时卷。

它的生命周期跟 Pod 绑定:

Pod 创建 → emptyDir 创建 Pod 删除 → emptyDir 删除 即使容器异常了,emptyDir仍然存在

Pod 中的多个容器可以共享同一个emptyDir

例如:

apiVersion:v1kind:Podmetadata:name:emptydir-demospec:containers:-name:appimage:busyboxcommand:["sh","-c","sleep 3600"]volumeMounts:-name:cachemountPath:/cache-name:sidecarimage:busyboxcommand:["sh","-c","sleep 3600"]volumeMounts:-name:cachemountPath:/cachevolumes:-name:cacheemptyDir:{}

这里appsidecar都能访问/cache,它们看到的是同一个临时目录。


3. emptyDir 的常见使用场景

emptyDir适合这些场景。

3.1 临时缓存

例如:

  • 图片缩略图缓存;
  • 文件下载缓存;
  • 模型推理中间缓存;
  • Maven/npm/pip 构建缓存;
  • 查询结果临时缓存。

特点是:

丢了可以重建,不需要持久保存。

3.2 多容器共享文件

一个 Pod 里有多个容器:

  • 主容器生成文件;
  • sidecar 容器读取并上传;
  • init container 初始化配置文件;
  • 日志 sidecar 读取应用输出。

emptyDir可以作为它们之间的共享目录。

3.3 临时计算中间结果

例如视频转码、批处理、AI 任务、ETL 任务:

输入文件 → 中间文件 → 输出结果 → 上传对象存储

中间文件不需要持久化,适合放emptyDir

3.4 应用临时工作目录

有些应用需要/tmp/work/cache这样的工作目录。为了避免直接写容器层,可以挂载emptyDir

3.5 内存型临时目录

emptyDir还支持内存介质:

volumes:-name:tmpemptyDir:medium:MemorysizeLimit:1Gi

这类emptyDir使用 tmpfs,速度快,但会消耗内存。

适合:

  • 小文件高速缓存;
  • 临时密钥文件;
  • 对 IO 延迟敏感的小型临时数据。

但不适合大文件。


4. emptyDir 的能力边界

emptyDir很方便,但要记住几个边界。

4.1 emptyDir 不是持久化存储

Pod 删除后,emptyDir数据就没了。

如果数据不能丢,应该使用:

  • PVC;
  • 对象存储;
  • 外部数据库;
  • 分布式文件系统。

4.2 emptyDir 默认使用节点本地磁盘

没有指定medium: Memory时,emptyDir默认使用节点本地存储。

这意味着:

emptyDir 写多了,本质上是在消耗节点磁盘。 emptydir 在容器中看到的不是一个独立的磁盘(不想pvc那种),在容器中df -h 那个目录看到的磁盘还是节点上那个kubelet所在的磁盘
apiVersion: v1 kind: Pod metadata: name: test-cdl6k namespace: insight-system spec: containers: - args: ---config- /etc/test/config.yaml image: test:v20260625 imagePullPolicy: IfNotPresent livenessProbe: failureThreshold:3httpGet: path: /healthz port: metrics scheme: HTTP initialDelaySeconds:20periodSeconds:10successThreshold:1timeoutSeconds:5name:testvolumeMounts: - mountPath: /opt/oomprotection/log name: log-dir volumes: - emptyDir: sizeLimit: 1Gi name: log-dir

但进入容器,看不到的log目录不是1G,而是节点磁盘:

多个 Pod 的emptyDir、容器日志、镜像层、容器可写层,都可能共享节点的本地磁盘资源。

4.3 emptyDir 的风险不是单个 Pod,而是节点总量

单个 Pod 看起来只用了几十 Gi,但节点上几十个 Pod 加起来,就可能把节点磁盘打满。

这也是为什么emptyDir必须监控。


5. emptyDir.sizeLimit 是什么?

我们可以给emptyDir配置sizeLimit

volumes:-name:cacheemptyDir:sizeLimit:100Gi

它表达的是:

这个emptyDir卷最多希望使用 100Gi。

注意,这个限制是卷级别的。

也就是说,它限制的是:

某个 Pod 内某个 emptyDir volume 的使用量

而不是整个节点磁盘。


6. 单个 Pod 超过 sizeLimit:为什么能精准驱逐?

假设某个 Pod 配置:

emptyDir:sizeLimit:100Gi

当这个 Pod 的emptyDir实际使用超过 100Gi 时,即使节点磁盘还有剩余空间,kubelet 也会驱逐这个 Pod。

因为这时问题很明确:

Pod A 的 emptyDir 上限是 100Gi Pod A 实际用了 101Gi Pod A 违反了自己的限制

这是一个“局部配额超限”。

类比一下:

你租了一个 100 平米仓库。整栋楼还有空房间,不代表你可以占用 101 平米。你超出了自己的合同面积,所以处理对象就是你。

所以 kubelet 可以精准驱逐这个 Pod。

可能看到的事件类似:

Usage of EmptyDir volume "cache" exceeds the limit "100Gi"

这个是大家都理解的,kubelet也会检测(虽然做不到实时,但会检测,检测到就驱逐对应的pod)

7. 每个 Pod 都没超过 sizeLimit,但节点磁盘到了阈值

现在换一个场景。

节点可用本地磁盘资源有限,例如 500Gi。节点上有多个 Pod:

PodemptyDir sizeLimitemptyDir 实际使用
pod-a100Gi80Gi
pod-b100Gi80Gi
pod-c100Gi80Gi
pod-d100Gi80Gi
pod-e100Gi80Gi
pod-f100Gi80Gi

每个 Pod 都没超过 100Gi。

但是它们加起来:

6 x 80Gi = 480Gi

再加上:

  • 容器日志;
  • 镜像层;
  • 容器可写层;
  • kubelet 目录;
  • 系统组件占用;
  • 其他 Pod 的临时文件。

节点磁盘可能就触发了 kubelet 的 eviction threshold。

这时问题不再是:

哪个 Pod 超过了自己的 sizeLimit?

而是:

节点整体临时存储资源不足。

这属于“节点级资源压力”。


8. 为什么节点磁盘压力时,被驱逐的不一定是写满的那个 Pod?

这是理解 Kubernetes 驱逐机制的关键。

8.1 单 Pod 超限时,有明确违规者

Pod A sizeLimit = 100Gi Pod A used = 101Gi 结论:Pod A 违规

所以驱逐 Pod A。

8.2 节点磁盘压力时,不一定有单个违规者

Pod A sizeLimit = 100Gi, used = 80Gi Pod B sizeLimit = 100Gi, used = 80Gi Pod C sizeLimit = 100Gi, used = 80Gi Pod D sizeLimit = 100Gi, used = 80Gi 节点磁盘触发压力

此时每个 Pod 都可以说:

我没超过自己的限制。

所以 kubelet 不能简单地说“谁违规就驱逐谁”。

它只能做节点级资源恢复:

节点磁盘压力 → 找一个最适合驱逐的 Pod → 驱逐后看节点是否恢复 → 如果没恢复,再驱逐下一个

9. 节点压力驱逐时,kubelet 大概怎么选 Pod?

在节点资源压力下,kubelet 不会简单按照“谁最接近 emptyDir.sizeLimit”排序。

它通常会综合考虑:

  1. Pod Priority;
  2. Pod QoS;
  3. Pod 的资源 request;
  4. 当前实际使用量是否超过 request;
  5. 超过 request 的程度;
  6. 当前压力资源类型,例如 memory、nodefs、imagefs、ephemeral-storage;
  7. Pod 是否使用了比自己声明更多的资源。

这里,可以看到没有把emptydir占用考虑在内,所以极端场景可能出现节点磁盘压力,但最终把所有pod都驱逐了(最后才驱逐到那个写的满的那个pod


10. “最差会不会把所有 Pod 都驱逐一遍?”

理论上,在极端情况下,节点持续无法恢复磁盘压力,kubelet 会持续选择 Pod 驱逐。

所以从现象上看,确实可能出现:

驱逐一个 Pod,不够 再驱逐一个 Pod,还不够 继续驱逐

如果节点上大量 Pod 都在消耗本地存储,并且释放效果不足,或者新的 Pod 又被调度回来继续写,可能造成一轮又一轮驱逐。

但严格说,kubelet 的目标不是“把所有 Pod 都驱逐一遍”。

它的目标是:

驱逐尽量少的 Pod,让节点资源回到安全阈值以上。

只是当节点磁盘压力很严重、Pod 使用量都很高、没有合理 request/limit、调度器又继续把 Pod 调回来时,就可能出现连续驱逐、反复驱逐,甚至看起来像“把一批 Pod 都扫了一遍”。

所以这类问题不应该靠事后驱逐兜底,而应该靠:

  1. 合理设置ephemeral-storage.requests
  2. 合理设置ephemeral-storage.limits
  3. 监控 emptyDir 使用量;
  4. 监控节点磁盘压力;
  5. 控制单节点可调度的临时存储总量。

11. emptyDir 和 ephemeral-storage 的关系

这两个概念经常混在一起。

11.1 emptyDir.sizeLimit

volumes:-name:cacheemptyDir:sizeLimit:100Gi

它限制的是:

这个 emptyDir 卷最多使用多少

11.2 ephemeral-storage request/limit

resources:requests:ephemeral-storage:50Gilimits:ephemeral-storage:100Gi

它描述的是容器/Pod 的本地临时存储资源需求和上限。

它可能包括:

  • 容器可写层;
  • 容器日志;
  • emptyDir;
  • 其他本地临时存储使用。

11.3 推荐同时配置

完整一点的配置应该像这样:

apiVersion:v1kind:Podmetadata:name:emptydir-practicespec:containers:-name:appimage:busyboxcommand:["sh","-c","sleep 3600"]resources:requests:cpu:"500m"memory:"512Mi"ephemeral-storage:"50Gi"limits:cpu:"1"memory:"1Gi"ephemeral-storage:"100Gi"volumeMounts:-name:cachemountPath:/cachevolumes:-name:cacheemptyDir:sizeLimit:100Gi

含义是:

配置作用
emptyDir.sizeLimit: 100Gi限制该 emptyDir 卷最大使用量
requests.ephemeral-storage: 50Gi告诉调度器这个 Pod 预计需要多少临时存储
limits.ephemeral-storage: 100Gi限制该容器/Pod 的临时存储上限

但更多时候,**业务的pod不会配置ephemeral-storage,**而很多pod的emptydir的上限又超出磁盘大小;同时即使不超,每个业务也希望看到磁盘的使用情况,所以需要该emptydir的监控,但从kubelet上报的指标中是没有的emptydir的指标,只有pvc磁盘的指标,所以需要补齐emptydir的使用量和sizelimite的记录,关联到pod

12. emptyDir Pod粒度监控方案应该怎么设计?

下面进入实战部分。

目标不是只看节点磁盘,而是建立三层监控:

Pod emptyDir 使用量 Pod ephemeral-storage 使用量 (先不讨论) Node 磁盘 / ephemeral-storage 压力 (node指标在node-exporter开源组件中已经有)

13. 监控目标一:单 Pod emptyDir 使用量

13.1 为什么要监控

单个 Pod 的emptyDir超过sizeLimit时,可能被精准驱逐。

所以要提前发现:

某个 Pod 的 emptyDir 使用量正在接近 sizeLimit

emptydir limit采集

使用量采集

prometheus采集到两类指标后,汇聚出使用率:

13.2 需要采集的指标

理想情况下,要能看到:

指标含义
podPod 名称
namespace命名空间
node所在节点
volumeemptyDir 卷名
used_bytes当前使用量
size_limit_bytes配置的 sizeLimit
usage_ratio使用率

计算:

usage_ratio = used_bytes / size_limit_bytes

由于kubelet中缺少emptydir指标,所以我设计监控方案:
① sizelimit通过informer机制监听pod,pod的增删变化记录到指标中emptydir_size_limit_bytes{pod=“pod名称”,namespace=“xxx”,pod_uid=“xxxx”,path=“log-dir 对应emptydir name”}
pod_uid namespace 从pod的详细中取:

pod中配置了sizelimit的emptydir - emptyDir: sizeLimit: 1Gi name: log-dir

② emptydir_used_bytes{pod_uid=“xxxx”,path=“log-dir”}在每个节点上采集所有emptydir中所有文件的大小组合,定时采集,节点上每个emptydir路径
节点上每个emptydir路径

/var/lib/containers/kubelet/pods/a74bdf6a-bb18-48ab-9462-3c92c7eb1aff/volumes/kubernetes.io~empty-dir/log-dir a74bdf6a-bb18-48ab-9462-3c92c7eb1aff是pod_uid,log-dir为emptydir的名称路径

③ 指标采集到prometheus,通过rules pod_uid关联得到新指标emptydir_used_rate=emptydir_used_bytes/ on(pod_id) group_right(pod,namespace) emptydir_size_limit_bytes

13.3 告警建议

级别条件说明
warningemptyDir 使用率 > 70% 持续 10 分钟提前发现增长趋势
criticalemptyDir 使用率 > 85% 持续 5 分钟需要人工介入
emergencyemptyDir 使用率 > 95% 持续 1 分钟很可能即将驱逐

14. 监控目标二:节点磁盘和 eviction threshold

节点级监控同样重要。

14.1 要监控哪些磁盘

Kubernetes 中常见概念:

名称含义
nodefskubelet、emptyDir、日志等所在文件系统
imagefs容器镜像所在文件系统,如果单独分盘
containerfs某些运行时中容器文件系统所在位置

实际要看节点如何部署。

14.2 关键指标

指标含义
node_filesystem_avail_bytes节点文件系统可用空间
node_filesystem_size_bytes节点文件系统总空间
kube_node_status_condition{condition=“DiskPressure”}节点是否有磁盘压力
kube_pod_status_reason{reason=“Evicted”}Pod 是否被驱逐
kube_event驱逐事件,取决于事件采集方案

14.3 节点级告警建议

级别条件说明
warningnodefs 使用率 > 75% 持续 10 分钟提前扩容或清理
criticalnodefs 使用率 > 85% 持续 5 分钟接近 eviction 风险
emergencynodefs 使用率 > 90% 或 DiskPressure=True可能开始驱逐
criticalEvicted Pod 数量 > 0已发生影响

15. 监控维度不要只看节点,也不要只看 Pod

很多团队只做了节点磁盘告警:

节点磁盘 > 85% 告警

这不够。

因为等节点磁盘已经 85% 时,问题可能已经很严重了。

也有人只看 Pod 是否被 Evicted:

Pod Evicted 告警

这更晚。

推荐监控顺序应该是:

单 Pod emptyDir 使用率上涨 → Pod ephemeral-storage 接近 request/limit → 节点 nodefs 使用率上涨 → 节点 DiskPressure → Pod Evicted

越靠前,越能提前处理。


16. 治理建议:不要只靠驱逐兜底

emptyDir治理建议分三层。

16.1 应用层治理

应用应该控制临时文件生命周期:

  • 定期清理临时文件;
  • 避免无限增长日志;
  • 中间结果及时上传对象存储;
  • 大文件不要长期放 emptyDir;
  • 缓存要有淘汰策略。

16.2 Pod 配置治理

每个使用大量emptyDir的 Pod 都建议配置:

resources:requests:ephemeral-storage:"合理值"limits:ephemeral-storage:"上限值"

同时配置:

emptyDir:sizeLimit:"上限值"

不要只配sizeLimit

21.3 集群层治理

集群层面建议:

  1. 设置 ResourceQuota 限制 namespace 总 ephemeral-storage;
  2. 设置 LimitRange 给默认 request/limit;
  3. 对大量使用 emptyDir 的 workload 做节点隔离;
  4. 对构建类、批处理类任务使用专用节点池;
  5. 对 nodefs/imagefs 做容量监控;
  6. 采集 kubelet eviction event;
  7. 监控 Pod emptyDir 和 ephemeral-storage 使用排行。

22. 实战建议:哪些场景不适合 emptyDir?

以下场景不要优先用emptyDir

场景建议
数据不能丢使用 PVC 或外部存储
单 Pod 需要几百 Gi 临时文件考虑专用节点池或 PVC
多副本共享数据使用共享存储或对象存储
长周期缓存使用外部缓存或持久化卷
构建产物需要保留上传制品库或对象存储
日志大量增长接入日志系统,不要长期落 emptyDir

emptyDir最适合的是:

生命周期短、可丢失、可重建、容量可控的临时数据。

25. 总结

emptyDir的问题,本质不是“能不能挂一个临时目录”,而是:

Pod 临时存储如何被限制、如何被调度、如何被监控、如何在节点压力下被驱逐。

需要记住几个关键点:

  1. emptyDir默认使用节点本地磁盘,多个 Pod 会共享节点磁盘资源。
  2. emptyDir.sizeLimit是卷级上限,不是调度 request。
  3. 单个 Pod 超过自己的sizeLimit,kubelet 可以精准驱逐这个 Pod。
  4. 每个 Pod 都没超过sizeLimit,但总和导致节点磁盘压力时,kubelet 会按节点级 eviction 策略选择 Pod。
  5. 节点压力驱逐时,被驱逐的不一定是最接近sizeLimit的 Pod。
  6. 如果资源压力持续,kubelet 可能连续驱逐多个 Pod,直到节点恢复安全阈值。
  7. 不要只配置emptyDir.sizeLimit,还要配置resources.requests/limits.ephemeral-storage
  8. 监控要覆盖 Pod emptyDir、Pod ephemeral-storage、Node nodefs/imagefs、DiskPressure 和 Evicted 事件。
  9. 大量使用emptyDir的业务,最好配套 ResourceQuota、LimitRange 和专用节点池。

一句话总结:

emptyDir.sizeLimit解决的是“单个 Pod 不要越界”;ephemeral-storage request/limit和节点监控解决的是“整个节点不要被所有 Pod 一起打爆”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/6/26 3:28:34

2026年GEO优化公司哪家好:权威实力排行与全景能力图谱

摘要:当AI搜索正在重塑企业获客路径,越来越多品牌主开始追问同一个问题——GEO优化公司哪家好,找谁做GEO生成式引擎优化才真正靠谱?这篇文章从行业背景、技术路线、服务成熟度和实际能力差异出发,梳理当前国内GEO生成式…

作者头像 李华
网站建设 2026/6/26 3:27:46

杨洋出席周大福品牌活动 时光厚韵续东方新章

6月24日,周大福全球品牌代言人杨洋受邀现身上海,出席周大福品牌线下活动。本次亮相,杨洋延续一贯的绅士格调,以一身简约黑西装造型,佩戴周大福映翠系列珠宝惊艳亮相。极致光影勾勒利落身形,清冽轮廓搭配从容…

作者头像 李华
网站建设 2026/6/26 3:25:54

终极免费文档下载脚本:30+平台无障碍获取学习资源

终极免费文档下载脚本:30平台无障碍获取学习资源 【免费下载链接】kill-doc 看到经常有小伙伴们需要下载一些免费文档,但是相关网站浏览体验不好各种广告,各种登录验证,需要很多步骤才能下载文档,该脚本就是为了解决您…

作者头像 李华
网站建设 2026/6/26 3:25:23

CAN FD 是什么?一文看懂 CAN 通信的分类

CAN FD 是什么?一文看懂 CAN 通信的分类CAN(Controller Area Network,控制器局域网)是 1986 年由德国博世公司提出的串行通信总线,凭借抗干扰强、成本低、多节点共享一条总线等优点,成为汽车电子和工业控制…

作者头像 李华
网站建设 2026/6/26 3:23:25

女巫之火下载2026最新+全DLC

下载链接 基于状态机与动态难度调节的FPS游戏《巫火》系统架构解析 在现代第一人称射击(FPS)游戏设计中,复合型架构的引入为传统射击逻辑带来了新的状态变化。由波兰独立工作室 The Astronauts 研发的《巫火》(Witchfire&#xf…

作者头像 李华