如何使用 K8spacket 和 Grafana 對 K8s 的 TCP 數據包流量進行可視化
前言
如何知道 K8S 集群內 Pod 之間建立了哪些 TCP 連接?集群之間存在哪些調用關系?
使用 k8spacket 和Grafana,你可以可視化集群中的 TCP 流量。了解工作負載如何相互通信,以及建立了多少連接,交換了多少字節,這些連接處于活動狀態的時間。
介紹
k8spacket是用 Golang 編寫的工具,它使用gopacket第三方庫來嗅探工作負載(傳入和傳出)上的 TCP 數據包。它在運行的容器網絡接口上創建 TCP 偵聽器。當 Kubernetes 創建一個新容器時,CNI 插件負責提供與其他容器進行通信的可能性。最常見的方法是用linux namespace隔離網絡并用veth pair連接隔離的 namespace 與網橋。除了bridge 類型,CNI 插件還可以使用其他類型(vlan, ipvlan,macvlan),但都為容器創建了一個網絡接口,它是k8spacket嗅探器的主要句柄。
k8spacket有助于了解 Kubernetes 集群中的 TCP 數據包流量:
- 顯示集群中工作負載之間的流量
- 通知流量在集群外路由到哪里
- 顯示有關連接關閉套接字的信息
- 顯示工作負載發送/接收的字節數
- 計算建立連接的時間
- 顯示整個集群中工作負載之間的網絡連接拓撲
k8spacket是一個 Kubernetes API 客戶端,可以將嗅探到的工作負載解析為可視化上可見的集群資源名稱(Pods和Services)。它作為DaemonSet Pod啟動,使用 hostNetwork,并監聽節點上的網絡接口。
k8spacket 收集 TCP 流、處理數據,使用 Node Graph API Grafana 數據源插件(詳情請查看 Node Graph API 插件),通過 API 展示在Grafana面板。
要安裝k8spacket,需要同時安裝 Grafana。下面將在Kind安裝的 k8s 集群上做演示。
安裝 k8spacket
使用 Helm 安裝:
helm repo add k8spacket https://k8spacket.github.io/k8spacket-helm-chart
helm install k8spacket --namespace k8spacket k8spacket/k8spacket --create-namespace
默認安裝會使用下面的命令獲取所有需要監聽的網絡接口:
ip address | grep @ | sed -E 's/.* (\w+)@.*/\1/' | tr '\n' ',' | sed 's/.$//'
其中可能包含一些狀態為Down的接口,此時啟動k8spacket會報錯:
2022/08/15 00:17:34 error opening pcap handle: tunl0: That device is not up
報錯中提示網絡接口tunl0狀態不是up。
所以需要自定義修改values.yaml中的參數。將charts包拉取到本地,解壓之后再修改:
mkdir k8spacket
helm fecth k8spacket/k8spacket
tar -zxf k8spacket-0.1.0.tgz
cd k8spacket
修改 values.yaml 中的內容,過濾掉tunl0:
k8sPacket:
tcp:
listener:
interfaces:
## 實現容器網絡接口的命令
command: "ip address | grep @ | grep -v tunl0 | sed -E 's/.* (\\w+)@.*/\\1/' | tr '\\n' ',' | sed 's/.$//'"
## 多久刷新一次要監聽的網絡接口列表
refreshPeriod: "10s"
## 每 (periodDuration) 秒,刷新在過去 (closeOlderThanDuration) 秒內沒有看到活動的連接。
flushing:
periodDuration: "10s"
closeOlderThanDuration: "20s"
- refreshPeriod參數表示多久刷新一次要監聽的網絡接口列表,增加新的網絡接口監聽,移除舊網絡接口監聽。
- 每 periodDuration秒,刷新在過去 closeOlderThanDuration秒內沒有看到活動的連接。
安裝成功,包含以下Daemonset Pods 和 Service:
# k get pod -n k8spacket -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
k8spacket-9m4cz 1/1 Running 0 10m 192.168.16.4 k8s118-control-plane <none> <none>
k8spacket-b4q9k 1/1 Running 0 10m 192.168.16.6 k8s118-control-plane3 <none> <none>
k8spacket-b5nnp 1/1 Running 0 10m 192.168.16.7 k8s118-control-plane2 <none> <none>
k8spacket-c25jh 1/1 Running 0 10m 192.168.16.2 k8s118-worker <none> <none>
k8spacket-cqqxh 1/1 Running 0 10m 192.168.16.5 k8s118-worker2 <none> <none>
k8spacket-h9hjc 1/1 Running 0 10m 192.168.16.3 k8s118-worker3 <none> <none>
# k get svc -n k8spacket -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
k8spacket ClusterIP 11.0.227.158 <none> 8080/TCP 31m app.kubernetes.io/instance=k8spacket,app.kubernetes.io/name=k8spacket
k8spacket Pod 提供了 /metrics 接口暴露指標:
curl 192.168.16.4:8080/metrics
安裝 dashboards
下載k8spacket項目,并將dashboards目錄下的面板 configmaps 創建到 K8S 中:
wget https://github.com/k8spacket/k8spacket/archive/refs/heads/master.zip
unzip master.zip
cd k8spacket-master
kubectl apply --recursive -f ./dashboards
創建了 k8spacket-logs-dashboard、k8spacket-metrics-dashboard、k8spacket-node-graph-dashboard三個面板。
其中的metrics面板公開了 Prometheus 指標,這里不做演示。只關心node-graph面板。
安裝 grafana
使用 Helm 安裝 grafana,helm-charts 包地址如下:
- https://github.com/grafana/helm-charts
同樣的拉取到本地:
helm repo add grafana https://grafana.github.io/helm-charts
helm fetch grafana/grafana
tar -zxf grafana-6.32.13.tgz
cd grafana/
- charts包版本為:6.32.13
- grafana版本為:9.0.5
修改values.yaml,將 Node Graph API 插件和數據源,以及 node-graph dashboard configmaps 添加到 Grafana。同時開啟數據持久化。例如:
persistence
type pvc
enabledtrue
env
GF_INSTALL_PLUGINS hamedkarbasi93-nodegraphapi-datasource
dashboardProviders
dashboardproviders.yaml
apiVersion1
providers
name'default'
orgId1
folder''
type file
disableDeletionfalse
editabletrue
options
path /var/lib/grafana/dashboards/default
dashboardsConfigMaps
default k8spacket-node-graph-dashboard
datasources
nodegraphapi-plugin-datasource.yaml
apiVersion1
datasources
name"Node Graph API"
jsonData
url"http://k8spacket.k8spacket.svc.cluster.local:8080"
access"proxy"
basicAuthfalse
isDefaultfalse
readOnlyfalse
type"hamedkarbasi93-nodegraphapi-datasource"
typeLogoUrl"public/plugins/hamedkarbasi93-nodegraphapi-datasource/img/logo.svg"
typeName"node-graph-plugin"
orgId1
version1
在values.yaml目錄下執行創建命令:
helm install grafana -f values.yaml ./
獲取到admin賬號的密碼:
kubectl get secret --namespace default grafana -o jsonpath="{.data.admin-password}" | base64 --decode ; echo
開啟臨時端口轉發,使得集群外可以訪問grafana實例:
kubectl --namespace default port-forward service/grafana 3000:80 --address 0.0.0.0
通過http://{Kind宿主機IP}:3000打開grafana面板,并使用上面獲取到的密碼登錄,可以看到Node Graph API插件成功安裝:
在node graph面板可以看到集群中網絡連接拓撲:
使用
統計類型
- connection:幫助了解工作負載之間以及與外部客戶端之間建立了多少連接。它會告訴你哪些套接字保持打開狀態并可能導致問題。
- bytes:顯示工作負載發送或接收的字節數。
- duration:計算連接的生命周期。
過濾器
- by namespace:選擇一個或多個 k8s 命名空間
- by names included:選擇工作負載名稱進行可視化
- by names excluded:從可視化中排除工作負載名稱