干货丨Kubernetes 中分析调试网络流量的4种方法
本文章轉自@twt社區
【摘要】Kubernetes 中的應用出了問題, 往往需要進行網絡抓包分析. 本文介紹了在Kubernetes 中網絡調試分析的4種方法。
【作者】崔凱東
前言
在當今世界,分布式系統,微服務/SOA架構遍地,服務之間的許多交互和通信都不再是同一主機的不同線程或進程,而是跨主機,甚至跨網絡區域。那么一旦相關服務出現問題,我們就會需要調試服務間的通訊、主機間的網絡……
 
Kubernetes 中的應用出了問題,往往需要進行網絡抓包分析。本文介紹了在 Kubernetes 中網絡調試分析的4種方法。
1、使用 sidecar
2、使用 netshoot - 一個 Docker + Kubernetes網絡故障排除的瑞士軍刀容器
3、利用Network Namespace
4、使用 kubectl 插件 - ksniff
方法一:使用 Sidecar
Sidecar應用范圍不僅僅止于此,比如:APM監控的agent就可以通過這種方式來掛載。
Sidecar 前來救援!
在過去的幾個月里,我嘗試了各種方法來克服這個問題,最終形成了我將在本文中概述的方法。它是捕獲Kubernetes/OpenShift pods之間的網絡流量數據的簡單方法,允許開發人員更好地分析和調試容器化應用程序中的通信問題,并更快、更有效地解決問題。
我們將使用tcpdump捕獲一個所謂的PCAP(packet capture)文件,該文件將包含pod的網絡流量。然后可以將這個PCAP文件加載到Wireshark之類的工具中來分析流量,在本例中,分析在pod中運行的服務的RESTful通信。在本文中,我將使用Red Hat Process Automation Manager產品的KIE服務器(執行服務器)作為示例,但是這種方法應該適用于任何類型的容器化應用程序。
要克服的第一個問題是Kubernetes pod中tcpdump命令的可用性。KIE服務器容器映像沒有安裝tcpdump。其次,容器不提供從Red Hat存儲庫安裝tcpdump的實用程序。為了克服這個問題,我們使用了“sidecar容器”的概念。
Sidecar 概念
sidecar容器是與實際服務/應用程序運行在相同pod中的容器,能夠為服務/應用程序提供附加功能。sidecar容器的一個例子是Istio的Envoy sidecar,它使pod成為服務網格的一部分。在本例中,我們將部署一個sidecar容器,該容器提供tcpdump實用程序。由于pod中的多個容器共享相同的網絡層,所以我們可以使用sidecar來捕獲進出KIE服務器的網絡流量。
部署 Sidecar
在這個例子中,我部署了 Red Hat Process Automation Manager 7 Mortgage Demo ,它將在我的OpenShift namespace中創建兩個pod。一個pod運行Business Central workbench,另一個pod是執行服務器的pod。這兩個組件之間的通信是通過REST完成的,這是我們將要捕獲的流量。
 
我們的目標是捕獲KIE服務器pod上的網絡流量,以便分析Business Central workbench 發送給KIE服務器的RESTful命令。要做到這一點,我們首先需要附加(attach)一個 sidecar 到KIE服務器的pod.
1、在Overview頁面中,單擊要分析的pod的名稱。這將打開_部署配置(Deployment Config, 簡稱DC)_頁面。
2、在_部署配置_屏幕的右上角,單擊Actions -> Edit YAML。這將打開DC 的YAML配置。
 
3、向下滾動,直到看到單詞 containers 。我們將添加一個額外的容器,安裝了tcpdump的sidecar到pod中。直接在 containers 定義下添加以下YAML片段:
 
 
4、保存配置。這將部署一個新的pod,它現在由兩個容器組成:一個容器包含KIE服務器,另一個容器包含我們的tcpdump工具,它將無限期地持續運行。
捕獲和分析流量
隨著sidecar的部署和運行,我們現在可以開始捕獲數據了。我嘗試的方法之一是使用oc rsh命令遠程執行sidecar中的tcpdump命令,將網絡數據流輸出到FIFO文件,并將數據直接導入Wireshark。由于各種原因,這種方法失敗了。其中一個問題是,tcpdump向stderr發送信息消息,但是這些消息與stdout在相同的流中, 并且是通過SSH接收,從而破壞了進入Wireshark的數據。
我最后使用的方法是登錄到sidecar容器,并在sidecar中運行tcpdump命令來創建PCAP文件。當您捕獲了足夠的數據后,就可以停止捕獲過程并將PCAP文件復制到您希望使用Wireshark進行網絡流量分析的機器上。具體步驟如下:
1、在您的開發機器上,用oc 客戶端連接到OpenShift實例,并激活正確的項目(project, 即namespace),運行oc get pods命令來列出您的pods:
 
2、使用以下命令登錄到我們的KIE服務器pod的tcpdump容器中:oc rsh -c tcpdump rhpam7-mortgage-kieserver-2-zcpsn
3、在tcpdump容器中,運行此命令以啟動網絡流量捕獲過程: tcpdump -s 0 -n -w /tmp/kieserver.pcap
4、運行要分析的網絡流量的測試。在本例中,我將從Business Central workbench中啟動一個業務流程,它將向KIE服務器發送一個RESTful請求。
5、捕獲足夠的數據后,在tcpdump容器中使用Ctrl+C完成捕獲過程。
6、回到本地機器。將PCAP文件從pod復制到本地機器: oc cp -c tcpdump rhpam7-mortgage-kieserver-2-zcpsn:tmp/kieserver.pcap kieserver.pcap
7、用Wireshark打開PCAP文件并分析網絡流量。在這個例子中,我正在分析我的HTTP POST方法,它創建了Mortgage 進程的一個新實例:
 
總結
在容器環境(如Kubernetes和/或OpenShift)中分析pod之間的網絡通信可能比在非容器環境中更困難一些。然而,sidecar容器的概念為開發人員提供了一種簡單的工具,可以將容器連同所需的開發工具和實用程序附加到微服務pod上。 這避免了開發人員必須在應用程序容器映像本身中安裝這些調試工具,從而保持容器的輕便和干凈。 使用像 oc rsh 和 oc cp 這樣的OpenShift工具,我展示了如何輕松地從pod捕獲網絡流量數據并將數據帶到開發機器進行分析。
方法二:使用 netshoot
Netshoot - Docker + Kubernetes網絡故障排除的瑞士軍刀容器
 
用途
Docker和Kubernetes網絡故障排除變得復雜。通過正確理解Docker和Kubernetes網絡的工作方式和正確的工具集,您可以排除故障并解決這些網絡問題。netshoot容器有一組強大的網絡troubleshoot工具,可以用來排除Docker網絡問題。與這些工具一起出現的還有一組用例,展示了如何在真實場景中使用這個容器。
Network Namespaces - 網絡名稱空間
在開始使用這個工具之前,有一點很重要:網絡名稱空間。網絡名稱空間提供與網絡相關的系統資源的隔離。Docker使用網絡和其他類型的名稱空間(pid、mount、user…)為每個容器創建一個隔離的環境。從接口、路由到ip的所有內容都完全隔離在容器的網絡名稱空間中。
Kubernetes也使用網絡名稱空間。Kubelets為每個pod創建一個網絡名稱空間,其中該pod中的所有容器共享相同的網絡名稱空間(eths、IP、tcp套接字……)。這是Docker容器和Kubernetes pod之間的關鍵區別。
名稱空間很酷的一點是您可以在它們之間進行切換。您可以輸入不同容器的網絡名稱空間,使用甚至沒有安裝在該容器上的工具在其網絡堆棧上執行一些故障排除。此外,netshoot可以通過使用主機的網絡名稱空間來對主機本身進行故障排除。這允許您在不直接在主機或應用程序包上安裝任何新包的情況下執行任何故障排除。
針對容器的用法
- 容器的網絡名稱空間:如果您的應用程序的容器存在網絡問題,您可以像這樣使用容器的網絡名稱空間啟動netshoot: $ docker run
 -it --net container: nicolaka/netshoot
- 主機的網絡名稱空間:如果您認為網絡問題在于主機本身,那么可以使用該主機的網絡名稱空間啟動netshoot。命令: $ docker run
 -it --net host nicolaka/netshoot
- 網絡的網絡名稱空間:如果要對Docker網絡進行故障排除,可以使用nsenter輸入網絡的名稱空間。這將在下面的nsenter部分進行解釋。
針對 Kubernetes 的用法
 
網絡問題
許多網絡問題可能導致應用程序性能下降。其中一些問題可能與底層網絡基礎設施有關。其他問題可能與主機或Docker級別的配置錯誤有關。讓我們來看看常見的網絡問題:
- 延遲(latency)
- 路由(routing)
- DNS解析(DNS resolution)
- 防火墻(firewall)
- 不完整的ARP(incomplete ARPs)
為了解決這些問題,netshoot包含了一組強大的工具,如圖所示。
 
被包含的包
 
方法三:利用Network Namespace
正如方法二中提到的Network Namespace概念,實際上,不同的容器,只是在宿主機上不同 namespace 運行的進程而已。因此要在不同的容器抓包可以簡單地使用命令切換 network namespace 即可,可以使用在宿主機上的 tcpdump 等應用進行抓包。
 
具體操作步驟如下:
1、查看指定 pod 運行在哪個宿主機上: kubctl describe pod -n mservice
2、獲得容器的 pid: docker inspect -f {{.State.Pid}}
3、進入該容器的 network namespace: nsenter --target -n
4、使用宿主機的tcpdump 抓包, 指定 eth0 網卡: tcpdump -i eth0 tcp and port 80 -vvv
5、或者直接抓包并導出到文件: tcpdump -i eth0 -w /tmp/out.cap
6、從遠程 scp 到本地: scp ipaddr:/tmp/out.cap ./
7、之后在 Wireshark 中可以打開文件非常直觀得查看過濾抓到的數據。
方法四:使用 kubectl 插件ksniff
題外話:krew - kubectl 插件包管理器
Krew是kubectl插件的包管理器。(后續會使用krew來安裝 ksniff , 方便很多)
什么是 krew?
krew是一個使kubectl插件易于使用的工具。krew可以幫助發現插件,并在機器上安裝和管理它們。類似于apt、dnf或brew等工具。
krew 易于使用:
 
查看在krew上可用的kubectl插件列表,或者運行kubectl krew search來發現可用的插件。
安裝 krew
Bash 和 ZSH:
1、確保git 已安裝;
2、運行如下命令, 下載并安裝krew
 
3、添加 HOME/.krew/bin目錄到PATH環境變。如下:exportPATH="HOME/.krew/bin 目錄到 PATH 環境變。如下: export PATH="HOME/.krew/bin目錄到PATH環境變。如下:exportPATH="{KREW_ROOT:-KaTeX parse error: Expected 'EOF', got '}' at position 11: HOME/.krew}?/bin:PATH" 并重啟下shell生效。
安裝ksniff
通過 krew : kubectl krew install sniff
使用方法
kubectl < 1.12: kubectl plugin sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]kubectl >= 1.12: kubectl sniff <POD_NAME> [-n <NAMESPACE_NAME>] [-c <CONTAINER_NAME>] [-i <INTERFACE_NAME>] [-f <CAPTURE_FILTER>] [-o OUTPUT_FILE] [-l LOCAL_TCPDUMP_FILE] [-r REMOTE_TCPDUMP_FILE]POD_NAME: Required. the name of the kubernetes pod to start capture it's traffic. NAMESPACE_NAME: Optional. Namespace name. used to specify the target namespace to operate on. CONTAINER_NAME: Optional. If omitted, the first container in the pod will be chosen. INTERFACE_NAME: Optional. Pod Interface to capture from. If omited, all Pod interfaces will be captured. CAPTURE_FILTER: Optional. specify a specific tcpdump capture filter. If omitted no filter will be used. OUTPUT_FILE: Optional. if specified, ksniff will redirect tcpdump output to local file instead of wireshark. LOCAL_TCPDUMP_FILE: Optional. if specified, ksniff will use this path as the local path of the static tcpdump binary. REMOTE_TCPDUMP_FILE: Optional. if specified, ksniff will use the specified path as the remote path to upload static tcpdump to.舉例:
 kubectl sniff mypod -n myproject -o /tmp/mypod.pcap
總結
為了在容器或K8S中進行網絡調試和分析,本文列舉了4種方法,現在進行總結歸納:
1、使用 sidecar - sidecar 容器所在的pod中的多個容器共享相同的網絡層,且sidecar容器可以包含tcpdump等工具;
2、利用Network Namespace - 不同的容器,**只是在宿主機上不同 namespace 運行的進程而已。**容器的網絡也是如此。
3、使用netshoot - netshoot 其實是包含一系列的常用網絡分析調試工具集的容器,真正的使用方法其實還是以上2種:
1)通過 sidecar掛載
2)利用Network Namespace分析調試
4、使用 kubectl 插件 - ksniff,個人猜想,這個只是一個通過 kubectl 插件的封裝,底層原理應該還是 Network Namespace.
以上這些方法,有不同的前提條件和使用場景,希望本文讀完會讓你的K8S調試技能有所提升。
總結
以上是生活随笔為你收集整理的干货丨Kubernetes 中分析调试网络流量的4种方法的全部內容,希望文章能夠幫你解決所遇到的問題。
 
                            
                        - 上一篇: Altium designer--LM3
- 下一篇: H.264的profile与level概
