青蛙小白
博客 / 2025/11

主机安全软件导致 Rook-Ceph OSD 容器启动失败的排查记录

2025/11/08 · — 字 · 阅读约 — 分钟 ·
目录

最近在一个Kubernetes集群部署 Rook-Ceph 时遇到了一个问题:OSD Pod 的主容器能正常启动,但 sidecar 容器却一直报 RunContainerError。折腾了一番,最后发现是节点上装的终端安全软件导致的。

问题现象

部署完成后检查 Pod 状态,发现 node-1 上有几个 Pod 异常:

kubectl get po -n rook-ceph -o wide | grep -v Running
NAME                                   READY   STATUS              RESTARTS   AGE
rook-ceph-osd-2-5bfd79754f-k8smh       0/2     RunContainerError   0          3m14s
rook-ceph-tools-8bd944548-gh29z        0/1     RunContainerError   223        26h

查看 Pod 事件,得到的错误信息是:

Warning  Failed  Error: context deadline exceeded
Message: failed to create containerd task: failed to create shim task: context canceled: unknown

奇怪的是,同样的镜像、同样的配置,node-2 和 node-3 上的 Pod 都正常,唯独 node-1 出问题。更奇怪的是 OSD Pod 的主容器 osd 能正常启动并进入 active 状态,但 log-collector 这个 sidecar 容器就是起不来。

排查过程

首先查看了 containerd 的日志:

journalctl -u containerd --since "10 minutes ago" | grep -i error

日志里都是超时错误:

level=error msg="StartContainer for xxx failed" error="failed to create containerd task: failed to create shim task: context deadline exceeded: unknown"

containerd 报超时,说明某个环节卡住了。为了缩小排查范围,绕过 Kubernetes 直接用 ctr 测试容器启动,发现普通容器能正常跑起来。

这时候注意到 rook-ceph-tools 这个 Pod 也一直起不来,看了一眼它的配置,发现设置了 tty: true。再想想 log-collector 的启动命令是 /bin/bash -m-m 参数会启用 job control,也涉及 TTY 操作。会不会是 TTY 相关的问题?

试了一下带 --tty 参数启动容器:

# 普通容器 - 正常
ctr -n k8s.io run --rm registry.example.com/ceph/ceph:v19.2.0 test echo hello
# 输出: hello

# 带 TTY 的容器 - 卡住
ctr -n k8s.io run --rm --tty registry.example.com/ceph/ceph:v19.2.0 test-tty /bin/bash -c "echo hello"
# 无响应

果然卡住了。在 node-2 上执行同样的命令,完全正常。问题锁定在 node-1 这台机器上。

既然进程卡住了,那就看看它卡在哪。找到了卡住的 runc init 进程,查看其内核调用栈:

cat /proc/<PID>/stack

输出如下:

[<0>] wait_woken+0x50/0x60
[<0>] n_tty_read+0x569/0x630
[<0>] tty_read+0x121/0x250
[<0>] jt_get_file_buffer+0x8d/0xc0 [resguard_linux]
[<0>] se_check_close_post+0x14d/0xd60 [resguard_linux]
[<0>] filter_close_post+0x1fc/0x240 [resguard_linux]
[<0>] hook_x64_sys_call+0x9e/0xd0 [syshook_linux]

调用栈里出现了 resguard_linuxsyshook_linux 这两个内核模块。一看名字就猜出是安全软件加载的。进程卡在 TTY 相关的系统调用上,而这些调用被安全模块拦截了。

对比了 node-1 和 node-2 的内核模块:

# node-1
lsmod | grep -E "resguard|syshook"
resguard_linux        643072  2
syshook_linux         135168  1

# node-2
lsmod | grep -E "resguard|syshook"
# (无输出)

果然,node-1 上装了某终端安全软件,而其他两个节点没有。

原因分析

该安全软件通过内核模块 hook 系统调用来实现安全防护。syshook_linux 负责拦截系统调用,resguard_linux 则实现具体的安全检测逻辑。这种 TTY 拦截机制通常用于防止反弹 Shell 攻击、审计终端操作等场景。

问题在于,容器运行时需要为某些容器分配 PTY。当容器配置了 tty: true,或者启动命令需要 job control 时,containerd 会尝试分配伪终端。安全软件的内核模块拦截了这个过程,导致操作阻塞,最终 containerd shim 等待超时。

回过头看受影响的容器:log-collector 的启动命令是 /bin/bash -m-m 参数启用 job control,需要进行 TTY 操作;rook-ceph-tools 则直接在 spec 里配置了 tty: true。这就解释了为什么它们会卡住。

解决方案

经过查看,找到了这个安全软件有自带的卸载脚本,可以直接用:

/usr/local/wsssr_defence_agent/uninstall

卸载后再次查看:


# 查看模块依赖
lsmod | grep -E "resguard|syshook|secmodel"

# 按顺序卸载(先卸载依赖的模块)
rmmod resguard_linux
rmmod syshook_linux
rmmod secmodel_linux 2>/dev/null

# 验证模块已卸载
lsmod | grep -E "resguard|syshook"

重建受影响的 Pod:

kubectl delete pod -n rook-ceph -l osd=2
kubectl delete pod -n rook-ceph -l app=rook-ceph-tools

Pod 立刻就能正常启动了。

这次是为了快速恢复服务临时卸载了安全软件,后续还是要联系安全团队,把容器运行时的进程(containerd-shim-runc-v2、runc 等)加入白名单,避免安全防护与容器环境冲突。

总结

这次能快速定位问题,主要靠对比正常和异常节点的差异。发现只有一台节点有问题后,用 ctr run --tty 确认是 TTY 相关的问题,然后看 /proc/<PID>/stack 找到卡在哪,一下就看到安全软件的内核模块了。

说起来,这台节点是后来加的,装了安全软件但其他节点没装,配置不一致才导致这个坑。以后在 K8s 节点上装安全软件之前,还是得先测一下对容器的影响,不然出了问题不好排查。

评论