Linux sysdig / sysdig-probe 的容器内 syscall 捕获与 chisels 分析

2次阅读

容器内 syscall 捕获必须用 sysdig -pc,它启用容器上下文感知,自动做 pid/ns 映射、路径重写和 cgroup 标注;-pc 缺失时看到的全是宿主机视角信息。

Linux sysdig / sysdig-probe 的容器内 syscall 捕获与 chisels 分析

容器内 syscall 捕获必须用 sysdig -pc,不是 sysdig -p

默认 sysdig 在容器里跑,看到的是宿主机视角的 syscall,PID、文件路径、网络地址全是宿主机命名空间里的——你查不到容器内进程的真实 /proc/123/root 下的文件,也看不到它实际绑定的 0.0.0.0:8080(而可能是 10.42.1.5:8080)。关键在 -pc:它启用容器上下文感知,自动做 PID/ns 映射、路径重写、cgroup 标注。

  • -pc 会把 evt.arg.filename/tmp/foo 翻译成容器内真实路径(如 /app/config.yaml),前提是容器挂载没用 :robind mount 覆盖 /proc
  • 不用 -pc 时,fd.name 对 socket 可能显示 172.17.0.3:5432,用了之后才变成容器内进程看到的 postgres:5432
  • 如果容器用 --pid=host--network=host-pc 仍生效,但部分字段(如 container.id)可能为空——这不是 bug,是 cgroup v1/v2 检测逻辑限制

sysdig-probe 加载失败常见于内核模块签名和 CONFIG_MODULE_SIG

很多发行版(RHEL 8+/centos Stream 9、ubuntu 22.04+)默认开启内核模块强制签名,sysdig-probesysdig-probe.ko 若未签名或密钥不匹配,insmod 直接报 Required key not available。这不是 sysdig 版本问题,是内核策略。

  • 检查是否触发签名限制:dmesg | grep -i "signature",出现 module verification failed 就是它
  • 临时绕过(仅调试):sudo mokutil --disable-validation + 重启,或启动时加 nosignature 内核参数(需 GRUB 配置)
  • 生产环境应重编译 probe:sudo /usr/share/sysdig/scripts/build_probe.sh,它会调用当前内核头和 dkms,生成已签名模块(前提是你有签名密钥)

chisel 分析容器流量时,netstatecho_fds 输出字段含义不同

netstat chisel 列的是连接元数据(含容器名、端口、状态),echo_fds 则聚焦 fd 层级的 syscall 上下文(比如哪个线程 open() 了哪个 socket、后续是否 connect() 成功)。两者输出字段名一样,但来源和精度不同——别拿 netstatcontainer.nameecho_fdscontainer.name 用。

  • netstat -pccontainer.name 来自 cgroup path 解析,稳定;echo_fds -pccontainer.name 是 syscall 触发时实时查的,若进程刚 fork 出来还没进 cgroup,可能为空
  • 分析 http 404 错误时,echo_fds 能看到 write syscall 的 buffer 内容(需 -A),但 netstat 只能看到连接建立成功与否
  • 对 gRPC 流式调用,netstat 显示一条 ESTABLISHED 连接,echo_fds 却可能列出几十次 sendto,因为每个 message 都是一次 syscall

docker + sysdig 容器化部署时,/dev/sysdig 设备权限容易被 SElinux 拦截

即使加了 --device /dev/sysdig,容器里运行 sysdig -pc -c topfiles_bytes 还是卡住或报 Operation not permitted,大概率是 SELinux 的 sysdig_device_t 类型没放开。AppArmor 同理,但更少见。

  • 快速验证:ausearch -m avc -ts recent | grep sysdig,如果有 avc: denied { read } for dev="sysdig",就是它
  • 临时放行:sudo setsebool -P container_sysdig_device 1(RHEL/CentOS);Ubuntu 上则需 sudo aa-logprof 交互添加 /dev/sysdig 访问规则
  • 注意:docker run --privileged 能绕过,但等于开了所有设备访问,不推荐——只要明确给 /dev/sysdig + 正确 SELinux 上下文即可

事情说清了就结束。syscall 捕获的“容器内”不是靠猜路径实现的,是靠 -pc 实时做 Namespace 映射;probe 加载失败八成是签名拦的,不是 sysdig 自己坏了;chisel 字段看着一样,背后数据源差得远;SELinux 不是摆设,它真会默默挡掉 /dev/sysdig

text=ZqhQzanResources