IMLC.ME

Kubernetes 容器内部如何捉 tcpdump

与普通场景下捉 tcpdump 不一样,部署在容器内部的应用程序无法直接在服务器上捉取流量。捕获应用程序流量要相对麻烦。

Sidecar

该方法 tcpdump 以容器的形式与应用程序共同运行。由于 Kubernetes 的多个 container 处于同一 network namespace,所以处于不同容器中的 tcpdump 可以捕获同一个 Pod 内的不同 container 的流量。

优点:通用性强

缺点:会导致 Pod 重启

例子

下方的 Yaml 文件中,定义了一个 Pod 和 一个 Service。

Pod 中有两个容器——httpbin 和 tcpdump。httpbin 是一款开源的 HTTP 测试程序,可用来接收请求和返回特定行为的响应,用于模拟应用程序。tcpdump 用于捕获流量。

这里我直接使用同行已经做好的 corfr/tcpdump 镜像。该镜像会 /data/ 目录下生成 tcpdump 文件。tcpdump 具体的行为可以参考 Dockerfile https://github.com/CoRfr/tcpdump-docker/blob/master/Dockerfile.

而 Service 用于暴露 httpbin,方便发起 HTTP 请求。

apiVersion: v1
kind: Pod
metadata:
  name: tcpdump-demo
  labels:
    app: tcpdump-demo
spec:
  containers:
    - name: httpbin
      image: kennethreitz/httpbin
      ports:
        - containerPort: 80
    - name: tcpdump
      image: corfr/tcpdump
---
apiVersion: v1
kind: Service
metadata:
  name: tcpdump-demo
  labels:
    app: tcpdump-demo
spec:
  ports:
    - port: 80
      protocol: TCP
  selector:
    app: tcpdump-demo
  type: NodePort

你可以通过执行 curl 命令,触发一段测试流量。

curl http://<node-ip>:<node-port>/get

然后,执行如下命令把流量文件拷贝出来,在 Wireshark 等软件中打开。

kubectl cp tcpdump-demo:/data/dump00 ./dump00 -c tcpdump

Worker Node

外部流量流入 Pod 前,必须经过 worker node。也就是说,在 worker node 上也可以捕获应用流量。

优点:可以捕获 Pod 启动前的流量

缺点:可能需要指定端口、网卡以避免捕获过多的流量。而查询端口、网卡操作比较麻烦。另外 worker node 上也未必有/允许安装 tcpdump。

tcpdump -C 1000 -W 100 -v -w dump.cap

容器内部执行 tcpdump 命令

直接 kubectl exec -it ...-- bash 进容器,以普通方法执行 tpcdump 命令也是一个可选的方法(大概)。

优点:可以避免容器重启丢失现场

缺点:我不觉得成熟的生产环境应用会开放 root 权限安装 tcpdump...

zypper in -y tcpdump # 或者通过其他系统的包管理工具安装 tcpdump
tcpdump -C 1000 -W 100 -v -w /tmp/dump.cap

之后把流量文件复制出来

kubectl cp tcpdump-demo:/tmp/dump.cap ./dump.cap