前言

如何知道 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"

安装成功,包含以下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 包地址如下:

同样的拉取到本地:

helm repo add grafana https://grafana.github.io/helm-charts helm fetch grafana/grafana tar -zxf grafana-6.32.13.tgz cd grafana/

修改values.yaml,将 Node Graph API 插件和数据源,以及 node-graph dashboard configmaps 添加到 Grafana。同时开启数据持久化。例如:

persistence: type: pvc enabled: true env: GF_INSTALL_PLUGINS: hamedkarbasi93-nodegraphapi-datasource dashboardProviders: dashboardproviders.yaml: apiVersion: 1 providers: - name: 'default' orgId: 1 folder: '' type: file disableDeletion: false editable: true options: path: /var/lib/grafana/dashboards/default dashboardsConfigMaps: default: k8spacket-node-graph-dashboard datasources: nodegraphapi-plugin-datasource.yaml: apiVersion: 1 datasources: - name: "Node Graph API" jsonData: url: "http://k8spacket.k8spacket.svc.cluster.local:8080" access: "proxy" basicAuth: false isDefault: false readOnly: false type: "hamedkarbasi93-nodegraphapi-datasource" typeLogoUrl: "public/plugins/hamedkarbasi93-nodegraphapi-datasource/img/logo.svg" typeName: "node-graph-plugin" orgId: 1 version: 1

在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插件成功安装:

数据库部署在k8s如何配置网络 如何使用K8spacket和(1)

在node graph面板可以看到集群中网络连接拓扑:

数据库部署在k8s如何配置网络 如何使用K8spacket和(2)

统计类型

数据库部署在k8s如何配置网络 如何使用K8spacket和(3)

数据库部署在k8s如何配置网络 如何使用K8spacket和(4)

数据库部署在k8s如何配置网络 如何使用K8spacket和(5)

,