ebpf調研(2)
接著上次,普補充完善2個部分:
- bpftrace使用 以及與k8s的結合
在調研(1)簡要介紹了下bpftrace,這里在深入了解一下,它 類似于 DTrace 或 SystemTap,它在 eBPF 之上構建了一個簡化的跟蹤語言, 也叫D語言,通過簡單的幾行腳本,就可以達到復雜的跟蹤功能。多行的跟蹤指令也可以放到腳本文件中執行,腳本后綴通常為 .bt。生產環境中,推薦使用 docker 來運行 bpftrace。比如:
另外,在k8s里面,為了更加方便的使用bpftrace,建議采用kubectl-trace插件,它是IOVisor開源的,安裝kubectl-trace非常簡單,直接在kubectl所在機器上執行。具體見:
//github.com/iovisor/kubectl-trace
# kubectl trace is a kubectl plugin that allows you to schedule the execution of bpftrace programs in your Kubernetes cluster.
既能trace某個node,也能trace任意的container 。舉例如下
# kubectl trace run $nodemame -e "tracepoint:syscalls:sys_enter_* { @[probe] = count(); }"# kubectl trace run $nodemame -f read.bt (把命令放到文件中)
# kubectl trace run -e 'uretprobe:/proc/$container_pid/exe:"main.counterValue" { printf("%d\n", retval) }' pod/$pod_name 。
可見, kubectl trace 用法和bpftrace用法基本一致,就是把bpftrace包裝了一下。
注意: 當 kubectl trace 需要trace內核服務時,需要一些特權,例如基于PSP策略,但是PodSecurityPolicy 在 Kubernetes v1.21 版本中被棄用,將在 v1.25 中刪除。
- 邊緣網絡eBPF超能力 (字節最佳實踐)
火山引擎邊緣計算在數據面也大量使用了 eBPF 及其 map 機制,并基于 eBPF 實現了 VPC 網絡、負載均衡、彈性公網 IP、外網防火墻等一系列高性能、高可用的云原生網絡解決方案。//www.volcengine.com/docs/6499
虎牙基礎架構團隊在邊緣計算方面做了很多工作,支持實時內容加工能力很好下沉到邊緣,研發了邊緣容器方案和邊緣容器網絡。為解決邊緣公網抖動的問題,自研了“蜘蛛俠”虎牙 SDWAN 解決方案,建設了基于 ebpf 和 dpdk 的適應視頻業務高帶寬、低延時的高性能邊緣網關。
- 內置的bcc-tool介紹
BCC 內置了一套強大的工具集,叫bcc-tool, 它是基于ebpf技術開發的一套功能強大的Linux性能監視,網絡等動態跟蹤工具。 下面簡要介紹了下的它的用法。
例如
- trace磁盤IO和延遲(latency)
- Trace unix/tcp套接字
- Trace exec()系統調用, 即使是短時系統調用。(deubg ,Trouble-shoot)
- Trace on-cpu/off-cpu分布
- Trace oom情況
bcc-tools 相關命令
#cd /usr/share/bcc/introspection
#./bps --help
BPF Program Snapshot (bps):
List of all BPF programs loaded into the system.
Usage: bps [bpf-prog-id]
[bpf-prog-id] If specified, it shows the details info of the bpf-prog
# cd /usr/share/bcc/tools
# cd /usr/share/bcc/tools
|
./profile -h 參數說明 |
詳細描述 |
|
Profile CPU stack traces at a timed interval |
給CPU的棧軌跡(Stack Trace)畫像(prifile)
|
| -p PID, --pid PID profile this PID only | 只追蹤該pid的調用流程 |
|
-U, --user-stacks-only show stacks from user space only (no kernel space stacks) |
只查看用戶態調用流程,無內核態
|
| -K, --kernel-stacks-only show stacks from kernel space only (no user space stacks) |
只查看內核態調用流程,無用戶態 |
|
-F , --frequency sample frequency, Hertz |
例如: -F 99 表示按照99hz的頻率進行采樣,默認是采用的49hz |
|
-c COUNT, --count COUNT sample period, number of events |
選擇采樣次數 -c 5表示在周期內采樣5次,-c和-F兩者不能同時使用 |
| -C CPU, --cpu CPU cpu number to run profile on | 允許幾個cpu運行profile程序
|
| --stack-storage-size STACK_STORAGE_SIZE the number of unique stack traces that can be stored and displayed (default 16384) | 設置調用棧的使用空間和默認支持空間大小,unique stack traces(默認的棧是16k)
unique stack traces 是什么呢? |
//www.cnblogs.com/haoxing990/p/12122372.html
| ./funclatency -h | |
| Time functions and print latency as a histogram | funclatency從字面意思就可以知道其作用是獲取函數的執行時延(這里的時延可不是函數被延時了多長時間,而是函數執行了多長時間),以直方圖(histogram)形式展示 |
| -p PID, --pid PID trace this PID only | 指定跟蹤某個進程ID各函數花費時間 |
| -i INTERVAL, --interval INTERVAL summary interval, in seconds | 指定執行間隔時間,以秒為單位 |
| -d DURATION, --duration DURATION total duration of trace, in seconds | 指定該程序運行多次時間。-i和-d配合使用 -i 2 -d 10 # output every 2 seconds, for duration 10s,每隔2s輸出一次,持續10s |
| -T, --timestamp include timestamp on output | 輸出時間戳,即當前調用funlatency的具體時間 |
| -u, --microseconds microsecond histogram -m, --milliseconds millisecond histogram | 矩形圖統計采用us的形式矩形圖統計采用ms的形式 |
| -r, --regexp use regular expressions. Default is "*" wildcards only. | 正則表達式,匹配規則,監測某一類函數,只有*是通配符 |
| ./funclatency 'c:*printf' # time the *printf family of functions | 這里c:是什么意思? |
| ./funclatency c:read 查看用戶態動態庫函數read執行時間分布情況 | 這里c:是什么意思? |
| ./funclatency 'clone' ./funclatency 'vfs_fstat*' | 0 functions matched by "clone". Exiting. 0 functions matched by "vfs_fstat*". Exiting. 追蹤vfs_fstat*類函數總共運行時間分布情況 |
//www.cnblogs.com/haoxing990/p/12129914.html
|
./hardirqs -h |
|
| Summarize hard irq event time as histograms
|
硬中斷時間時間和直方圖 |
| positional arguments: interval output interval, in seconds outputs number of outputs |
輸出間隔, 輸出次數。 ./hardirqs 1 10 # print 1 second summaries, 10 times 用每隔一秒共顯示一次,共十次的形式 |
| -T, --timestamp include timestamp on output -N, --nanoseconds output in nanoseconds -C, --count show event counts instead of timing -d, --dist show distributions as histograms | 顯示時間戳, 用ns的形式顯示 不顯示各中斷執行時間,而是顯示中斷發生的次數
對每一個硬中斷各自采用矩形圖方式顯示出來
|
| ./hardirqs -NT 1 | 每隔1s顯示一次,單位為ns,并顯示時間戳 |
從help來看,hardirqs功能支持過于單調,甚至沒法支持單獨跟蹤某一個硬中斷的功能,這塊可能讓人覺得很無語,但是這么做原因是為什么呢? 筆者認為主要有兩個
原因:
- 想單獨跟蹤某個函數的話,采用funclatency足以。
- hardirqs相比采用perf跟蹤中斷情況更加輕量高效。
//www.cnblogs.com/haoxing990/p/12130344.html
|
./softirqs -h |
|
|
Summarize soft irq event time as histograms. |
softirqs顧名思義,用于跟蹤軟中斷事件,主要用于軟中斷處理時延的跟蹤。和 hardirqs 用法一樣,這里省略 |
//www.cnblogs.com/haoxing990/p/12153979.html
在使用funcslower這個函數時,發現其功能相比funclatency對時間更加具體化,對于想知道某個函數執行時間分布情況時,采用funclatency是個不錯的選擇,但是對于急切想知道系統中某個函數被執行的時間時,使用funcslower再方便不過了。
funcslower字面意思,函數中的慢者,簡而言之,查看哪些函數調用執行時間超過了某個設定值。這個功能可能會是你在多種系統分析工具都無效后,作為最后的診斷手段,用于系統性能問題分析了。
|
./funcslower -h |
|
|
Trace slow kernel or user function calls. |
追蹤 kernel 和 user 慢函數調用 |
| -m MIN_MS, --min-ms MIN_MS minimum duration to trace (ms) -u MIN_US, --min-us MIN_US minimum duration to trace (us) | # 執行時間低于xx ms,作為閾值# 執行時間長于xx us,作為閾值 |
| -U, --user-stack show stacks from user space -K, --kernel-stackshow stacks from kernel space | #顯示用戶態棧調用信息
#顯示內核態棧調用信息 |
| -f print output in folded stack format. | # 個人認為是用于生成火焰圖時可以考慮
|
| -a ARGUMENTS, --arguments ARGUMENTS print this many entry arguments, as hex | #打印輸入參數,按照十進制的方式
|
| ./funcslower __kmalloc -a 2 -u 1 |
顯示執行__kmalloc時間操作1us的進程,并且打印出每一個進程傳入該函數的前兩個參數值。 |
| ./funcslower read -a 3 -u 1 |
cannot attach kprobe, probe entry may not exist
Exception: Failed to attach BPF program trace_0 to kprobe read |
| ./funcslower c:read -a 3 -u 1 |
這樣才對,用c:read 還不知道why? |
//www.cnblogs.com/haoxing990/p/12159247.html
|
./funccount -h |
|
|
Count functions, tracepoints, and USDT probes user-mode statically defined traces (USDT) |
從funccount的字面意思可以看出,其作用在于統計函數被調用的次數。 |
|
-p PID, --pid PID trace this PID only |
僅僅跟蹤某個進程調用情況 |
|
-i INTERVAL, --interval INTERVAL summary interval,seconds |
每間隔多長時間打印一次跟蹤結果,單位為s |
|
-d DURATION, --duration DURATION total duration of trace, seconds |
跟蹤持續多長時間,單位為s |
|
-r, --regexp use regular expressions. Default is "*" wildcards |
對于跟蹤某一類的函數,匹配規則可以采用*符號 |
|
./funccount c:malloc # count all malloc() calls in libc
./funccount go:os.* # count all "os.*" calls in libgo |
c:代表c程序 go:代表go程序 |
| -D, --debug print BPF program before starting (for debugging purposes) | # 顯示跟蹤調試信息, 程序源碼 |
//www.cnblogs.com/haoxing990/p/12178807.html
|
./runqlat -h |
|
| Summarize run queue (scheduler) latency as a histogram |
runplat的作用在調度性能分析這塊十分的重要,其作用是主要檢測一個tasks從運行隊列中到運行需要等待的時延。 |
| positional arguments:interval output interval, in seconds count number of outputs | #輸出間隔時間,單位秒 #輸出次數 |
|
./runqlen -h |
|
|
Summarize scheduler run queue length as a histogram |
runqlen從字面意思,很簡單的看出其是統計運行隊列的長度 輸出結果中 count 是什么意思呢? |
//www.cnblogs.com/haoxing990/p/12203742.html
pidpersec從字面意思來了,就是個每秒pid產生的數目。這個家伙功能較為單一,做用就是統計每秒通過fork產生的pid數目。這家伙沒有help功能,所以其功能十分單一。
先了解什么是off-cpu
//www.cnblogs.com/haoxing990/p/12203997.html
On-CPU: where threads are spending time running on-CPU.
Off-CPU: where time is spent waiting while blocked on I/O, locks, timers, paging/swapping, etc.
從上面的意思基本上了解offcputime的意思是什么了:用于測量某一進程被阻塞的時間。
|
./offcputime -h |
|
|
Summarize off-CPU time by stack trace |
測量某一進程被阻塞的時間 |
|
positional arguments: duration duration of trace, in seconds |
持續時間,單位秒 |
| -p PID, --pid PID trace this PID only
-t TID, --tid TID trace this TID only |
#僅僅跟蹤某一進程阻塞時間 #僅僅跟蹤某一線程阻塞時間 |
| -u, --user-threads-onlyuser threads only (no kernel threads) -k, --kernel-threads-onlykernel threads only (no user threads) | #僅僅跟蹤用戶態而非內核態線程阻塞時間#僅僅跟蹤內核態線程阻塞時間
|
| -U, --user-stacks-onlyshow stacks from user space only (no kernel space stacks) -K, --kernel-stacks-only show stacks from kernel space only (no user space stacks) | #僅僅顯示用戶態調用棧關系
#僅僅顯示內核態調用棧關系 |
| -f, --folded output folded format | # 采用折疊模式輸出, 也就是按照行的形式輸出 |
| -m MIN_BLOCK_TIME, --min-block-time MIN_BLOCK_TIME the amount of time in microseconds over which we store traces (default 1) -M MAX_BLOCK_TIME, --max-block-time MAX_BLOCK_TIME the amount of time in microseconds under which we store traces (default U64_MAX) | #只打印阻塞時間不小于xxx us的進程情況 #只打印阻塞時間不大于xxx us的進程情況 只打印 -m <= x <= -M之間的。單位是us |
pcstat( page cache stat )頁緩存統計命令