MENU

K8s 节点磁盘排查:overlay2 大文件定位 Pod 实战

• April 15, 2026 • Read: 4 • 编码👨🏻‍💻

背景

K8s node 工作节点磁盘告警,发现 /home/application/docker/overlay2 目录占用很大。这个目录存放的是 Docker overlay2 存储驱动的 layer ID(镜像层或容器层的哈希),需要定位是哪个 Pod 产生的。


排查步骤

1. 进入 overlay2 目录

cd /home/application/docker/overlay2

2. 按大小排序找出大 layer

du -sh * | sort -hr | head -10

示例输出:

83G    058fafcef62ef64534f68ab0de17537120b5f437405b2a8c2ba3e02917aebb87
52G    a1b2c3d4e5f6...
...

3. 根据 layer ID 查找容器 ID

docker inspect $(docker ps -aq) --format='{{.Id}} {{.GraphDriver.Data.UpperDir}}' | grep <layer-id>

示例:

docker inspect $(docker ps -aq) --format='{{.Id}} {{.GraphDriver.Data.UpperDir}}' | grep 058fafcef62e

输出:

2d0142b1081d354b61c105116ed49fca9749566369bb57a6b96f5ec2519ba6b6 /home/application/docker/overlay2/058fafcef62ef64534f68ab0de17537120b5f437405b2a8c2ba3e02917aebb87/diff
  • 容器 ID:2d0142b1081d...

4. 根据容器 ID 查找 Pod 信息

docker inspect <容器id> --format='{{json .Config.Labels}}' | jq .
注:需要安装 jq 命令:yum install jq -y

示例:

docker inspect 2d0142b1081d --format='{{json .Config.Labels}}' | jq .

输出:

{
  "annotation.io.kubernetes.container.hash": "2897634b",
  "annotation.io.kubernetes.container.restartCount": "0",
  "annotation.io.kubernetes.container.terminationMessagePath": "/dev/termination-log",
  "annotation.io.kubernetes.container.terminationMessagePolicy": "File",
  "annotation.io.kubernetes.pod.terminationGracePeriod": "30",
  "io.kubernetes.container.logpath": "/var/log/pods/base-uat_srebro-psm-education-d94db986f-sxjd4_943133e5-7684-4705-aa52-3fad0f393249/srebro-psm-education/0.log",
  "io.kubernetes.container.name": "srebro-psm-education",
  "io.kubernetes.docker.type": "container",
  "io.kubernetes.pod.name": "srebro-psm-education-d94db986f-sxjd4",
  "io.kubernetes.pod.namespace": "base-uat",
  "io.kubernetes.pod.uid": "943133e5-7684-4705-aa52-3fad0f393249",
  "io.kubernetes.sandbox.id": "d6a0115bab1f22202bbd0ad5b76f8b4433bb1e884ae57b854d49170f0f5b8b57"
}

5. 提取关键信息

字段说明
io.kubernetes.pod.namesrebro-psm-education-d94db986f-sxjd4Pod 名称
io.kubernetes.pod.namespacebase-uat命名空间
io.kubernetes.container.namesrebro-psm-education容器名称
io.kubernetes.container.logpath/var/log/pods/...容器日志路径

快速查看该 Pod

kubectl get pod srebro-psm-education-d94db986f-sxjd4 -n base-uat

# 查看日志
kubectl logs srebro-psm-education-d94db986f-sxjd4 -n base-uat --tail=100

# 进入容器
kubectl exec -it srebro-psm-education-d94db986f-sxjd4 -n base-uat -- /bin/sh

一键排查脚本

#!/bin/bash
# find-large-overlay.sh - 查找 overlay2 大文件对应的 Pod

OVERLAY_DIR="/home/application/docker/overlay2"
TOP_N=${1:-10}

echo "=== 查找 overlay2 目录下最大的 ${TOP_N} 个 layer ==="
cd $OVERLAY_DIR || exit 1

du -sh * 2>/dev/null | sort -hr | head -$TOP_N | while read size layer_id; do
    echo ""
    echo "【Layer】$layer_id"
    echo "【大小】$size"
    
    # 查找容器
    container_info=$(docker inspect $(docker ps -aq) --format='{{.Id}} {{.GraphDriver.Data.UpperDir}}' 2>/dev/null | grep $layer_id)
    
    if [ -n "$container_info" ]; then
        container_id=$(echo $container_info | awk '{print $1}')
        echo "【容器ID】${container_id:0:12}"
        
        # 查找 Pod 信息
        labels=$(docker inspect $container_id --format='{{json .Config.Labels}}' 2>/dev/null)
        if [ -n "$labels" ]; then
            pod_name=$(echo $labels | jq -r '.["io.kubernetes.pod.name"] // "N/A"')
            namespace=$(echo $labels | jq -r '.["io.kubernetes.pod.namespace"] // "N/A"')
            container_name=$(echo $labels | jq -r '.["io.kubernetes.container.name"] // "N/A"')
            
            echo "【Pod】$pod_name"
            echo "【命名空间】$namespace"
            echo "【容器名】$container_name"
            echo "【kubectl命令】kubectl logs $pod_name -n $namespace --tail=50"
        fi
    else
        echo "【状态】未找到运行中的容器(可能是已删除容器的残留)"
    fi
    echo "----------------------------------------"
done

使用方法:

chmod +x find-large-overlay.sh
./find-large-overlay.sh        # 默认显示前10个
./find-large-overlay.sh 5      # 显示前5个

image-20260415221844783

常见问题

Q: 为什么 overlay2 目录会占用很大?

原因说明
容器内日志未限制应用写入的日志文件持续增长

Q: 如何清理?

# 1. 先定位问题 Pod,修复应用(加日志切割)

# 2. 删除 Pod 重建(会清理对应 layer)
kubectl delete pod <pod-name> -n <namespace>

Q: 如何避免?

  1. 应用日志输出到 stdout,由 kubelet 统一管理

总结

步骤命令目的
1`du -sh * \sort -hr`找大 layer
2`docker inspect ... \grep layer`找容器 ID
3`docker inspect ... \jq .Labels`找 Pod 信息

核心思路: layer ID → 容器 ID → Pod 标签 → 定位应用

Archives Tip
QR Code for this page
Tipping QR Code