k8s抓取pod网络包

Mon May 25, 2020

500 Words|Read in about 3 Min
Tags: Devops  

在 Kubernetes 的实际使用中,我们经常需要配合业务调查问题,对于微服务来说,这个问题更多的是查看 API 的调用情况,这些API或者采用 RPC 协议或者是采用 HTTP 的协议。这两种协议都是基于 TCP 的协议,所以一般我们会到容器中使用 tcpdump 工具来抓包,然后就地或者拿出来放到 wireshark 图形化软件里面分析。

这种情况下,需要我们的基础镜像提前把 tcpdump 等排查工具打包进去,否则线上安装 debug 软件,一者违反安全规则,另外如果需要支持的 Pod 过多,安装 debug 工具本身就有不小的工作量。

krew

在 Kubernetes 中,有一个插件命令叫做 krew,可以通过这个命令来安装一个叫做 sniff 的插件工具来完成这个工作。下面我们先看看如何安装这个 krew 插件。

krew 的项目地址在:https://github.com/kubernetes-sigs/krew

首先,需要确认系统安装了 git。

其次,复制下面的命令到终端软件中,这段命令会去下载和安装这个 krew 插件。

$(
  set -x; cd "$(mktemp -d)" &&
  curl -fsSLO "https://storage.googleapis.com/krew/v0.2.1/krew.{tar.gz,yaml}" &&
  tar zxvf krew.tar.gz &&
  ./krew-"$(uname | tr '[:upper:]' '[:lower:]')_amd64" install \
    --manifest=krew.yaml --archive=krew.tar.gz
)

安装好的 krew 命令在目录 ~/.krew/bin 下面,所以我们可以把这个路径加到终端的配置文件中。一般是 ~/.bashrc 或者是 ~/.zshrc。

例如,使用如下的命令将 krew 命令的所在路径写入到 $PATH 中。

$ echo ‘export PATH=$PATH:$HOME/.krew/bin’ >> ~/.bashrc
需要注意的是,上面设置的这个路径同时也是通过 krew 安装的其他的插件命令所在的目录,所以一次设置后面其他的命令都可以直接使用了。

安装完 krew 之后,我们需要通过 kubectl krew update 命令来更新支持的插件命令列表,下载下来的 Plugin 配置文件都存放在 ~/.krew/index/plugins 下面。

$ kubectl krew update
Updated the local copy of plugin index.
sniff

我们可以使用命令 kubectl krew install sniff 来安装这个插件命令,安装好的命令位于 ~/.kube/store/sniff 下面。

$ kubectl krew install sniff
Updated the local copy of plugin index.
Installing plugin: sniff
CAVEATS:
\
 |  This plugin needs the following programs:
 |  * wireshark (optional, used for live capture)
/
Installed plugin: sniff

我们可以看下 sniff 命令的所在目录下的文件。

➜  ~ ls -ahl ~/.krew/store/sniff/v1.4.1
total 87056
drwx------  5 sk  staff   160B May 22 12:29 .
drwxr-xr-x  3 sk  staff    96B May 22 12:29 ..
-rw-r--r--  1 sk  staff    11K May 22 12:29 LICENSE
-rwxr-xr-x  1 sk  staff    40M May 22 12:29 kubectl-sniff
-rwxr-xr-x  1 sk  staff   2.6M May 22 12:29 static-tcpdump

这里面其实下载了两个文件,其中一个是 sniff,另外一个是 tcpdump,稍后我们会看到这个 tcpdump 的用途。

Pod 抓包 我们首先找个 Pod 来研究下 sniff 的具体抓包操作方法。

➜  ~            export KUBECONFIG=~/.kube/test
➜  ~ kubectl get pod
NAME                                               READY   STATUS    RESTARTS   AGE
client-59d4cd4c44-cbtrv                            2/2     Running   3          42d
datadog-agent-78xd4                                3/3     Running   2          2d
datadog-agent-kube-state-metrics-9d9b67548-x7lnf   2/2     Running   2          2d
datadog-agent-tvtzc                                3/3     Running   1          2d
datadog-agent-xd6hf                                3/3     Running   1          2d
nginx-5d58cd9694-mxnll                             2/2     Running   0          30d
server-5d648f9458-8lrnz                            2/2     Running   0          42d
server-5d648f9458-mdgw6                            2/2     Running   0          42d
server-5d648f9458-wxj9f                            2/2     Running   0          42d
➜  ~ kubectl get pod
➜  ~ kubectl sniff client-59d4cd4c44-cbtrv -o test.pcap
INFO[0000] sniffing method: upload static tcpdump
INFO[0000] using tcpdump path at: '/Users/sk/.krew/store/sniff/v1.4.1/static-tcpdump'
INFO[0000] no container specified, taking first container we found in pod.
INFO[0000] selected container: 'client'
INFO[0000] sniffing on pod: 'client-59d4cd4c44-cbtrv' [namespace: 'default', container: 'client', filter: '', interface: 'any']
INFO[0000] uploading static tcpdump binary from: '/Users/sk/.krew/store/sniff/v1.4.1/static-tcpdump' to: '/tmp/static-tcpdump'
INFO[0000] uploading file: '/Users/sk/.krew/store/sniff/v1.4.1/static-tcpdump' to '/tmp/static-tcpdump' on container: 'client'
INFO[0000] executing command: '[/bin/sh -c ls -alt /tmp/static-tcpdump]' on container: 'client', pod: 'client-59d4cd4c44-cbtrv', namespace: 'default'
INFO[0000] command: '[/bin/sh -c ls -alt /tmp/static-tcpdump]' executing successfully exitCode: '0', stdErr :''
INFO[0000] file found: '-rwxr-xr-x    1 root     root       2696368 Jan  1  1970 /tmp/static-tcpdump
'
INFO[0000] file was already found on remote pod
INFO[0000] tcpdump uploaded successfully
INFO[0000] output file option specified, storing output in: 'test.pcap'
INFO[0000] start sniffing on remote container
INFO[0000] executing command: '[/tmp/static-tcpdump -i any -U -w - ]' on container: 'client', pod: 'client-59d4cd4c44-cbtrv', namespace: 'default'

最后,我们就可以用本地的 wireshark 图形化工具打开这个 test.pcap 文件进行分析了。

使用wirshark打开即可

➜  ~ wireshark test.pcap

See Also

Mon May 25, 2020

500 Words|Read in about 3 Min
Tags: Devops