k8s pod因节点临时存储(ephemeral-storage)不足而被驱逐
·
es master三节点中的一个节点提示容器状态未知

describe发现events有如下提示,这个是Kubernetes Pod因节点临时存储(ephemeral-storage)不足而被驱逐(Evicted)的事件日志。
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning Evicted 15m kubelet The node was low on resource: ephemeral-storage. Threshold quantity: 3692958570, available: 3567316Ki. Container es-agent was using 1280Ki, request is 0, has larger consumption of ephemeral-storage. Container kbagent was using 4Ki, request is 0, has larger consumption of ephemeral-storage. Container exporter was using 20Ki, request is 0, has larger consumption of ephemeral-storage. Container elasticsearch was using 976Ki, request is 0, has larger consumption of ephemeral-storage.
Normal Killing 15m kubelet Stopping container elasticsearch
Normal Killing 15m kubelet Stopping container kbagent
Normal Killing 15m kubelet Stopping container es-agent
Normal Killing 15m kubelet Stopping container exporter
Warning ExceededGracePeriod 15m kubelet Container runtime did not kill the pod within specified grace period.
Warning FailedPreStopHook 14m kubelet PreStopHook failed
问题根因分析
- 直接原因:节点可用临时存储(available: 3567316Ki ≈ 3.4Gi)低于驱逐阈值(Threshold
quantity: 3692958570 ≈ 3.52Gi) - 触发机制:kubelet 的节点压力驱逐(Node Pressure Eviction)
- 连锁问题:
- PreStop钩子执行失败(14m前)
- 容器未在优雅终止期内停止(ExceededGracePeriod)
- 最终被强制杀死
核心问题:容器未设置 ephemeral-storage 资源请求/限制
从日志看,所有容器 request is 0,这意味着:
- 没有声明对临时存储的资源请求
- QoS等级为 BestEffort(最低优先级)
- 节点资源不足时,这类Pod会被最先驱逐
解决方案
1. 立即恢复(临时措施)
# 查看Pod当前状态
kubectl get pod <pod-name> -n <namespace>
# 如果Pod已被删除,检查是否有控制器(Deployment/StatefulSet)自动重建
kubectl get deploy,sts -n <namespace>
# 手动删除Pod让其重建(如果控制器存在)
kubectl delete pod <pod-name> -n <namespace>
2. 根本解决(资源配置)
在Pod/Deployment/StatefulSet中添加资源限制:
spec:
containers:
- name: elasticsearch
resources:
requests:
ephemeral-storage: "2Gi" # 请求量
limits:
ephemeral-storage: "4Gi" # 限制量(防止容器写爆磁盘)
- name: es-agent
resources:
requests:
ephemeral-storage: "500Mi"
limits:
ephemeral-storage: "1Gi"
- name: kbagent
resources:
requests:
ephemeral-storage: "100Mi"
limits:
ephemeral-storage: "200Mi"
- name: exporter
resources:
requests:
ephemeral-storage: "50Mi"
limits:
ephemeral-storage: "100Mi"
3. 修复 PreStop 钩子
PreStop钩子失败会导致优雅终止超时,检查并修复:
# 查看Pod的PreStop配置
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A 5 -B 5 preStop
# 常见问题:
# - 钩子中调用的命令/API不存在
# - 超时时间设置过短
# - 网络问题导致钩子无法完成
建议增加 terminationGracePeriodSeconds(默认30秒):
spec:
terminationGracePeriodSeconds: 60 # 增加到60秒
containers:
- name: elasticsearch
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "curl -XPOST http://localhost:9200/_cluster/nodes/_local/shutdown"]
4. 节点层面优化
# 查看节点磁盘使用情况
kubectl describe node <node-name> | grep -A 5 "Allocated resources"
# 清理节点上的无用资源
# - 清理已终止的容器日志
# - 清理未使用的镜像
# - 清理已完成的Pod
docker system prune -f # 如果是Docker运行时
5. 配置驱逐阈值(集群管理员)
修改kubelet配置,调整更合理的阈值:
# /var/lib/kubelet/config.yaml
evictionHard:
imagefs.available: "15%"
nodefs.available: "10%"
ephemeral-storage.available: "10%" # 当前是约15%
evictionSoft:
ephemeral-storage.available: "15%"
evictionSoftGracePeriod:
ephemeral-storage.available: "2m"
预防建议
- 监控告警:对节点磁盘使用率设置告警(如 > 80%)
- 日志轮转:配置容器日志轮转策略(max-size, max-file)
- 持久化存储:对需要大量存储的组件使用PVC而非emptyDir
- 资源配额:在命名空间级别设置ResourceQuota限制总存储使用
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: your-namespace
spec:
hard:
requests.ephemeral-storage: "20Gi"
limits.ephemeral-storage: "40Gi"
验证修复
# 查看Pod资源请求/限制是否生效
kubectl describe pod <pod-name> -n <namespace> | grep -A 3 "QoS"
# 期望输出:QoS Class: Burstable 或 Guaranteed(有requests)
如果问题持续,需要检查:
- 是否有日志文件过大未轮转
- 是否有应用产生大量临时文件
- 节点的emptyDir目录(/var/lib/kubelet)是否被其他Pod占满
怎么看出来是临时存储的
1. 直接从事件消息中识别
日志里明确写了:
The node was low on resource: ephemeral-storage
- ephemeral-storage 就是"临时存储"的英文术语
- 中文翻译:临时存储、临时存储空间、临时卷存储
2. 关键词对照表
| 英文关键词 | 中文含义 | 说明 |
|---|---|---|
ephemeral-storage | 临时存储 | Kubernetes官方术语 |
ephemeral | 临时/短暂的 | 表示非持久化 |
emptyDir | 临时卷 | Pod级别临时存储的一种实现 |
nodefs | 节点文件系统 | 包含 /var/lib/kubelet 等 |
imagefs | 镜像文件系统 | 存放容器镜像 |
3. 阈值表达式的含义
Threshold quantity: 3692958570, available: 3567316Ki
这两个值的单位不一样:
3692958570 → 没有单位后缀,默认是字节(bytes)
换算:3692958570 bytes ≈ 3.52 GiB
3567316Ki → KiB(Kibibyte)
换算:3567316 KiB ≈ 3.4 GiB
所以实际含义是:
阈值: 3.52 GiB (硬驱逐阈值)
可用: 3.40 GiB
可用 < 阈值 → 触发驱逐
4. Kubernetes存储类型对比
| 存储类型 | 生命周期 | 是否临时 | 典型用途 |
|---|---|---|---|
| ephemeral-storage | Pod生命周期 | ✅ 是 | 容器日志、镜像层、emptyDir |
| emptyDir | Pod生命周期 | ✅ 是 | 临时缓存、共享数据 |
| hostPath | 节点生命周期 | ❌ 否 | 宿主机目录挂载 |
| PersistentVolume (PVC) | 独立于Pod | ❌ 否 | 持久化数据(数据库) |
| configMap/secret | Pod生命周期 | ✅ 是 | 配置文件、密钥 |
5. ephemeral-storage 包含哪些内容?
/var/lib/kubelet/
├── containers/ # 容器可写层
├── volumes/ # emptyDir等临时卷
├── pods/ # Pod相关文件
└── ...
/var/log/containers/ # 容器日志
/var/lib/docker/ # 镜像层(部分计入)
- 如何查看当前Pod的临时存储使用?
# 方法1:查看Pod的详细状态
kubectl describe pod <pod-name> -n <namespace>
# 查找 "Ephemeral Storage" 相关行
# 方法2:查看节点上所有Pod的存储使用
kubectl top pod -n <namespace> --containers
# 注:top命令不直接显示存储,需要结合以下命令
# 方法3:查看节点的存储分配情况
kubectl describe node <node-name>
# 输出示例:
# Allocated resources:
# ephemeral-storage: 15Gi (40%)
7. 实际查看节点存储的命令
# 登录到节点,查看实际磁盘使用
df -h /var/lib/kubelet
# 输出示例:
# Filesystem Size Used Avail Use% Mounted on
# /dev/sda1 100G 85G 15G 85% /var/lib/kubelet
# 查看详细的目录占用
du -sh /var/lib/kubelet/* | sort -hr | head -10
8. 日志中的"request is 0"含义
Container es-agent was using 1280Ki, request is 0
- 容器实际使用了 1280 KiB 的临时存储
- 但没有设置资源请求(request=0)
- 这意味着该Pod的QoS是 BestEffort(最低优先级)
- 当节点资源不足时,这种Pod会被最先驱逐
9.快速验证命令
bash
# 查看Pod的QoS等级(如果是BestEffort则没有requests)
kubectl get pod <pod-name> -n <namespace> -o jsonpath='{.status.qosClass}'
# 查看Pod的资源请求
kubectl get pod <pod-name> -n <namespace> -o yaml | grep -A 10 "resources:"
总结:如何一眼识别"临时存储驱逐
- 看关键词:ephemeral-storage 或 临时存储
- 看资源类型:不是 memory 或 cpu
- 看驱逐原因:Evicted + resource: ephemeral-storage
- 看数值单位:Ki、Mi、Gi(或纯数字表示字节)
- 看容器使用:using 多少,request 是多少
如果日志写的是 disk pressure 或 nodefs,也是指磁盘/存储相关,但 ephemeral-storage 是Kubernetes 1.8+后的标准术语。
更多推荐


所有评论(0)