天天看點

快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示

快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示

作者 | 四忌

來源 | 阿裡技術公衆号

一  背景

随着軟體應用的叢集化、容器化、微服務化,産品的穩定性越來越依賴網絡。現有的專有雲和一體機産品,部署在裸機,從硬體伺服器、交換機到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整體架構如下:

快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示

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  整體架構圖

快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示

四  部署和配置方法

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(延遲) 等資訊:

快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示
快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示
快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示

2  核心版本依賴(>=4.9)

Socket 資訊采集依賴 tcp_diag 核心子產品。

eBPF 還在快速發展期,核心中的功能也日趨增強,一般推薦基于Linux 4.4+ (4.9 以上會更好) 核心的來使用 eBPF。部分 Linux Event 和 BPF 版本支援見下圖:

快速界定故障:Socket Tracer網絡監控實踐一  背景二  目标三  實作原理四  部署和配置方法五  前台展示

阿裡雲官方鏡像站更新上線

阿裡雲官方鏡像站完成更新上線,免費提供Linux鏡像下載下傳服務,擁有Ubuntu、Deepin、MongoDB、Apache、Maven、Composer等多種開源軟體鏡像源,此外還提供域名解析DNS、網絡授時NTP等服務,緻力于為網際網路使用者提供全面,高效和穩定的基礎服務。

點選

這裡

,快去看看吧~

繼續閱讀