ACK KubeSkoop(原ACK Net Exporter)是阿里雲Container Service開源的網路監控和問題診斷套件,協助您監測和快速排查叢集中的網路疑難問題。本文介紹在ACK託管叢集中使用KubeSkoop的最佳實務,協助您快速上手並解決實際問題。
背景資訊
KubeSkoop提供了基於eBPF的深度網路監控、網路連通性診斷、抓包、延遲探測等一系列能力,對外提供Prometheus指標和例外狀況事件。KubeSkoop通過守護進程Pod的方式運行在節點上,藉助eBPF技術,採集節點的資訊並彙總到具體的Pod中,提供標準化的介面,實現對網路高階資訊的觀測。KubeSkoop的核心架構如下圖所示。
安裝與配置ACK KubeSkoop組件
安裝ACK KubeSkoop組件
登入Container Service管理主控台,在左側導覽列選擇叢集列表。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,單擊組件管理。
在組件管理頁面搜尋ACK KubeSkoop,找到對應組件並單擊安裝。
在安裝組件 ACK KubeSkoop頁面中單擊確認。
配置KubeSkoop組件
您可以執行如下命令,通過ConfigMap方式配置KubeSkoop組件。
kubectl edit cm kubeskoop-config -n ack-kubeskoop您也可以通過控制台配置KubeSkoop組件。
登入Container Service管理主控台,在左側導覽列單擊叢集列表。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
在配置項頁面,設定命名空間為ack-kubeskoop,然後搜尋kubeskoop-config,單擊kubeskoop-config右側操作列下的編輯。
在編輯面板配置參數,然後單擊確定。KubeSkoop支援的配置項及其含義如下:
參數
描述
預設值
debugmode
是否開啟偵錯模式。取值:
false:不開啟偵錯模式。
true:開啟偵錯模式。開啟後,支援DEBUG層級的日誌,調試介面,Go pprof和gops診斷工具。
falseport
指標服務的連接埠,提供HTTP服務。
9102enableController
是否啟用控制器組件。控制器負責與Kubernetes API互動,執行監控或管理工作。
truecontrollerAddr
控制器服務的地址,用於定位Kubeskoop控制器組件。
dns:kubeskoop-controller:10263metrics.probes
需要收集的監控指標類型列表,每個probe對應一個指標類別。
metrics: probes: - name: conntrack - name: qdisc - name: netdev - name: io - name: sock - name: tcpsummary - name: tcp - name: tcpext - name: udp - name: rdma可參見探針,指標和事件瞭解相應探針詳情。
在ConfigMap更新完成後,無需重啟ACK KubeSkoop組件,組件將會自動熱重載變更,開啟或關閉對應的探針。
配置ARMS Prometheus大盤
登入ARMS控制台。
在左側導覽列,單擊接入管理。
在接入管理介面中,單擊新增接入,在接入中心搜尋方塊中搜尋KubeSkoop,單擊ACK KubeSkoop網路監控。
在彈出的ACK KubeSkoop 網路監控頁面中,選擇待接入的Container Service叢集,填入接入名稱後,單擊確定開啟KubeSkoop監控。
登入Container Service管理主控台,在左側導覽列單擊叢集列表。
在叢集列表頁面,單擊目的地組群名稱,然後在左側導覽列,選擇。
單擊其他頁簽,在大盤列表中可以看到KubeSkoop建立的節點和Pod監控大盤。

關於阿里雲Prometheus監控的更多使用說明,請見接入與配置阿里雲Prometheus監控。
KubeSkoop使用說明
手動查看KubeSkoop的監控指標
KubeSkoop提供適配Prometheus格式的監控資料,在安裝完KubeSkoop後,您可以通過訪問任意一個KubeSkoop的Pod執行個體的服務連接埠擷取到全部的指標資訊:
可執行如下命令擷取到所有KubeSkoop執行個體。
kubectl get pod -n ack-kubeskoop -o wide | grep kubeskoop-agent預期輸出:
kubeskoop-agent-2chvw 1/1 Running 0 43m 172.16.16.xxx cn-hangzhou.172.16.16.xxx <none> <none> kubeskoop-agent-2qtbf 1/1 Running 0 43m 172.16.16.xxx cn-hangzhou.172.16.16.xxx <none> <none> kubeskoop-agent-72pgf 1/1 Running 0 43m 172.16.16.xxx cn-hangzhou.172.16.16.xxx <none> <none>執行如下命令,擷取指標資訊,需要將命令中的
172.16.xxx.xxx替換為上一步中擷取到的KubeSkoop執行個體的地址。curl http://172.16.16.xxx:9102/metrics
KubeSkoop提供的監控指標資料格式如下:
kubeskoop_netdev_rxbytes{k8s_namespace="",k8s_node="cn-hangzhou.172.16.16.xxx",k8s_pod=""} 2.970963745e+09如何使用ACK KubeSkoop定位容器網路中的偶發疑難問題
以下內容提供了針對部分雲原生典型問題的排查指南,結合ACK KubeSkoop,協助您快速擷取與問題有關的資訊。
DNS逾時相關問題
在雲原生環境中,DNS服務逾時問題會導致服務的訪問失敗,出現DNS訪問逾時的常見原因有:
DNS服務響應的速度較慢,無法在程式的逾時時間到達前完成一次DNS查詢。
由於發送端的問題,未能順利或者及時發送DNS Query報文。
服務端及時響應了報文,但是由於發送端本身的記憶體不足等問題出現了丟包。
您可以藉助以下幾個指標來協助排查偶發的DNS逾時問題:
指標名稱 | 說明 |
kubeskoop_pod_udpsndbuferrors | UDP協議通過網路層方法發送時出現報錯的次數。 |
kubeskoop_pod_udpincsumerrors | UDP接收報文時出現CSUM校正錯誤的次數。 |
kubeskoop_pod_udpnoports | 網路層調用 |
kubeskoop_pod_udpinerrors | UDP接收報文時出現錯誤的次數。 |
kubeskoop_pod_udpoutdatagrams | UDP協議通過網路層方法成功發送報文的數量。 |
kubeskoop_pod_udprcvbuferrors | UDP在將應用程式層協議資料拷貝到Socket接收隊列時由於隊列不足導致的報錯次數。 |
由於雲原生環境中很多服務依賴於CoreDNS提供網域名稱解析服務,在出現DNS問題時,如果出現問題的DNS請求與CoreDNS有關,您需要同時觀察CoreDNS相關Pod的上述指標的異常情況。
Nginx Ingress HTTP響應狀態代碼499/502/503/504相關問題
雲原生環境下,Ingress網關或者其他擔任Proxy/Broker作用的代理服務出現偶發的異常是較為常見的疑難問題,對於Nginx Ingress及以Nginx為底座的其他代理服務中,499/502/503/504問題是最為常見的四類,它們各自表徵的含義如下:
499:當請求Nginx的用戶端在Nginx沒有進行回複的時候就關閉了TCP串連,常見原因包括:用戶端串連建立之後,發送請求較晚,導致Nginx回複過程中就達到了Client Timeout,常見於Android用戶端的非同步請求架構中。
服務端在串連建立後,串連的處理較慢,需要深入排查。
服務端在向上遊Upstream的後端發起請求時,後端處理較慢。
502:情境多見於Nginx與Upstream後端之間串連層面的問題,例如串連建立失敗,或者後端異常的關閉,常見原因包括:後端配置的DNS網域名稱解析失敗,通常在使用Kubernetes Service作為後端時會出現。
與Upstream之間建立串連失敗。
Upstream的請求或者響應過大,無法分配到記憶體等幹擾正常業務互動的現象。
503:在Nginx中,用於提示用戶端所有的Upstream均出現了停用情況,在雲原生情境下,有一些特定的含義,常見原因包括:沒有可用的後端,這種情況通常出現較少。
流量過大,被Ingress的Limit Req所限制。
504:用於表徵Nginx與Upstream相關的業務報文出現逾時的問題,常見原因為Upstream返回的業務報文沒有及時到達。
在遇到上述幾類問題時,您需要先收集一些通用的資訊用於界定問題發生的可能範圍與下一步排查方向:
Nginx提供的access_log資訊,尤其是
request_time、upstream_connect_time與upstream_response_time。Nginx提供的error_log資訊,在問題發生時是否有異常的報錯資訊出現。
如果配置了Liveness或者Readiness健全狀態檢查,可查看健全狀態檢查。
在上述資訊的基礎上,當可能出現串連失敗時,您需要按照問題的具體現象關注以下指標的變化:
指標名稱 | 說明 |
kubeskoop_tcpext_listenoverflow | 當LISTEN狀態的Socket接受串連時出現半串連隊列溢出時會計數。 |
kubeskoop_tcpext_listendrops | 當LISTEN狀態的Sock建立SYN_RECV狀態的Sock失敗時會計數。 |
kubeskoop_netdev_txdropped | 網卡發送錯誤併產生丟棄的次數。 |
kubeskoop_netdev_rxdropped | 網卡接收錯誤併產生丟棄的次數。 |
kubeskoop_tcp_activeopens | 單個Pod內TCP成功發起SYN初次握手的次數,不包括SYN的重傳,但是串連建立失敗也會導致這個指標上升。 |
kubeskoop_tcp_passiveopens | 單個Pod內TCP完成握手並成功分配Sock的累積值,通常可以理解為成功建立串連的數量。 |
kubeskoop_tcp_retranssegs | 單個Pod內重傳的總報文數,這裡已經根據TSO進行了提前的分區計算。 |
kubeskoop_tcp_estabresets | 單個Pod內異常關閉TCP串連的次數,這裡僅從結果層面統計。 |
kubeskoop_tcp_outrsts | 單個Pod內TCP發送的Reset報文次數。 |
kubeskoop_conntrack_invalid | 在CT建立過程中由於各種原因無法建立,但是報文並未被丟棄的次數。 |
kubeskoop_conntrack_drop | 由於CT建立過程中無法建立而丟棄報文的次數。 |
針對出現了類似Nginx響應慢的情況時,例如雖然出現了逾時,但是Nginx的request_time很短的情況,您可以關注以下指標的變化:
指標名稱 | 說明 |
kubeskoop_tcpsummary_tcpestablishedconn | 當前存在的ESTABLISHED狀態的TCP串連數量。 |
kubeskoop_pod_tcpsummarytcptimewaitconn | 當前存在的TIME_WAIT狀態的TCP串連數量。 |
kubeskoop_tcpsummary_tcptimewaitconn | 當前處ESTABLISHED狀態的TCP串連的發送隊列中存在的資料包的Bytes總數。 |
kubeskoop_tcpsummary_tcprxqueue | 當前處ESTABLISHED狀態的TCP串連的接收隊列中存在的資料包的Bytes總數。 |
kubeskoop_tcpext_tcpretransfail | 重傳報文返回除了EBUSY之外的報錯時計數,說明重傳無法正常完成。 |
在上述指標資訊的基礎上,根據指標在對應問題時間點的變化,可以縮小排查的範圍。
TCP Reset報文相關問題
TCP Reset報文是TCP協議中用於對非預期情況做響應的動作,通常會對使用者程式造成以下的影響:
connection reset by peer報錯,通常出現在Nginx等C lib依賴的業務中。Broken pipe報錯,通常出現在Java或Python等封裝TCP串連的業務中。
雲原生網路環境中,出現Reset報文的常見原因有很多,以下列舉了幾種常見的Reset報文成因:
服務端的異常,導致無法正常提供服務,例如配置的TCP使用的記憶體不足等原因,這一類情況通常會主動發送Reset。
在使用Service或負載平衡時,由於Endpoint或者Conntrack等有狀態的機制出現異常而轉寄到了非預期的後端。
安全原因導致的串連釋放。
在NAT環境,高並發等情境下出現防止迴繞序號(Protection Against Wrapped Sequence Numbers,以下簡稱PAWS)或者序號迴繞現象。
使用TCP Keepalive進行串連保持,但在長時間沒有進行正常業務通訊的情況。
為了快速區分以上不同的根因,您可以收集一些基本的資訊指標:
梳理Reset報文產生時網路的用戶端和服務端之間的拓撲結構。
關注以下指標的變化:
指標名稱
說明
kubeskoop_tcpext_tcpabortontimeout
由於keepalive/window probe/重傳的調用超過上限發送Reset時會更新此計數。
kubeskoop_tcpext_tcpabortonlinger
TCP的Linger2選項開啟後,快速回收處於FIN_WAIT2的串連時發送Reset的次數。
kubeskoop_tcpext_tcpabortonclose
狀態機器之外的原因關閉TCP串連時,仍有資料沒有讀取而發送Reset報文,則會進行指標計數。
kubeskoop_tcpext_tcpabortonmemory
在需要分配tw_sock/tcp_sock等邏輯中,由於tcp_check_oom觸發記憶體不足而發送Reset結束串連的次數。
由於Linger/Linger2選項開啟而通過Reset進行串連的快速回收時發送Reset的計數。
kubeskoop_tcpext_tcpackskippedsynrecv
在SYN_RECV狀態的Socket不回複ACK的次數。
kubeskoop_tcpext_tcpackskippedpaws
由於PAWS機制觸發校正,但是OOW限速限制了ACK報文發送的次數。
kubeskoop_tcp_estabresets
單個Pod內異常關閉TCP串連的次數,這裡僅從結果層面統計。
kubeskoop_tcp_outrsts
單個Pod內TCP發送的Reset報文次數。
偶髮網絡延遲抖動相關問題
網路偶發延遲抖動類問題是雲原生環境中最為常見和最難定位的一類問題,成因的現象極多,同時出現延遲可能會導致上述的三種問題的產生。容器網路情境下,節點內部出現的網路延遲通常包含以下幾種原因:
出現某個RT調度器管理的即時進程執行時間過久,導致業務進程或網路核心線程出現排隊較長或者處理較慢的現象。
進程本身出現了偶發外部調用耗時久的現象,如雲端硬碟響應慢,RDS的RTT偶發增加等常見原因,導致請求處理較慢。
節點本身配置問題導致節點內不同CPU或不同NUMA Node之間負載不均,高負載的系統出現卡頓。
核心的有狀態機器制引發的延遲,如Conntrack的Confirm操作,大量Orphan Socket影響了正常的Socket尋找等。
面對此類問題,儘管表現為網路問題,其最終的原因通常是由於OS的其他原因導致,您可以關注以下指標來縮小排查的範圍:
指標名稱 | 說明 |
kubeskoop_io_ioreadsyscall | 進程進行檔案系統讀操作,如read,pread的次數。 |
kubeskoop_io_iowritesyscall | 進程進行檔案系統寫操作,如write,pwrite的次數。 |
kubeskoop_io_ioreadbytes | 進程從檔案系統,通常是塊裝置中讀取的Bytes數量。 |
kubeskoop_io_iowritebytes | 進程向檔案系統進行寫入的Bytes數量。 |
kubeskoop_tcpext_tcptimeouts | CA狀態並未進入recovery/loss/disorder時觸發,當SYN報文未得到回複時進行重傳會計數。 |
kubeskoop_tcpsummary_tcpestablishedconn | 當前存在的ESTABLISHED狀態的TCP串連數量。 |
kubeskoop_tcpsummary_tcptimewaitconn | 當前存在的TIME_WAIT狀態的TCP串連數量。 |
kubeskoop_tcpsummary_tcptxqueue | 當前處於ESTABLISHED狀態的TCP串連的發送隊列中存在的資料包的Bytes總數。 |
kubeskoop_tcpsummary_tcprxqueue | 當前處於ESTABLISHED狀態的TCP串連的接收隊列中存在的資料包的Bytes總數。 |
kubeskoop_softnet_processed | 單個Pod內所有CPU處理的從網卡放入CPU的Backlog的報文數量。 |
kubeskoop_softnet_dropped | 單個Pod內所有CPU丟棄的報文數量。 |
客戶案例分析
以下為部分容器網路客戶藉助ACK KubeSkoop進行疑難問題排查分析的案例,您可以比對現象進行參考。
案例一:偶發DNS Timeout問題
問題現象
客戶A發現異常,現象為有偶發的DNS解析逾時,使用者業務採用PHP,DNS服務為配置CoreDNS。
排查過程
根據客戶描述,與客戶溝通後擷取客戶監控中的DNS相關資料。
分析客戶報錯時間點內資料,發現以下問題。
報錯時間內
kubeskoop_udp_noports增加1,指標整體較小。kubeskoop_packetloss_total指標加1,丟包數變化較少。
客戶回函配置的DNS地址為公網某服務商地址,結合監控資訊,判斷客戶報錯根因為DNS請求返回較慢,使用者態逾時返回後,DNS回包到達。
案例二:Java應用偶發串連失敗問題
問題現象
客戶B發現異常,現象為出現偶發的Tomcat不可用,每次出現期間約為5~10s。
排查過程
經過日誌分析,確認現象發生時,客戶的Java Runtime進行中GC操作。
KubeSkoop監控部署後發現客戶在問題的時間點
kubeskoop_tcpext_listendrops指標有明顯的上升。經過分析後得出結論,客戶的Java Runtime進行GC操作時,處理請求的速度變慢,導致請求的釋放變慢,但是請求的建立並沒有被限制,因此產生了大量的連結,將Listen Socket的Backlog打滿後產生溢出,導致
kubeskoop_tcpext_listendrops上升。此問題中,客戶的串連堆積期間短,且本身處理能力沒有問題,因此建議客戶調整Tomcat相關參數後,解決了客戶問題。
案例三:某客戶偶髮網絡延遲抖動問題
問題現象
客戶C發現異常,現象為客戶應用與Redis之間的請求出現了偶發的RTT增高導致業務逾時,但是無法複現。
排查過程
經過日誌分析,客戶出現了偶發的Redis請求總回應時間超過300ms的情況。
部署KubeSkoop後,從監控中發現了kubeskoop_virtcmdlatency_latency指標在問題發生時有增長,增長的le(Prometheus監控中的Level)為18與15。經過換算得知此時出現過兩次延遲較高的虛擬化調用,其中le為15的產生了36ms以上的延遲,而le為18的產生了200ms以上的延遲。
由於核心的虛擬化調用執行時會佔據CPU,無法被搶佔,因此客戶的偶發延遲是由於Pod的批量增刪過程中有一些虛擬化調用執行過久導致。
案例四:Ingress Nginx偶發健全狀態檢查失敗問題
問題現象
Ingress機器有偶發的健全狀態檢查失敗並伴隨著業務請求失敗的問題。
排查過程
部署監控後發現出現的問題是多個指標有異常的變化。
kubeskoop_tcpsummary_tcprxqueue與kubeskoop_tcpsummary_tcptxqueue均出現了上升。kubeskoop_tcpext_tcptimeouts出現了上升。kubeskoop_tcpsummary_tcptimewaitconn下降,kubeskoop_tcpsummary_tcpestablishedconn上升。
經過分析後確認在問題發生的時間點,核心工作正常,串連建立正常,但進程的運行出現了異常,包括處理收取Socket中的報文以及實際執行報文的發送操作,推測此時使用者進程存在調度問題或者限制問題。
建議使用者查看Cgroup的監控後發現客戶在問題時間點出現了CPU Throttled現象,證明此時出現了偶發的使用者進程由於Cgroup原因無法得到調度的現象。
參見啟用CPU Burst效能最佳化策略,為Ingress配置CPU Burst功能後,解決了這一類問題。