作者 | 四忌
來源 | 阿裡技術公衆号
一 背景
随着軟體應用的叢集化、容器化、微服務化,産品的穩定性越來越依賴網絡。現有的專有雲和一體機産品,部署在裸機,從硬體伺服器、交換機到os都是不可靠的,且監控盲區較多,其中網絡是重災區。對于網絡不穩定導緻的中間件連結逾時、裝置掉線、視訊推流卡頓等問題,缺乏有效的網絡層監控名額定界問題。一旦現場不存在,由網絡引發的問題很難定位。現有的網絡監控方案,都集中在網卡次元做流量、錯包等名額統計,粒度過粗,隻有從Socket和TCP連接配接次元,監控socket緩存狀态,采集TCP建連、斷開、實時流量、延遲、重傳等資訊,才可以最直接的反映業務的網絡狀态。
二 目标
現有的網絡監控工具如 ss、netstat 等,可以顯示伺服器目前 Socket 狀态快照,在問題現場可以有效的輔助我們排查問題。當現場不存在,我們希望能有工具能儲存曆史網絡狀态。然而單純記錄曆史 Socket 五元組資訊,在複雜拓撲場景是不夠的,因為IP很可能是動态的,還須将目前時刻的 Socket 連接配接和業務屬性(Pod Name、裝置身份...)關聯,才能達到還原問題現場,快速界定故障域的目的。
1 典型場景
- 叢集中間件通路逾時問題定界。
- 資料采集丢包問題定界:例如裝置側聲稱發包,但網關沒有收到,現場不在了,互相扯皮。
- 裝置連雲鍊路檢測。
- 視訊直播卡頓問題定界。
- ...
2 能力綜述
Socket次元資訊采集
- 流量(tx/rx)、延遲(srtt),待重傳包數量、總重傳次數、收發隊列長度,Accept隊列長度。
- TCP 生命周期監控:監聽TCP Close事件,統計連接配接時長,收發包總位元組數。
- TCP Reset異常監控:收到或者發送Reset的異常,及異常時刻的TCP State。
雲原生監控方案适配
- 現有的netstat、ss等網絡資訊統計工具,無法做到跨network namespce的socket資訊統計。在雲原生環境使用不便。需要做到監控k8s叢集所有節點,及節點上所有Pod的Socket狀态。
- 采集資料名額化,支援對接 Prometheus 的 Exporter 接口。
- 支援名額推送到 VictoriaMetrics。
名額選取原理
TCP的名額有很多,為什麼采集上述的名額資訊,出發點是希望找到可以反映應用程式狀态和網絡連通狀态名額,如果有其它名額采集建議也歡迎留言。下面展開分析下上述名額的采集原因:
1)TCP Retransmit
包重傳的逾時時間是RTO,通常是200ms左右,當我們觀察到一段時間出現了TCP包重傳,後續又恢複正常了,可以判斷這個時間段出現了網絡抖動, 就可以找網絡的同學來幫忙排查問題了。
2)TCP SRTTRTT
(round-trip time)為資料完全發送完(完成最後一個比特推送到資料鍊路上)到收到确認信号的時間。
SRTT(smoothed round trip time)是平滑過的RTT。
通過srtt曆史曲線圖或柱狀圖,觀察出來延遲的區間變化,就可以知道網絡連接配接的srtt是否抖動。如果業務延遲發生了抖動,srtt很穩定,就可以說明大機率不是網絡的問題,可能是業務的問題,或者排程的問題等等; 反之,如果srtt也發生了抖動,那麼可以先檢查一下網絡連接配接。
3)TCP Tx/Rx
監控連結的流量,結合對現場業務的了解,在業務出現丢失資料場景,可以輔助定位時網絡問題還是應用問題:
- 傳輸層收到資料,但堆積在rcv_queue中,可能是應用層處理代碼阻塞。
- 傳輸層Rx沒有增加,則很可能是對端沒有發送資料。
4)TCP reset reasons
Reset 包是導緻TCP異常斷開的常見原因之一,下面對可能觸發 reset 事件的原因做一個彙總(如有錯漏歡迎補充):
- Non-Existence TCP endpoint: Port or IP(Restrict Local IP address):服務端不存在。(SYN -> Server reset)
- TCP SYN matches existing sessions:服務端、或者防火牆已存在相同5元組連接配接。(SYN -> Server reset)
- Listening endPoint Queue Full :應用層沒有及時accept,導緻服務端Accept隊列滿(全連結隊列滿),分兩種情況:對于新來握手請求 SYN -> SYN包會被Server默默丢棄,不會觸發reset;碰巧在Client 回 ACK(握手第三個包)時,accept 隊列滿了,Server 會根據 tcp_abort_on_overflow sysctl 配置,決定是否發送 reset。
- Half-Open Connections:服務端程式重新開機,導緻連結資訊丢失。(中間資料-> Server reset)
- RESET by Firewalls in transit:在防火牆維護session狀态的場景(NAT網關),防火牆Session TTL過期。(中間資料-> FW reset)
- Time-Wait Assassination:Client Time-Wait 期間,收到 Server 端遲到的資料包,回送Ack給Server,導緻Server發送Rst包。(Server 遲到資料 -> Client Ack-> Server Reset)
- Aborting Connection:用戶端Abort,核心發送reset給服務端。(Client Reset)
三 實作原理
Socket Tracer 使用 eBPF+Tracepoint 捕捉 TCP 的 reset&new&close 等事件,使用 netlink + tcp_diag 周期抓取核心 Socket 資訊快照。
1 eBPF
背後的思想是:“與其把資料包複制到使用者空間執行使用者态程式過濾,不如把過濾程式灌進核心去”。
eBPF 是一個在核心中運作的虛拟機,它可以去運作使用者。在使用者态實作的這種 eBPF 的代碼,在核心以本地代碼的形式和速度去執行,它可以跟核心的 Trace 系統相結合,給我們提供了幾乎無限的可觀測性。
eBPF 的基本原理:它所有的接口都是通過 BPF 系統調用來跟核心進行互動,eBPF 程式通過 LVM 和 Cline 進行編譯,産生 eBPF 的位元組碼,通過 BPF 系統調用,加載到核心,驗證代碼的安全性,進而通過 JIT 實時的轉化成 Native 的 X86 的指令。eBPF整體架構如下:
2 kprobe
當安裝一個kprobes探測點時,kprobe首先備份被探測的指令,然後使用斷點指令(即在i386和x86_64的int3指令)來取代被探測指令的頭一個或幾個位元組。
當CPU執行到探測點時,将因運作斷點指令而執行trap操作,那将導緻儲存CPU的寄存器,調用相應的trap處理函數,而trap處理函數将調用相應的notifier_call_chain(核心中一種異步工作機制)中注冊的所有notifier函數,kprobe正是通過向trap對應的notifier_call_chain注冊關聯到探測點的處理函數來實作探測處理的。
當kprobe注冊的notifier被執行時,它首先執行關聯到探測點的pre_handler函數,并把相應的kprobe struct和儲存的寄存器作為該函數的參數,接着,kprobe單步執行被探測指令的備份,最後,kprobe執行post_handler。等所有這些運作完畢後,緊跟在被探測指令後的指令流将被正常執行。
3 tracepoint
tracepoint和kprobe相比,tracepoint是一個靜态的hook函數,是預先在核心裡面編寫好才使用。tracepoint實作是基于hooks的思想,在函數的入口就被放置一個probe點,這個probe點就會跟蹤調用這個函數的各種資訊,并将追蹤的資訊儲存到一個環形隊列中去,如果使用者希望讀取這些核心,就會通過debugfs形式來通路。
4 方案選型
eBPF 調用方案
對比調用eBPF能力的三種方案,bpftrace / bcc / libbpf,最終選擇bcc:
- bpftrace提供了腳本語言,友善輸出核心資訊到控制台,做CLI工具很友善。但沒有提供API接口,不友善背景代碼調用和資訊讀取。
- libbpf會直接把核心bpf代碼編譯成bin檔案,再放到目标機運作。目标是一次編譯,四處運作,為了解決跨核心版本(配置)的可移植問題,需依賴BTF kernel選項,目前絕大部分核心預設沒有打開該功能,需要修改配置重新編譯kernel才行。
- bcc在目标機環境運作階段,動态編譯bpf核心代碼,來解決可移植性問題。是現階段使用最廣的方案,絕大部分bpf監控工具都基于bcc-tools;并且提供API接口,便于代碼內建,其中核心代碼基于C語言,應用層代碼提供python和go兩種語言API。
Socket 資訊采集方案
eBPF+kprobe在目标函數上動态挂載hook函數,在高頻調用(收發包函數)的場景額外開銷較大,是以在周期統計socket連結收發資料量、重傳次數等場景,我們參考 ss 的實作,基于 linux netlink + tcp_diag 核心子產品,該方案适合應用主動抓取某個時間點socket 統計資訊快照,可以減少額外性能開銷。
5 整體架構圖
四 部署和配置方法
1 指令行參數定義
包含Socket采集過濾配置檔案路徑,socket資訊采集周期,vm-insert的URL位址。
bash-5.0# ./socktracer --help
Usage of ./socktracer:
-configfile string
Socket tracer target config file (default "/etc/filter.yaml")
-metricsCacheNum int
Metrics local cached number (default 10000)
-namespace string
Namespace for metrics
-sockScanInterval int
Socket statistical information scan interval (default 30)
-version
Show version information and exit
-vmaddr string
URL of Victoria Metrics write address
-web.listen-address string
Address to listen on for web interface and telemetry. (default ":8080")
-web.metrics-path string
Path under which to expose metrics. (default "/metrics")
2 Socket采集過濾配置檔案格式
一台伺服器上的Socket連接配接數量非常多,資料量和比較大,我們往往隻關心部分服務的相關連接配接,就像tcpdump我們也往往會對IP和端口做過濾一樣。過濾配置檔案使用yaml格式,定義如下:
filter.yaml配置檔案定義,用于配置過濾需跟蹤的 Socket 連結:type SocketID struct {
Protocol string `yaml:"protocol"` // Only support TCPv4 currently, will support UDP and IPv6 when needed.
LocalIP string `yaml:"localIP"` // Specify local IP, will overwrite LocalPod when both set
LocalPod string `yaml:"localPod"` // Specify prefix of local podName, will be overwritten by LocalIP when both set
LocalPort int `yaml:"localPort"` // Specify local Port, set to 0 means do not filter local port
PeerIP string `yaml:"peerIP"` // Specify peer IP, will overwrite PeerPod when both set
PeerPort int `yaml:"peerPort"` // Specify peer Port, set to 0 means do not filter peer port
PeerPod string `yaml:"peerPod"` // Specify prefix of peer podName, will be overwritten by PeerIP when both set
}
樣例:bash-5.0# cat /etc/filter.yaml
filters:
- localIP: "" //采集目标1:不指定本地IP,可以不配置或者設定為空
localPort: 6379 //指定本地端口,通常選擇固定的server端口作為過濾條件
localPod: "default/redis-" //指定本地PodName字首,格式為: namespace/podName字首
- localPod: "default/iotx-event-center" // 采集目标2:指定本地PodName字首。peerPod: "default/redis-" //指定對端PodName字首,格式為: namespace/podName字首
peerPort: 6379 //指定對端端口
五 前台展示
1 Grafana Dashboard
下圖中,連接配接到 redis server 的所有TCP連接配接(來自不同的Client+Port)都會被監控,展示總并發連接配接數和連接配接的 rtt(延遲) 等資訊:
2 核心版本依賴(>=4.9)
Socket 資訊采集依賴 tcp_diag 核心子產品。
eBPF 還在快速發展期,核心中的功能也日趨增強,一般推薦基于Linux 4.4+ (4.9 以上會更好) 核心的來使用 eBPF。部分 Linux Event 和 BPF 版本支援見下圖:
阿裡雲官方鏡像站更新上線
阿裡雲官方鏡像站完成更新上線,免費提供Linux鏡像下載下傳服務,擁有Ubuntu、Deepin、MongoDB、Apache、Maven、Composer等多種開源軟體鏡像源,此外還提供域名解析DNS、網絡授時NTP等服務,緻力于為網際網路使用者提供全面,高效和穩定的基礎服務。
點選
這裡,快去看看吧~