線上環境 Linux 系統調用追蹤

提到如何動態追蹤進程中的系統調用,相信你們第一時間都能想到 strace,它的基本用法很是簡單,很是適合用來解決 「爲何這個軟件沒法在這臺機器上運行?」 這類問題。但若是須要分析線上服務 (特別是延遲敏感型)的某些系統調用的延遲時,strace 則不那麼合適,由於它引入的開銷會很是大,從性能分析大師 Brendan Gregg 的測試結果得知,被 strace 追蹤的目標進程的運行速度會下降 100 倍以上,這對生產環境來講將是個災難。前端

那麼是否有比較好用的工具用在生產環境上呢?答案是確定的,下面將介紹兩款工具的經常使用命令,方便你們須要時查閱。api

Perf

衆所周知,perf 是 Linux 系統下很是強大的性能工具,由 Linux 內核開發人員在不斷演進和優化。除了能夠分析 PMU (Performance Monitoring Unit) 硬件事件,內核事件等通用功能外,perf 還提供了其餘「子模塊」,好比 sched 分析調度器,timechart 根據負載特徵可視化系統行爲,c2c 分析可能存在的 false sharing (RedHat 在大量 Linux 的應用上,測試過這套 c2c 的開發原型,成功地發現了不少熱點的僞共享緩存行問題。)等, 而 trace 則可用於分析系統調用,其功能很是強大,並保證了能夠接受的開銷—— 運行速度僅放慢 1.36 倍(dd 做爲測試負載) 。咱們一塊兒看下幾個經常使用的場景:緩存

  1. 調用 syscall 數量的 top 排行榜數據結構

    perf top -F 49 -e raw_syscalls:sys_enter --sort comm,dso --show-nr-samples

    從輸出能夠看到在採樣期間,kube-apiserver 的調用 syscall 的次數最多。架構

  2. 顯示超過必定延遲的系統調用信息ssh

    perf trace --duration 200

    從輸出中能夠看到進程名稱、pid ,超過 200 ms 的具體系統調用參數和返回值。工具

  3. 統計某個進程一段時間內系統調用的開銷oop

    perf trace -p $PID  -s

    從輸出中能夠看到各系統調用的次數,返回錯誤次數,總延遲,平均延遲等信息。性能

  4. 咱們也能夠進一步分析高延遲的調用棧信息測試

    perf trace record --call-graph dwarf -p $PID -- sleep 10

  5. 對一組任務進行 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

對於 Traceloop 你們可能有點陌生,但提到 BCC 想必你們就以爲熟悉了。BCC 的前端是 Python/C++,其所屬 iovisor 下還有一個項目叫 gobpf 是 BCC 的 go binding。而 Traceloop 則是基於 gobpf 庫進行開發的,此項目的主要目標應用場景是容器、K8S 環境。其原理比較簡單,其架構如圖所示:

核心步驟以下:

  1. 利用 bpf helper 獲取 cgroup id,根據 cgroup id 而不是 pid、tid 進行過濾。
  2. 每一個 cgroup id 對應一個 bpf tail call,經過這種方式實現對此 cgroup id 對應的 perf ring buffer 進行寫入。
  3. 用戶空間根據 cgroup id 讀取對應的 perf ring buffer。

須要注意的是,當前 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

從 benchmark 結果看,strace 的引發的目標程序性能降低最大,perf trace 次之,traceloop 最小。

總結

strace 依然是解決 「爲何這個軟件沒法在這臺機器上運行?」 相關問題的利器,但對於分析系統調用延遲等問題,perf trace 是合適的選擇,其也是基於 BPF 的實現,對於使用 cgroup v2 的容器、K8S 環境,traceloop 會更方便一些。

相關文章
相關標籤/搜索