Red Hat Training

A Red Hat training course is available for RHEL 8

第 51 章 使用 BPF 编译器集合进行网络追踪

本节介绍 BPF Compiler Collection(BCC)是什么,如何安装 BCC,以及如何使用 bcc-tools 软件包提供的预创建脚本执行不同的网络追踪操作。所有这些脚本均支持 --ebpf 参数显示实用程序上传到内核的 eBPF 代码。您可以使用这些代码了解更多有关编写 eBPF 脚本的信息。

51.1. BCC 介绍

BPF Compiler Collection(BCC)是一个库,可帮助创建扩展的 Berkeley Packet Filter(eBPF)程序。eBPF 程序的主要工具是在不需要额外的开销或存在安全问题的情况下,分析操作系统性能和网络性能。

BCC 不再需要用户了解 eBPF 的技术详情,并提供了许多开箱即用的功能,如带有预创建的 eBPF 程序的 bcc-tools 软件包。

注意

eBPF 程序在事件中触发,如磁盘 I/O、TCP 连接以及进程创建。程序不太可能导致内核崩溃、循环或者变得无响应,因为它们在内核的安全性虚拟机中运行。

51.2. 安装 bcc-tools 软件包

本节论述了如何安装 bcc-tools 软件包,该软件包还会将 BPF Compiler Collection(BCC)库作为依赖性安装。

先决条件

流程

  1. 安装 bcc-tools:

    # yum install bcc-tools

    BCC 工具安装在 /usr/share/bcc/tools/ 目录中。

  2. (可选)检查工具:

    # ll /usr/share/bcc/tools/
    ...
    -rwxr-xr-x. 1 root root  4198 Dec 14 17:53 dcsnoop
    -rwxr-xr-x. 1 root root  3931 Dec 14 17:53 dcstat
    -rwxr-xr-x. 1 root root 20040 Dec 14 17:53 deadlock_detector
    -rw-r--r--. 1 root root  7105 Dec 14 17:53 deadlock_detector.c
    drwxr-xr-x. 3 root root  8192 Mar 11 10:28 doc
    -rwxr-xr-x. 1 root root  7588 Dec 14 17:53 execsnoop
    -rwxr-xr-x. 1 root root  6373 Dec 14 17:53 ext4dist
    -rwxr-xr-x. 1 root root 10401 Dec 14 17:53 ext4slower
    ...

    上面列表中的 doc 目录包括了每个工具的文档。

51.3. 显示添加到内核的接受队列中的 TCP 连接

内核在 TCP 3 通道握手中接收 ACK 数据包后,内核会在连接的状态变为 ESTABLISHED后,将连接从 SYN 队列移到 accept 队列。因此,只有成功的 TCP 连接才能在此队列中看到。

tcpaccept 实用程序使用 eBPF 功能显示所有内核添加到 accept 队列的连接。这个程序是轻量级的,因为它跟踪了内核的 accept() 功能,而不是捕获数据包并过滤它们。例如:一般故障排除请使用 tcpaccept 来显示服务器接受的新连接。

流程

  1. 输入以下命令启动追踪内核 accept 队列:

    # /usr/share/bcc/tools/tcpaccept
    PID   COMM      IP RADDR         RPORT  LADDR    LPORT
    843   sshd      4  192.0.2.17    50598  192.0.2.1  22
    1107  ns-slapd  4  198.51.100.6  38772  192.0.2.1  389
    1107  ns-slapd  4  203.0.113.85  38774  192.0.2.1  389
    ...

    每次内核接受连接时,tcpaccept 显示连接详情。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpaccept(8) man page。
  • 有关 tcpaccept 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpaccept_example.txt 文件。
  • 要显示 eBPF 脚本 tcpaccept8) 上传到内核,请使用 /usr/share/bcc/tools/tcpaccept --ebpf 命令。

51.4. 追踪传出的 TCP 连接尝试

tcpconnect 实用程序使用 eBPF 功能跟踪 TCP 连接尝试。该工具的输出还包括失败的连接。

tcpconnect 工具是轻量级的,因为它跟踪了内核的 connect() 功能,而不是捕获数据包并过滤它们。

流程

  1. 输入以下命令启动显示所有传出连接的追踪过程:

    # /usr/share/bcc/tools/tcpconnect
    PID    COMM         IP SADDR      DADDR          DPORT
    31346  curl         4  192.0.2.1  198.51.100.16  80
    31348  telnet       4  192.0.2.1  203.0.113.231  23
    31361  isc-worker00 4  192.0.2.1  192.0.2.254    53
    ...

    每次内核处理传出连接时,tcpconnect 会显示连接详情。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpconnect(8) man page。
  • 有关 tcpconnect 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpconnect_example.txt 文件。
  • 要显示 eBPF 脚本 tcpconnect(8) 上传到内核,请使用 /usr/share/bcc/tools/tcpconnect --ebpf 命令。

51.5. 测量出站 TCP 连接的延迟

TCP 连接延迟是建立连接所需的时间。这通常涉及内核 TCP/IP 处理和网络往返时间,而不是应用程序运行时。

tcpconnlat 工具使用 eBPF 功能来测量发送的 SYN 数据包和接收的响应数据包之间的时间。

流程

  1. 开始测量出站连接的延迟:

    # /usr/share/bcc/tools/tcpconnlat
    PID    COMM         IP SADDR      DADDR          DPORT LAT(ms)
    32151  isc-worker00 4  192.0.2.1  192.0.2.254    53    0.60
    32155  ssh          4  192.0.2.1  203.0.113.190  22    26.34
    32319  curl         4  192.0.2.1  198.51.100.59  443   188.96
    ...

    每次内核处理传出连接时, tcpconnlat 会在内核接收响应数据包后显示连接详情。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpconnlat(8) man page。
  • 有关 tcpconnlat 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpconnlat_example.txt 文件。
  • 要显示 eBPF 脚本 tcpconnlat(8) 上传到内核,请使用 /usr/share/bcc/tools/tcpconnlat --ebpf 命令。

51.6. 显示被内核丢弃的 TCP 数据包和片段详情

tcpdrop 工具可让管理员显示内核丢弃的 TCP 数据包和片段详情。使用这个实用程序调试丢弃数据包的高速率,以便远程系统发送基于计时器的重新传输。释放数据包和片段的高速率可能会影响服务器的性能。

tcpdrop 实用程序使用 eBPF 功能直接从内核检索信息,而不是捕获和过滤数据包。

流程

  1. 输入以下命令来显示丢弃 TCP 数据包和片段详情:

    # /usr/share/bcc/tools/tcpdrop
    TIME     PID    IP SADDR:SPORT       > DADDR:DPORT   STATE (FLAGS)
    13:28:39 32253  4  192.0.2.85:51616  > 192.0.2.1:22  CLOSE_WAIT (FIN|ACK)
    	b'tcp_drop+0x1'
    	b'tcp_data_queue+0x2b9'
    	...
    
    13:28:39 1      4  192.0.2.85:51616  > 192.0.2.1:22   CLOSE (ACK)
    	b'tcp_drop+0x1'
    	b'tcp_rcv_state_process+0xe2'
    	...

    每次内核丢弃 TCP 数据包和网段时,tcpdrop 会显示连接的详情,包括导致丢弃软件包的内核堆栈追踪。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpdrop(8) man page。
  • 有关 tcpdrop 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpdrop_example.txt 文件。
  • 要显示 eBPF 脚本 tcpdrop(8) 上传到内核,请使用 /usr/share/bcc/tools/tcpdrop --ebpf 命令。

51.7. 追踪 TCP 会话

tcplife 实用程序使用 eBPF 跟踪打开和关闭的 TCP 会话,并输出一行总结信息。管理员可以使用 tcplife 来识别连接以及传输的流量数量。

本节中的示例论述了如何显示连接到端口 22(SSH)来检索以下信息:

  • 本地进程 ID(PID)
  • 本地进程名称
  • 本地 IP 地址和端口号
  • 远程 IP 地址和端口号
  • 接收和传输的流量的数量(以 KB 为单位)。
  • 连接处于活跃状态的时间(毫秒)

流程

  1. 输入以下命令开始追踪到本地端口 22 的连接:

    /usr/share/bcc/tools/tcplife -L 22
    PID   COMM    LADDR      LPORT RADDR       RPORT TX_KB  RX_KB      MS
    19392 sshd    192.0.2.1  22    192.0.2.17  43892    53     52 6681.95
    19431 sshd    192.0.2.1  22    192.0.2.245 43902    81 249381 7585.09
    19487 sshd    192.0.2.1  22    192.0.2.121 43970  6998     7 16740.35
    ...

    每次连接关闭时,tcplife 会显示连接详情。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcplife(8) man page。
  • 有关 tcplife 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcplife_example.txt 文件。
  • 要显示 eBPF 脚本 tcplife(8) 上传到内核,请使用 /usr/share/bcc/tools/tcplife --ebpf 命令。

51.8. 追踪 TCP 重新传输

tcpretrans 工具显示 TCP 重传输的详情,如本地和远程 IP 地址和端口号,以及重新传输时的 TCP 状态。

该工具使用 eBPF 功能,因此开销非常低。

流程

  1. 使用以下命令来显示 TCP 重新传输详情:

    # /usr/share/bcc/tools/tcpretrans
    TIME     PID  IP LADDR:LPORT   T> RADDR:RPORT         STATE
    00:23:02 0    4  192.0.2.1:22  R> 198.51.100.0:26788  ESTABLISHED
    00:23:02 0    4  192.0.2.1:22  R> 198.51.100.0:26788  ESTABLISHED
    00:45:43 0    4  192.0.2.1:22  R> 198.51.100.0:17634  ESTABLISHED
    ...

    每当内核调用 TCP 重新传输功能时,tcpretrans 就会显示连接详情。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpretrans(8) man page。
  • 有关 tcpretrans 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpretrans_example.txt 文件。
  • 要显示 eBPF 脚本 tcpretrans(8) 上传到内核,请使用 /usr/share/bcc/tools/tcpretrans --ebpf 命令。

51.9. 显示 TCP 状态更改信息

在 TCP 会话中,TCP 状态会改变。tcpstates 工具使用 eBPF 功能跟踪这些状态更改,并打印包括每个状态持续时间的详细信息。例如:使用 tcpstates 来确定连接是否在初始化状态花费了太多时间。

流程

  1. 使用以下命令开始追踪 TCP 状态更改:

    # /usr/share/bcc/tools/tcpstates
    SKADDR           C-PID C-COMM     LADDR     LPORT RADDR       RPORT OLDSTATE    -> NEWSTATE    MS
    ffff9cd377b3af80 0     swapper/1  0.0.0.0   22    0.0.0.0     0     LISTEN      -> SYN_RECV    0.000
    ffff9cd377b3af80 0     swapper/1  192.0.2.1 22    192.0.2.45  53152 SYN_RECV    -> ESTABLISHED 0.067
    ffff9cd377b3af80 818   sssd_nss   192.0.2.1 22    192.0.2.45  53152 ESTABLISHED -> CLOSE_WAIT  65636.773
    ffff9cd377b3af80 1432  sshd       192.0.2.1 22    192.0.2.45  53152 CLOSE_WAIT  -> LAST_ACK    24.409
    ffff9cd377b3af80 1267  pulseaudio 192.0.2.1 22    192.0.2.45  53152 LAST_ACK    -> CLOSE       0.376
    ...

    每次连接改变其状态时,tcpstates 会显示一个新的行,其中包含更新的连接详情。

    如果多个连接同时更改其状态,使用第一列(SKADDR)中的套接字地址来确定哪些条目属于同一连接。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpstates(8) man page。
  • 有关 tcpstates 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpstates_example.txt 文件。
  • 要显示 eBPF 脚本 tcpstates(8) 上传到内核,请使用 /usr/share/bcc/tools/tcpstates --ebpf 命令。

51.10. 聚合发送到特定子网的 TCP 流量

tcpsubnet 实用程序总结了并聚合本地主机发送到子网的 IPv4 TCP 流量,并显示固定间隔中的输出。该工具使用 eBPF 功能来收集并总结数据,以减少开销。

默认情况下,tcpsubnet 总结了以下子网的流量:

  • 127.0.0.1/32
  • 10.0.0.0/8
  • 172.16.0.0/12
  • 192.0.2.0/24/16
  • 0.0.0.0/0

请注意,最后一个子网(0.0.0.0/0)会捕获所有(catch-all)数据。tcpsubnet 实用程序计算与这个 catch-all 条目中前 4 个不同的子网的所有流量。

按照以下步骤计算 192.0.2.0/24198.51.100.0/24 子网的流量。所有子网的流量都会在 0.0.0.0/0 catch-all 子网条目中跟踪。

流程

  1. 开始监控发送到 192.0.2.0/24198.51.100.0/24 和其他子网的流量数量:

    # /usr/share/bcc/tools/tcpsubnet 192.0.2.0/24,198.51.100.0/24,0.0.0.0/0
    Tracing... Output every 1 secs. Hit Ctrl-C to end
    [02/21/20 10:04:50]
    192.0.2.0/24           856
    198.51.100.0/24       7467
    [02/21/20 10:04:51]
    192.0.2.0/24          1200
    198.51.100.0/24       8763
    0.0.0.0/0              673
    ...

    这个命令以字节为单位显示指定子网每秒一次的流量。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcpsubnet(8) man page。
  • 有关 tcpsubnet 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcpsubnet.txt 文件。
  • 要显示 eBPF 脚本 tcpsubnet(8) 上传到内核,请使用 /usr/share/bcc/tools/tcpsubnet --ebpf 命令。

51.11. 通过 IP 地址和端口显示网络吞吐量

tcptop 程序以 KB 为单位显示主机发送并接收的 TCP 流量。这个报告会自动刷新并只包含活跃的 TCP 连接。该工具使用 eBPF 功能,因此开销非常低。

流程

  1. 要监控发送和接收的流量,请输入:

    # /usr/share/bcc/tools/tcptop
    13:46:29 loadavg: 0.10 0.03 0.01 1/215 3875
    
    PID    COMM         LADDR           RADDR              RX_KB   TX_KB
    3853   3853         192.0.2.1:22    192.0.2.165:41838  32     102626
    1285   sshd         192.0.2.1:22    192.0.2.45:39240   0           0
    ...

    命令的输出只包括活跃的 TCP 连接。如果本地或者远程系统关闭了连接,则该连接在输出中不再可见。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcptop(8) man page。
  • 有关 tcptop 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcptop.txt 文件。
  • 要显示 eBPF 脚本 tcptop(8) 上传到内核,请使用 /usr/share/bcc/tools/tcptop --ebpf 命令。

51.12. 追踪已建立的 TCP 连接

tcptracer 工具跟踪连接、接受和关闭 TCP 连接的内核功能。该工具使用 eBPF 功能,因此开销非常低。

流程

  1. 使用以下命令启动追踪过程:

    # /usr/share/bcc/tools/tcptracer
    Tracing TCP established connections. Ctrl-C to end.
    T  PID    COMM        IP SADDR        DADDR       SPORT  DPORT
    A  1088   ns-slapd    4  192.0.2.153  192.0.2.1   0      65535
    A  845    sshd        4  192.0.2.1    192.0.2.67  22     42302
    X  4502   sshd        4  192.0.2.1    192.0.2.67  22     42302
    ...

    每当内核连接、接受、或关闭连接时,tcptracer 会显示连接详情。

  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 tcptracer(8) man page。
  • 有关 tcptracer 和示例的详情,请查看 /usr/share/bcc/tools/doc/tcptracer_example.txt 文件。
  • 要显示 eBPF 脚本 tcptracer(8) 上传到内核,请使用 /usr/share/bcc/tools/tcptracer --ebpf 命令。

51.13. 追踪 IPv4 和 IPv6 侦听尝试

solisten 实用程序跟踪所有 IPv4 和 IPv6 侦听尝试。它跟踪监听尝试,包括最终失败或者不接受连接的监听程序。当程序要侦听 TCP 连接时,程序会追踪内核调用的功能。

流程

  1. 输入以下命令启动显示所有监听 TCP 尝试的追踪过程:

    # /usr/share/bcc/tools/solisten
    PID    COMM           PROTO         BACKLOG     PORT     ADDR
    3643   nc             TCPv4         1           4242     0.0.0.0
    3659   nc             TCPv6         1           4242     2001:db8:1::1
    4221   redis-server   TCPv6         128         6379     ::
    4221   redis-server   TCPv4         128         6379     0.0.0.0
    ....
  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 solisten man page。
  • 有关 solisten 和示例的详情,请查看 /usr/share/bcc/tools/doc/solisten_example.txt 文件。
  • 要显示 eBPF 脚本 solisten 上传到内核,请使用 /usr/share/bcc/tools/solisten --ebpf 命令。

51.14. 软中断的服务时间概述

softirqs 工具总结了服务软中断(软 IRQ)所花的时间,并将此时间显示为总计或直方分布。这个工具使用 irq:softirq_enterirq:softirq_exit 内核追踪点,这是一个稳定的追踪机制。

流程

  1. 输入以下命令启动追踪 soft irq 事件时间:

    # /usr/share/bcc/tools/softirqs
    Tracing soft irq event time... Hit Ctrl-C to end.
    ^C
    SOFTIRQ          TOTAL_usecs
    tasklet                  166
    block                   9152
    net_rx                 12829
    rcu                    53140
    sched                 182360
    timer                 306256
  2. Ctrl+C 停止追踪过程。

其它资源

  • 详情请查看 softirqs man page。
  • 有关 softirqs 和示例的详情,请查看 /usr/share/bcc/tools/doc/softirqs_example.txt 文件。
  • 要显示 eBPF 脚本 solisten 上传到内核,请使用 /usr/share/bcc/tools/softirqs --ebpf 命令。
  • 有关 mpstat 如何使用此信息的详情,请查看 mpstat(1) man page。

51.15. 其它资源

  • 有关 BCC 的详情,请查看 /usr/share/doc/bcc/README.md 文件。