Kubernetes Pod 命名空间内抓包
Jun 10, 2020 22:20 · 686 words · 2 minute read
有时我们需要抓包来观察 Kubernetes 上的应用程序流量,当然可以使用 kubectl exec -it
先进入 Pod 后直接抓包,但是容器镜像中不一定如我们所愿预先安装好了 tcpdump。既然容器的本质是“用各种类型的命名空间掩饰”的进程,那我们只要进入它的网络命名空间,就可以使用宿主机上的 tcpdump 工具对命名空间的网络栈进行抓包。
以抓取到达 Kube DNS (也就是 CoreDNS)的流量为例:
kubectl get po -l k8s-app=kube-dns -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-66bff467f8-b92vk 1/1 Running 22 26d
coredns-66bff467f8-r6ps5 1/1 Running 22 26d
我们需要查出 Pod 中容器的 PID,首先根据 Pod 名称中的关键字过滤出相关 Docker 容器:
$ docker ps | grep coredns
7af1244c7a30 67da37a9a360 "/coredns -conf /etc…" About a minute ago Up 59 seconds k8s_coredns_coredns-66bff467f8-r6ps5_kube-system_a7629e1d-59c8-44cf-8898-b80ea80c5a67_22
bd610a71fd45 67da37a9a360 "/coredns -conf /etc…" About a minute ago Up 59 seconds k8s_coredns_coredns-66bff467f8-b92vk_kube-system_cbc90861-dce9-471c-88ad-270b7e41ccf3_22
cc504bfc4899 k8s.gcr.io/pause:3.2 "/pause" About a minute ago Up 59 seconds k8s_POD_coredns-66bff467f8-r6ps5_kube-system_a7629e1d-59c8-44cf-8898-b80ea80c5a67_177
41d024c741b9 k8s.gcr.io/pause:3.2 "/pause" About a minute ago Up 59 seconds k8s_POD_coredns-66bff467f8-b92vk_kube-system_cbc90861-dce9-471c-88ad-270b7e41ccf3_197
使用 docker inspect
查出 ID 为 7af1244c7a30 的容器的 PID:
docker inspect -f {{.State.Pid}} 7af1244c7a30
4021
拿到 PID 4021
后使用 nsenter
命令进入容器的网络命名空间(Namespace)
$ nsenter --help
Usage:
nsenter [options] <program> [<argument>...]
Run a program with namespaces of other processes.
Options:
-t, --target <pid> target process to get namespaces from
-m, --mount[=<file>] enter mount namespace
-u, --uts[=<file>] enter UTS namespace (hostname etc)
-i, --ipc[=<file>] enter System V IPC namespace
-n, --net[=<file>] enter network namespace
-p, --pid[=<file>] enter pid namespace
-U, --user[=<file>] enter user namespace
-S, --setuid <uid> set uid in entered namespace
-G, --setgid <gid> set gid in entered namespace
--preserve-credentials do not touch uids or gids
-r, --root[=<dir>] set the root directory
-w, --wd[=<dir>] set the working directory
-F, --no-fork do not fork before execing <program>
-Z, --follow-context set SELinux context according to --target PID
-h, --help display this help and exit
-V, --version output version information and exit
For more details see nsenter(1).
$ nsenter -n -t 4021
查看 eth0 网卡:
$ ifconfig eth0
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1450
inet 10.244.0.249 netmask 255.255.255.0 broadcast 0.0.0.0
ether 66:5e:9c:02:1b:d1 txqueuelen 0 (Ethernet)
RX packets 884 bytes 286008 (279.3 KiB)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 862 bytes 88268 (86.1 KiB)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
10.244.0.249 就是 Kubernetes 网络为 Kube DNS Pod 分配的 IP。我们只需在此 eth0 网卡对 53 端口抓包即可:
$ tcpdump -i eth0 port 53
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
22:12:22.843753 IP k8s-kong.46400 > prl-local-ns-server.shared.domain: 26328+ NS? . (17)
22:12:22.844518 IP k8s-kong.60879 > prl-local-ns-server.shared.domain: 21544+ PTR? 1.55.211.10.in-addr.arpa. (42)
22:12:22.844944 IP prl-local-ns-server.shared.domain > k8s-kong.60879: 21544* 1/0/0 PTR prl-local-ns-server.shared. (82)
22:12:22.845114 IP k8s-kong.52595 > prl-local-ns-server.shared.domain: 35907+ PTR? 249.0.244.10.in-addr.arpa. (43)
22:12:22.856439 IP prl-local-ns-server.shared.domain > k8s-kong.52595: 35907 NXDomain* 0/1/0 (78)
22:12:24.344549 IP k8s-kong.55308 > prl-local-ns-server.shared.domain: 2512+ NS? . (17)
22:12:25.845298 IP k8s-kong.52928 > prl-local-ns-server.shared.domain: 58987+ NS? . (17)
22:12:27.346102 IP k8s-kong.55661 > prl-local-ns-server.shared.domain: 6125+ NS? . (17)
22:12:28.846757 IP k8s-kong.53771 > prl-local-ns-server.shared.domain: 54605+ NS? . (17)