4. containerd 运行时故障排查:服务状态检查、日志分析与常见错误处理

在自动化发布流水线中,containerd 作为容器运行时的核心组件,其稳定性直接决定镜像拉取、容器创建与销毁等关键操作的成败。本章聚焦 containerd 服务状态检查、日志分析以及 shim 异常等高频故障的处理方法,帮助运维与开发人员快速定位并恢复运行时故障。

4.1 containerd 服务状态检查

故障排查的第一步是确认 containerd 服务是否正常运行。以下命令用于检查服务状态、监听端口与 gRPC 接口健康度。

检查项 命令 预期输出
systemd 服务状态 systemctl status containerd Active: active (running)
监听端口 ss -tlnp | grep containerd LISTEN 0 128 *:9090 *:*
gRPC 健康检查 ctr version Client/Server 版本号正常返回
命名空间列表 ctr namespace ls 至少包含 default、k8s.io 等
排查要点:如果 systemctl status containerd 显示 Active: failed,立即查看 journalctl -u containerd --no-pager -n 50 获取最后 50 行日志;若端口未监听,检查 containerd 配置文件 /etc/containerd/config.toml 中的 grpc.address 是否正确。

4.2 日志分析:结构化定位故障根因

containerd 日志默认输出到 systemd journal,日志级别从 debug 到 fatal。以下表格列出常见日志模式及其对应的故障类型。

日志模式 故障类型 典型错误片段
level=error msg="failed to start shim" shim 启动失败 exec: "containerd-shim-runc-v2": executable file not found
level=warning msg="image garbage collection failed" 镜像 GC 异常 unlinkat /var/lib/containerd/io.containerd.snapshotter.v1.overlayfs: device or resource busy
level=error msg="failed to dial" gRPC 连接中断 connection refused: tcp 127.0.0.1:9090
level=info msg="stop container with signal" 容器被强制终止 signal: killed (OOM 或超时)
日志分析三步法:
1. 使用 journalctl -u containerd -f 实时跟踪日志流。
2. 过滤特定级别:journalctl -u containerd -p err --since "5 min ago"。
3. 结合时间戳与容器 ID 交叉关联:grep "container_id" /var/log/containerd.log。
containerd 日志分析流程 containerd 日志分析流程 journalctl 采集 级别过滤 (err/warn) 模式匹配 shim 启动失败 镜像 GC 异常 gRPC 连接中断 提示:使用 journalctl -u containerd -p err --since "10 min ago" 快速定位当前故障

4.3 常见错误处理:shim 异常深度剖析

shim 是 containerd 与 runc 之间的中间层,负责管理容器进程的生命周期。shim 异常是流水线中最常见的运行时故障之一,表现为容器创建失败、容器无故退出或残留僵尸进程。

4.3.1 shim 异常典型场景

场景 错误日志 根因
shim 二进制缺失 exec: "containerd-shim-runc-v2": stat /usr/bin/containerd-shim-runc-v2: no such file or directory containerd 安装不完整或升级后未同步 shim 二进制
shim 进程 OOM shim process killed: signal: killed (OOM) shim 内存限制过低或节点内存不足
shim 与 runc 版本不兼容 failed to create shim task: runc version mismatch containerd 与 runc 版本组合不匹配
shim 僵尸进程残留 failed to reap shim pid: waitid: no child processes 容器异常退出后 shim 未正确清理

4.3.2 shim 异常恢复步骤

  1. 确认 shim 二进制完整性:检查 /usr/bin/containerd-shim-runc-v2 是否存在且可执行;若缺失,重新安装 containerd 或手动复制二进制。
  2. 检查 shim 进程状态:ps aux | grep containerd-shim,查看是否有大量僵尸进程(状态 Z)。
  3. 清理残留 shim 进程:使用 kill -9 <PID> 强制终止异常 shim,然后执行 ctr tasks kill --signal 9 <container_id> 清理对应容器。
  4. 验证 runc 版本兼容性:runc --version 与 containerd --version 对比,确保大版本一致。
  5. 重启 containerd 服务:systemctl restart containerd,重启后立即检查日志确认 shim 正常启动。
注意:强制终止 shim 进程可能导致容器数据丢失或文件系统损坏。在生产环境中,优先尝试 ctr container delete <container_id> 优雅删除,再处理残留 shim。
shim 异常恢复流程 shim 异常恢复流程 检测 shim 异常 检查 shim 二进制 清理残留 shim 进程 重启 containerd 服务 恢复后执行 ctr version 验证服务健康

4.4 其他常见错误处理

4.4.1 镜像拉取超时

流水线中镜像拉取超时会导致构建失败。排查步骤:

  • 检查网络连通性:curl -I https://registry-1.docker.io/v2/。
  • 查看 containerd 配置中的 max_concurrent_downloads 和 timeout 参数。
  • 临时增加超时:修改 /etc/containerd/config.toml 中 [plugins."io.containerd.grpc.v1.cri".registry] 下的 timeout 为 300s。

4.4.2 容器启动后立即退出

常见于入口命令错误或依赖缺失。排查方法:

  • 使用 ctr container list 确认容器状态为 STOPPED。
  • 查看容器日志:ctr task logs <container_id>。
  • 检查 shim 日志中是否有 exit code 127(命令未找到)或 exit code 1(通用错误)。
自动化流水线集成建议:在 CI/CD 流水线中加入 containerd 健康检查步骤,例如:
#!/bin/bash
if ! systemctl is-active --quiet containerd; then
  echo "containerd 服务异常,触发自动恢复"
  systemctl restart containerd
  sleep 3
  if ! systemctl is-active --quiet containerd; then
    echo "自动恢复失败,请人工介入"
    exit 1
  fi
fi

4.5 故障排查清单

步骤 操作 验证命令
1 检查 containerd 服务状态 systemctl status containerd
2 查看最近错误日志 journalctl -u containerd -p err --since "1 hour ago"
3 确认 shim 二进制存在 which containerd-shim-runc-v2
4 清理僵尸 shim 进程 ps aux | grep defunct | grep -v grep
5 验证 gRPC 接口 ctr version
6 重启 containerd 服务 systemctl restart containerd

通过以上系统化的状态检查、日志分析与 shim 异常处理流程,运维人员可以在自动化发布流水线中快速恢复 containerd 运行时故障,保障容器编排的连续性与稳定性。