kubernetes 實(shí)用技巧: 使用 ksniff 抓包
概述
Kubernetes 環(huán)境中遇到網(wǎng)絡(luò)問題需要抓包排查怎么辦?傳統(tǒng)做法是登錄 Pod 所在節(jié)點(diǎn),然后 進(jìn)入容器 netns,最后使用節(jié)點(diǎn)上 tcpdump 工具進(jìn)行抓包。整個(gè)過程比較繁瑣,好在社區(qū)出現(xiàn)了 ksniff 這個(gè)小工具,它是一個(gè) kubectl 插件,可以讓我們在 Kubernetes 中抓包變得更簡單快捷。
本文將介紹如何使用 ksniff 這個(gè)工具來對(duì) Pod 進(jìn)行抓包。
安裝
ksniff 一般使用 krew 這個(gè) kubectl 包管理器進(jìn)行安裝:
kubectl krew install sniff
使用 wireshark 實(shí)時(shí)分析
抓取指定 Pod 所有網(wǎng)卡數(shù)據(jù)包,自動(dòng)彈出本地安裝的 wireshark 并實(shí)時(shí)捕獲:
kubectl -n test sniff website-7d7d96cdbf-6v4p6
可以使用 wireshark 的過濾器實(shí)時(shí)過濾分析喲:

保存抓包文件
有時(shí)在生產(chǎn)環(huán)境我們可能無法直接在本地執(zhí)行 kubectl,需要經(jīng)過跳板機(jī),這個(gè)時(shí)候我們可以將抓到的包保存成文件,然后再拷到本地使用 wireshark 分析。
只需加一個(gè) -o 參數(shù)指定下保存的文件路徑即可:
kubectl -n test sniff website-7d7d96cdbf-6v4p6 -o test.pcap
特權(quán)模式
ksniff 默認(rèn)通過上傳 tcpdump 二進(jìn)制文件到目標(biāo) Pod 的一個(gè)容器里,然后執(zhí)行二進(jìn)制來實(shí)現(xiàn)抓包。但該方式依賴容器是以 root 用戶啟動(dòng)的,如果不是就無法抓包。
這個(gè)時(shí)候我們可以加一個(gè) -p 參數(shù),表示會(huì)在 Pod 所在節(jié)點(diǎn)新起一個(gè) privileged 的 Pod,然后該 Pod 會(huì)調(diào)用容器運(yùn)行時(shí) (dockerd 或 containerd 等),新起一個(gè)以 root 身份啟動(dòng)的 container,并 attach 到目標(biāo) Pod 的 netns,然后執(zhí)行 container 中的 tcpdump 二進(jìn)制來實(shí)現(xiàn)抓包。
用法示例:
kubectl -n test sniff website-7d7d96cdbf-6v4p6 -p
查看明文
如果數(shù)據(jù)包內(nèi)容很多都是明文 (比如 HTTP),只希望大概看下明文內(nèi)容,可以指定 -o - 將抓包內(nèi)容直接打印到標(biāo)準(zhǔn)輸出 (stdout):
kubectl -n test sniff website-7d7d96cdbf-6v4p6 -o -
抓取時(shí)過濾
有時(shí)數(shù)據(jù)量很大,如果在抓取時(shí)不過濾,可能會(huì)對(duì) apiserver 造成較大壓力 (數(shù)據(jù)傳輸經(jīng)過 apiserver),這種情況我們最好在抓取時(shí)就指定 tcpdump 過濾條件,屏蔽掉不需要的數(shù)據(jù),避免數(shù)據(jù)量過大。
加 -f 參數(shù)即可指定過濾條件,示例:
kubectl -n test sniff website-7d7d96cdbf-6v4p6 -f "port 80"
FAQ
wireshark 報(bào) unknown
打開抓包文件時(shí),報(bào)錯(cuò) pcap: network type 276 unknown or unsupported:

通常是因?yàn)?wireshark 版本低導(dǎo)致的,升級(jí)到最新版就行。
抓包時(shí)報(bào) No such file or directory
使用 kubectl sniff 抓包時(shí),報(bào)錯(cuò) ls: cannot access '/tmp/static-tcpdump': No such file or directory 然后退出:

這是筆者在 mac 上安裝當(dāng)時(shí)最新的 ksniff v1.6.0 版本遇到的問題。該問題明顯是一個(gè) bug,static-tcpdump 二進(jìn)制沒有上傳成功就去執(zhí)行導(dǎo)致的,考慮三種解決方案:
手動(dòng)使用 kubectl cp 將二進(jìn)制拷到目標(biāo) Pod 再執(zhí)行 kubectl sniff 抓包。 kubectl sniff 指定 -p參數(shù)使用特權(quán)模式 (親測有效)。編譯最新的 ksniff,替換當(dāng)前 kubectl-sniff 二進(jìn)制,這也是筆者目前的使用方式。
