iofsstat:幫你輕鬆定位 IO 突高,前因後果一目瞭然 | 龍蜥技術

OpenAnolis小助手發表於2022-02-10
編者按 sysAK (system analyse kit),是龍蜥社群系統運維 SIG 下面的一個開源專案,聚集阿里百萬伺服器的多年運維經驗,針對不同的運維需求提供了一系列工具,形成統一的產品進行服務。本文總結了實際工作中 IO 打滿、IO util 高問題的處理經驗,將它梳理成一套理論分析方法並形成 iofsstat 工具,整合到了sysAK 工具集裡。以下將由作者帶大家一道領略 iofsstat 的獨特魅力。

文/ 李光水:系統運維SIG核心成員、 毛文安:系統運維SIG負責人。


一、 需求背景

經常碰到這樣一類問題:磁碟被打滿,然後 io utils 高,觸發業務監控告警,磁碟使用的是 HDD,出現問題的時候 iops 已經被打到幾百、bps 也已經到了上百 MB/s,然後持續個幾秒鐘結束,然後過個幾十秒又出現,這就造成了業務監控頻繁告警。業務方會苦惱,磁碟被打滿了到底是真實的業務需求量上來了呢?還是有什麼野程式在佔用 IO。比如之前碰到一例線上問題,平常都是正常的,突然某一天發現 IO 高了很多,然後客戶想知道是誰把 IO 整高了,後面通過系統的各個命令組合 +ftrace 指令碼統計,找到了貢獻最高的程式來自於一個與業務不相關的容器,他會定時啟動,謎一般的做大量的檔案拷貝動作。


二、現有工具

在定位問題這類問題的過程中,我們會通過系統的現有工具,定位具體的程式、檔案或者容器,然後採取下一步措施解決問題,如停掉程式、容器並檢視問題現象是否消失。一般地,如下幾類工具會使用比較頻繁:

  • 基於核心 diskstats 衍生的工具,如 iostat、sar-類命令的IO統計功能、vmstat-d

——可以巨集觀的從整個磁碟角度去統計 io 資訊,如統計整盤的 iops、bps

  • 基於核心 proc/$pid/io 衍生的工具,如 pidstat -d

——可以統計到程式貢獻的總體IO

  • 基於 Taskstats 衍生的工具,如 iotop

——可以統計到程式貢獻的總體 IO 以及貢獻的 iowait

儘管系統為我們提供了比較豐富的工具,但總有這樣一種感覺:使用已有的命令,儘管知道磁碟的 IO 高了,但不知道是哪個程式貢獻的;知道系統裡面的某個程式貢獻的 IO 高了,但又不確定這裡有多少 IO 是被我關心的磁碟給消費的,也不知道這些 IO 都是在操作什麼檔案,總覺得哪哪都差一點兒。所以總結下來,得到如下幾點訴求:

● 在磁碟 IO 被打滿的情況下,希望觀察是哪個程式貢獻了比較多的 IO

● 系統上統計到某個程式貢獻了大量的 IO,希望觀察到這些 IO 最終是被哪個磁碟給消費,或者這些 IO 是在訪問哪個檔案,如果這個程式是來自某個容器,希望依然可以獲取訪問的檔案以及此程式所在的容器

而本文所介紹的 iofsstat ,實現了從程式角度來統計 IO 資訊、檔案讀寫資訊,滿足了之前提到的幾個訴求,可以應用到 io utils 高、io 打滿類問題的定位中。


三、 iofsstat 功 介紹

3.1 統計指定磁碟的程式檔案 IO

主要統計某程式對某檔案貢獻了多少 IO,對使用者呈現的指標為程式角度+磁碟角度,磁碟角度這個毋庸置疑是為了能夠看到磁碟的全貌,程式角度,是更細粒度的,可以看到對應的在這個時刻,各程式的貢獻情況(PS:這裡並非程式貢獻的總和要等於磁碟整體的統計,因為統計的原理不一致,這裡可以更多的關注兩個角度之間的關聯性,如在某一時刻,磁碟統計到高了,這個時候可以看到對應的這個時刻的各個程式的貢獻程度),各指標如下:

程式角度:

comm:程式名、 pid:程式id、cnt_rd:讀檔案次數、bw_rd:讀檔案"頻寬"、cnt_wr:寫檔案次數、bw_wr :寫檔案"頻寬"、inode:檔案inode編號、filepath:檔案路徑,當在一次採集週期內由於程式訪問檔案很快結束情況下,獲取不到檔名則為"-"。

如程式來自某個容器,在檔名字尾會顯示 [containterId:xxxxxx]

磁碟角度:

xxx-stat:r_iops:磁碟總的讀 iops、 xxx-stat:w_iops:磁碟總的寫 iops、xxx-stat:r_bps:磁碟總的讀 bps、xxx-stat:w_bps:磁碟總的寫 bps、xxx-stat:wait:磁碟平均 io 延遲、xxx-stat:r_wait:磁碟平均讀 io 延遲、xxx-stat:w_wait:磁碟平均寫 io 延遲、xxx-stat:util%:磁碟 io utils

sysak iofsstat -d vdb1 --fs 1 #間隔1秒統計一次vdb磁碟上的程式讀寫檔案情況
2022/01/19 14:13:48
vda-stat:  r_iops     w_iops    r_bps    w_bps    wait   r_wait   w_wait  util%
           0.00       98.00     0.00    91.5MB/s  946.34 0.00     946.34  93.20
    
comm                pid     cnt_rd  bw_rd       cnt_wr  bw_wr       inode       filepath
dd                  55937   0       0           1096    137.0MB/s   9226        /home/data/tfatsf
...
顯示結果按照 bw_rd 與 bw_wr 的和做降序排列,如輸出結果較多想只看某程式情況下,可以使用 -p PID 只檢視指定程式
此功能基於 surftrace 開發, surftrace  是在 ftrace 基礎上封裝的一系列工具集,用於 trace 核心資訊,當前發行版主要包含 surftrace、surfGuide  兩大工具,後期還將包含 pylcc(python libbpf compile collections)。更多詳情可參考surftrace 專案程式碼連結。

3.1.1 程式、磁碟、檔案資訊

因為複雜的 IO 軟體棧,從使用者態到落盤,IO 經歷了不同的資料結構上的變化,同時經過 fs 和 block 之後,IO 的生產者也可能發生變化,因此在現有的條件下,無法做到不實現核心程式碼就可以直接獲取到這些資訊,我們所關注的資訊仍需要在核心中解析某些資料結構體外加推演來獲取,像獲取檔名、IO 大小、程式資訊等,比如我們通過在 block 層解析每個 io request 就可以獲取到相當飽滿的資訊:


通過這種方式,首先可以捕捉到所有類別的 IO,也肯定可以獲取 io 對應的檔案資訊,但是在 buffer io 情況下,需要在核心大動干戈的去輪詢所有的 task 的 files strcut 反推得到實際寫這個檔案的程式,而且一旦程式已經關閉了這個檔案,將會推導不出程式,因此不可取,另外應儘可能的避開核心 ko,避免後續使用上受限於核心版本問題;因此考慮 fs 層是否存在可用且穩定不會變化的 tracepoint。

實際上滿足功能的需求,只需要獲取程式資訊、IO 大小、dev 編號、檔案 inode 編號就夠了,而在檔案系統層沒有現成的符合這些需求的 tracepoint,因此考慮通過 kprobe_events 去 hook 特定函式;kprobe_events 又繞不開因為不同核心版本,資料結構會不一致,造成輸入到 kprobe_events 的表示式不一致的問題,幸運的是因為 surftrace 已經幫我們解決了這個問題,我們只需要關注 kprobe 之後資料的解析,而無需關注表示式的變化。

3.1.2 如何獲取檔案路徑

通過 3.1.1 已經獲取檔案 inode 編號,通過 find -inum 指定磁碟的掛載目錄,或者通過 debugfs 方式,獲取到檔名,但這種方式不僅耗時間也可能會耗 io;因為已經獲取到了程式資訊,接下來可以在 /proc/$pid/fd 過濾出來屬於指定磁碟下的檔案,然後比對檔案的 inode 即可獲取檔名,簡單高效,但缺點是當比對檔案過程中檔案訪問結束被 close 掉了,就獲取不到檔名了,但這種情況一般在有問題的情況下出現概率也很低(一般關注的 IO 打滿問題基本持續時間也都是秒級別)。

3.2 統計指定磁碟的程式IO貢獻

主要統計某程式對某磁碟貢獻了多少 IO,對使用者呈現的指標為程式角度+磁碟角度,磁碟角度這個毋庸置疑是為了能夠看到磁碟的全貌,程式角度,是更細粒度的,可以看到對應的在這個時刻,各程式的貢獻情況(PS:這裡並非程式貢獻的總和要等於磁碟整體的統計,因為統計的原理不一致,這裡可以更多的關注兩個角度之間的關聯性,如在某一時刻,磁碟統計到高了,這個時候可以看到對應的這個時刻的各個程式的貢獻程度),各指標如下:

程式角度:

comm:程式名、pid:程式 id、 iops_rd:程式貢獻的讀 iops、bps_rd :程式貢獻的讀bps、iops_wr:程式貢獻的寫iops、bps_wr :程式貢獻的寫bps。

磁碟角度:

同 3.1 節磁碟角度。

sysak iofsstat -d vdb 1 #間隔1秒統計一次vdb磁碟上的程式io貢獻情況
2022/01/19 12:04:38vda-stat:  r_iops     w_iops    r_bps    w_bps    wait   r_wait   w_wait  util%
           0.00       118.00    0.00   104.2MB/s  976.82 0.00     976.82  95.60
comm                    pid     iops_rd     bps_rd          iops_wr     bps_wr
[dd]                    98675   1           4.0KB/s         259         32.4MB/s
[kworker/u12:0]         91022   1           4.0KB/s         198         167.5MB/s
[jbd2/vdb1-8]           19510   0           0               1           4.0KB/s
...
顯示結果按照 iops_rd 與 iops_wr 的和做降序排列,如輸出結果較多想只看某程式情況下,可以使用 -p PID 只檢視指定程式,假設看到的是 kworker 類程式貢獻的 io 最高,可以進一步通過 3.1 節功能從 fs 角度來檢視是哪個程式、哪個檔案的 IO 最多。

3.2.1 實現原理

此功能基於 block 的 tracepoint,可獲取到指定磁碟的來自各程式的 IO 詳細資訊,然後統計每個程式的 iops、bps 貢獻。


四、效能開銷

iofsstat 本質上是基於 ftrace 的實現,不會引發當機,可以放心使用,由於使用的 ftrace 基本核心版本穩定,因此對核心版本依賴性也低,效能開銷方面,經過統計純 IO 統計功能(3.2 節)開銷單核 1% 以下,檔案 IO 統計功能(3.1節)稍微高一點,0.x%~3.x%,還在優化。


五、程式碼開源

iofsstat 程式碼將在 3 月中旬開源,敬請期待。

Gitee sysak 程式碼倉連結、surftrace 專案程式碼連結 、系統運維 SIG 地址可至龍蜥官方公眾號2022.2.9日相同推送檢視
—— 完 ——
加入龍蜥社群

加入微信群:新增社群助理-龍蜥社群小龍(微信:openanolis_assis),備註【龍蜥】與你同在;加入釘釘群:掃描下方釘釘群二維碼。歡迎開發者/使用者加入龍蜥社群(OpenAnolis)交流,共同推進龍蜥社群的發展,一起打造一個活躍的、健康的開源作業系統生態!

關於龍蜥社群

龍蜥社群OpenAnolis)是由 企事業單位、高等院校、科研單位、非營利性組織、個人等在自願、平等、開源、協作的基礎上組成的非盈利性開源社群。龍蜥社群成立於 2020 年 9 月,旨在構建一個開源、中立、開放的Linux 上游發行版社群及創新平臺。

龍蜥社群成立的短期目標是開發龍蜥作業系統( Anolis OS)作為 CentOS 停服後的應對方案,構建一個相容國際 Linux 主流廠商的社群發行版。中長期目標是探索打造一個面向未來的作業系統,建立統一的開源作業系統生態,孵化創新開源專案,繁榮開源生態。

目前, 龍蜥OS 8.4 已釋出,支援 X86_64 、Arm64、LoongArch 架構,完善適配飛騰、海光、兆芯、鯤鵬、龍芯等晶片,並提供全棧國密支援。

歡迎 加入我們,一起打造面向未來的開源作業系統!



來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70004278/viewspace-2855169/,如需轉載,請註明出處,否則將追究法律責任。

相關文章