提到如何动态追踪进程中的系统调用,相信你们第一时间都能想到 strace,它的基本用法很是简单,很是适合用来解决 “为何这个软件没法在这台机器上运行?” 这类问题。但若是须要分析线上服务 (特别是延迟敏感型)的某些系统调用的延迟时,strace 则不那么合适,由于它引入的开销会很是大,从性能分析大师 Brendan Gregg 的测试结果得知,被 strace 追踪的目标进程的运行速度会下降 100 倍以上,这对生产环境来讲将是个灾难。前端
那么是否有比较好用的工具用在生产环境上呢?答案是确定的,下面将介绍两款工具的经常使用命令,方便你们须要时查阅。api
众所周知,perf 是 Linux 系统下很是强大的性能工具,由 Linux 内核开发人员在不断演进和优化。除了能够分析 PMU (Performance Monitoring Unit) 硬件事件,内核事件等通用功能外,perf 还提供了其余“子模块”,好比 sched 分析调度器,timechart 根据负载特征可视化系统行为,c2c 分析可能存在的 false sharing (RedHat 在大量 Linux 的应用上,测试过这套 c2c 的开发原型,成功地发现了不少热点的伪共享缓存行问题。)等, 而 trace 则可用于分析系统调用,其功能很是强大,并保证了能够接受的开销—— 运行速度仅放慢 1.36 倍(dd 做为测试负载) 。咱们一块儿看下几个经常使用的场景:缓存
调用 syscall 数量的 top 排行榜数据结构
perf top -F 49 -e raw_syscalls:sys_enter --sort comm,dso --show-nr-samples
从输出能够看到在采样期间,kube-apiserver 的调用 syscall 的次数最多。架构
显示超过必定延迟的系统调用信息ssh
perf trace --duration 200
从输出中能够看到进程名称、pid ,超过 200 ms 的具体系统调用参数和返回值。工具
统计某个进程一段时间内系统调用的开销oop
perf trace -p $PID -s
从输出中能够看到各系统调用的次数,返回错误次数,总延迟,平均延迟等信息。性能
咱们也能够进一步分析高延迟的调用栈信息测试
perf trace record --call-graph dwarf -p $PID -- sleep 10
对一组任务进行 trace,好比后台有 2 个 bpf 工具在运行,咱们想看下它们系统调用使用状况,就能够先将它们添加到 perf_event 这个 cgroup 下,再执行 perf trace:
mkdir /sys/fs/cgroup/perf_event/bpftools/ echo 22542 >> /sys/fs/cgroup/perf_event/bpftools/tasks echo 20514 >> /sys/fs/cgroup/perf_event/bpftools/tasks perf trace -G bpftools -a -- sleep 10
perf-trace 的使用就介绍到这里,更多的用法请参考 man 手册,从上面能够看到 perf-trace 的功能很是强大,根据 pid 或 tid 就能够进行过滤。但彷佛没有对容器和 K8S 环境进行便捷的支持。不用着急,接下来介绍的这个工具就是针对容器和 K8S 环境的。
对于 Traceloop 你们可能有点陌生,但提到 BCC 想必你们就以为熟悉了。BCC 的前端是 Python/C++,其所属 iovisor 下还有一个项目叫 gobpf 是 BCC 的 go binding。而 Traceloop 则是基于 gobpf 库进行开发的,此项目的主要目标应用场景是容器、K8S 环境。其原理比较简单,其架构如图所示:
核心步骤以下:
须要注意的是,当前 cgroup id 的获取方式是经过 bpf helper:bpf_get_current_cgroup_id 来获取的,这个 id 是 cgroup v2 才有的。所以只适用于开启了 cgroup v2 的环境。尚不肯定此项目团队是否有意向经过读取 nsproxy 数据结构等方式来对 cgroup v1 进行支持,所以在这里只作简单介绍。随着 K8S 1.19 版本开始支持 cgroup v2,期待 cgroup v2 能尽快普及起来。如下使用 Centos 8 4.18 版本内核进行简单的演示:在 traceloop 退出时 dump 系统调用信息
sudo -E ./traceloop cgroups --dump-on-exit /sys/fs/cgroup/system.slice/sshd.service
从输出中能够看到,其输出和 strace/perf trace 相似,只是针对 cgroup 进行过滤。须要注意的是 Centos 8 没有像 Ubuntu 将 cgroup v2 挂载到 /sys/fs/cgroup/unified,而是直接挂载到 /sys/fs/cgroup 下,在使用前建议执行 mount -t cgroup2
来肯定挂载信息。
对于 K8S 平台,该团队将 traceloop 集成到 Inspektor Gadget 项目中,经过 kubectl 插件来运行,因为管网给出详细的 gif 示例,在这里就不作过多介绍了,对 cgroup v2 有需求的朋友能够试一试。
从 benchmark 结果看,strace 的引发的目标程序性能降低最大,perf trace 次之,traceloop 最小。
strace 依然是解决 “为何这个软件没法在这台机器上运行?” 相关问题的利器,但对于分析系统调用延迟等问题,perf trace 是合适的选择,其也是基于 BPF 的实现,对于使用 cgroup v2 的容器、K8S 环境,traceloop 会更方便一些。