背景docker inspect对接Docker daemondockerd读取 Docker 自己的元数据存储crictl inspect对接CRI runtimecontainerd/cri-o是 K8s 标准 CRI 接口工具直接调用容器运行时不走 dockerd在 K8s 环境现在绝大多数节点底层是containerd即使节点装了 dockerk8s 也不经过 dockerd而是直接调用 containerd。1、核心本质区别docker inspectDocker 专属 API输出 Docker 完整元数据镜像、容器、HostConfig、GraphDriver、docker 网络、docker volume 等 docker 内部概念。crictl inspectCRI 标准接口输出面向 K8s 的 Pod/Container 模型输出 CRI 定义的结构体没有 docker 那套 GraphDriver、HostConfig、Mounts 完整语义字段集合不一样。注意crictl inspect有两个对象crictl inspect container-id→ 查看容器crictl inspectp pod-id→ 查看 pod sandbox沙箱pause 容器2、输出结构对比1docker inspect你前面看过的 JSON示例【k8s】Docker inspect 命令输出完整 docker 模型包含大类Id、Created、StatePID、OOMKilled、ExitCodeConfig镜像原始配置 Env/Cmd/Entrypoint/VolumesHostConfigdocker run 参数资源限制、端口映射、重启策略GraphDriveroverlay2 LowerDir / UpperDir / MergedDir / WorkDir宿主机磁盘路径即基础镜像路径Mounts完整挂载列表 Source/Destination/ModeNetworkSettingsdocker 网络、IP、PortBindings、SandboxKeyRootFS镜像分层 diffID✅ 特点Docker 的全部内部细节都能看到docker 的概念全部保留。2crictl inspect containerIDCRI 输出CRI 把对象分成两层PodSandbox (pause 沙箱) 业务 Containerjson{ status: { id: 容器ID, pid: 1234, state: { }, createdAt: ..., sandboxId: pause容器ID, // 归属哪个pod沙箱 }, info: { config: { /* CRI容器配置image、env、command、mounts、resource限制 */ }, image: { /* 镜像信息 */ }, sandboxConfig: { /* pod沙箱配置pod namespace、hostname、dns、pod annotation */ } } }crictl缺失 docker 独有的字段重点❌没有HostConfigCRI 模型不使用 docker HostConfig 这套结构资源限制直接放在config.resources❌没有GraphDriver看不到 LowerDir、UpperDir、MergedDir 宿主机 overlay 磁盘路径这是最常踩坑点❌没有 docker 风格Mounts完整结构体挂载在config.mounts只有简单source,destination,readonly缺少 docker 的 volume 驱动信息❌没有 NetworkSettings网络信息放在inspectp(pod sandbox)里面业务容器本身不带网络信息网络属于 Pod 沙箱 pause 容器。K8s 中网络、hostname、dns、pid/uts/net 命名空间全部归属于PodSandbox(pause)业务容器共享沙箱的命名空间。 所以看 Pod IP、网络 namespace 要执行crictl inspectp pod-sandbox-id而不是看业务 container。crictl查看基础镜像要找到nfvo-lcm-server这个容器的 overlay 路径不要用容器 ID 去 grepmount应该反过来从进程的挂载信息里找。方法一通过容器 PID 查/proc最准确先拿到容器的 PIDcrictl inspect 3b6bdb6a4eca9 --output go-template --template {{.info.pid}}然后用这个 PID 去看它的挂载信息cat /proc/PID/mountinfo | grep overlay这条命令输出的upperdir和lowerdir就是属于这个容器的真实路径3、关键概念映射表containerd 环境表格功能docker inspectcrictl inspect / inspectp进程状态、PID、退出码Statestatus容器启动命令、环境变量Config.{Env,Cmd,Entrypoint}info.config.{env,command}CPU / 内存资源限制HostConfiginfo.config.resourcesoverlay2 磁盘路径 (Lower/UpperDir)GraphDriver.Data❌获取不到CRI 接口不暴露镜像分层 RootFSRootFS❌CRI 不返回 RootFS diffID挂载卷信息Mounts[]info.config.mounts[]信息精简Pod / 容器 IP、网络命名空间NetworkSettings在crictl inspectp sandboxID(pause 沙箱)业务容器无网络主机名、DNS 配置容器内 Config归属 PodSandboxinspectp对象模型单个容器容器自带网络PodSandbox (pause) 多个业务容器分离模型重要crictl拿不到 overlay2 的 UpperDir 等底层存储路径如果需要看 containerd 底层磁盘路径需要去读 containerd 内部元数据CRI 接口不给。K8s 节点底层是 containerd即使节点装了 dockerdocker ps / docker inspect看不到 k8s 的 pod 容器dockerd 和 containerd 是两套完全独立容器存储。4、实操示例K8s containerd 节点bash# crictl 列出pod沙箱 crictl pods # 查看pod沙箱pausePod IP、dns、网络命名空间用 inspectp crictl inspectp pod-sandbox-id # 查看pod里面的业务容器进程、env、command、挂载、资源 crictl inspect container-id # crictl 看不到overlay UpperDir如果想找只能查containerd内部数据库什么时候用哪个docker inspect纯 Docker 环境非 K8s排查 docker 容器、看 overlay 磁盘路径、docker volume、docker 端口映射。crictl inspect / inspectpK8s 节点底层 containerd/cri‑o排查 Pod 沙箱状态、容器进程、env、命令、挂载、资源缺点拿不到底层存储驱动路径 RootFS/GraphDriver。补充 containerd 环境如果非要拿到容器 overlay2 UpperDir/LowerDirCRI 工具 crictl 做不到需要调用 containerd 原生工具ctrbashctr c info container-idctr是 containerd 原生 CLI不是 CRI 标准工具可以拿到存储层路径。5、容易混淆区分小结澄清误区ctr c info并不会直接输出 UpperDir/LowerDir 绝对路径字符串只是可以拿到snapshotKey再手动拼接宿主机快照目录间接找到 overlay 文件。之前表格标记✅容易产生误导。表格工具后端接口适用对象是否可直接输出 Overlay UpperDir/LowerDir 绝对路径是否返回 snapshotKey是否可查看 OCI mounts (容器挂载)docker inspectdockerd (Docker 专属 API)docker run 创建的容器✅ 直接在GraphDriver.Data返回完整路径❌ docker 体系无 snapshotKey 概念✅Mounts字段crictl inspectCRI‑API (高层接口)K8s Pod 容器 (containerd/cri‑o)❌❌ CRI 接口屏蔽快照底层信息✅info.runtimeSpec.mountsnerdctl inspect默认 dockercompat 模式containerd Native APIK8s‑CRI/nerdctl 创建容器❌❌❌ K8s 容器 Mountsnullnerdctl container inspect --modenativecontainerd Native APIK8s‑CRI/nerdctl 创建容器❌❌ nerdctl 不输出 snapshotKey✅spec.mountsctr c infocontainerd Native API底层K8s‑CRI/ctr 创建容器❌间接获取需 snapshotKey 拼接路径✅ 返回.snapshotKey✅spec.mounts关键文字说明消除误导docker inspectdockerd 直接把 overlay 的UpperDir/LowerDir完整绝对路径放在 JSON 返回值开箱即用不需要二次查找。ctr c info返回字段.snapshotKey快照唯一标识不会返回/var/lib/containerd/.../upper这种完整路径。 你需要手动拼接快照根目录/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs/snapshots/${snapshotKey}/进入该目录后才可见 upper、lower、work、merged。所以ctr→ 有钥匙 (snapshotKey)但不给你开好门完整路径docker inspect 直接把门打开给你完整路径。一句话记忆docker inspect docker 私有完整元数据crictl inspect K8s CRI 标准化精简输出Pod 和容器分离屏蔽底层存储细节ctr containerd 底层原生工具可以看到更多底层细节。6、nerdctl 命令ctr≠ nerdctl二者是两套完全独立的客户端只不过都可以调用 containerd‑native API。containerd容器nerdctl工具 需要注意model参数nerdctl -n k8s.io inspect xxx 看不到挂载点nerdctl -n k8s.io inspect--modenative xxx 可以看到挂载点7、nerdctl 看不到 snapshotKeyctr c info 可以那么是工具的问题还是 后面容器的问题完全是工具 (nerdctl) 本身的输出裁剪问题和容器、containerd 后台没有任何关系。你这个 K8s 容器本身确实存在 snapshotKeycontainerd‑Native API 也返回了 snapshotKey只是 nerdctl 主动选择不打印这个字段。❌不是容器问题Kubelet/CRI 创建出来的 Pod 容器100% 都会分配 snapshotKey❌不是权限、命名空间 (k8s.io) 问题nerdctl和ctr使用完全一样的/run/containerd/containerd.sock访问后端。只是由于某些字段是OCI标准字段和非标准字段导致工具实现不同containerd 原生 API获取容器信息返回两块独立数据OCI Runtime Spec.spec进程、环境变量、mounts、namespace、cgroup属于OCI 标准--modenative会完整输出这块内容containerd 扩展字段非 OCI 标准.snapshotKey、.task、.shim、创建快照信息属于 containerd 内部私有元数据不属于 OCI 规范nerdctl container inspect --modenative的设计定位只输出 OCI‑spec 那一块标准内容不输出 containerd 私有扩展字段GitHub。ctr c info是 containerd 底层调试工具把 OCI spec containerd 私有元数据全部打印出来所以你能看到.snapshotKey
阅读完成 · 觉得有帮助?