背景
在日常kubernetes的運維中,經常遇到pod的網絡問題,如pod間網絡不通,或者端口不通,更複雜的,需要在容器裡面抓包分析才能定位。而kubertnets的場景,pod使用的鏡像一般都是盡量精簡,很多都是基于alpine基礎鏡像制作的,因而pod内沒有ping,telnet,nc,curl指令,更别說tcpdump這種複雜的工具了。除了在容器或者鏡像内直接安裝這些工具這種最原始的法子,我們探讨下其他法子。
實作
kubectl debug插件方式
項目位址 kubect debug,https://github.com/aylei/kubectl-debug
kubectl-debug
是一個簡單的 kubectl 插件,能夠幫助你便捷地進行 Kubernetes 上的 Pod 排障診斷。背後做的事情很簡單: 在運作中的 Pod 上額外起一個新容器,并将新容器加入到目标容器的
pid
,
network
,
user
以及
ipc
namespace 中,這時我們就可以在新容器中直接用
netstat
,
tcpdump
這些熟悉的工具來解決問題了, 而舊容器可以保持最小化,不需要預裝任何額外的排障工具。操作流程可以參見官方項目位址文檔。
一條 kubectl debug指令背後是這樣的
步驟分别是:
- 插件查詢 ApiServer:demo-pod 是否存在,所在節點是什麼
- ApiServer 傳回 demo-pod 所在所在節點
- 插件請求在目标節點上建立 Debug Agent Pod
- Kubelet 建立 Debug Agent Pod
- 插件發現 Debug Agent 已經 Ready,發起 debug 請求(長連接配接)
- Debug Agent 收到 debug 請求,建立 Debug 容器并加入目标容器的各個 Namespace 中,建立完成後,與 Debug 容器的 tty 建立連接配接
接下來,用戶端就可以開始通過 5,6 這兩個連接配接開始 debug 操作。操作結束後,Debug Agent 清理 Debug 容器,插件清理 Debug Agent,一次 Debug 完成。
直接進入容器net ns方式
有2種進入pod 所在net ns的方式,前提都是需要登入到pod所在主控端,且需要找出pod對應的容器ID或者名字。
ip netns方式
- 擷取pod對應容器的ID或者name
pid="$(docker inspect -f '{{.State.Pid}}' <container_name | uuid>)" #替換為環境實際的容器名字或者uuid
-
建立容器對應netns
ip netns會到/var/run/netns目錄下尋找network namespace,把容器程序中netns連接配接到這個目錄中後,ip netns才會感覺到
$ sudo mkdir -p /var/run/netns #docker預設不會建立這個連結,需要手動建立,這時候執行ip netns,就應當看到連結過來的network namespace $ sudo ln -sf /proc/$pid/ns/net "/var/run/netns/<container_name|uuid>"
- 執行ip netns <<container_name|uuid > bash,進入容器ns
ip netns exec <container_name|uuid> bash
- 執行telnet,tcpdump等指令,此時執行ip a或者ifconfig,隻能看到容器本身的IP
如下圖,執行ifconfig,隻看到容器本身的IP,此時執行telnet,tcpdump等于直接在容器内操作
nsenter方式
nsenter為util-linux裡面的一個工具,除了進入容器net ns,還支援其他很多操作,可以檢視官方文檔。
pid="$(docker inspect -f '{{.State.Pid}}' <container_name | uuid>)"
nsenter -t $pid -n /bin/bash
tcpdump -i eth0 -nn #此時利用主控端的tcpdump執行抓包操作,等于在容器内抓包
總結
- kubectl debug方式功能更強大,缺點是需要附加鏡像,要在目标pod建立debug agent的容器,比較笨重,但是優點是能使用的工具更多,不需要ssh到pod所在節點,除了netstat,tcpdump工具,還能使用htop,iostat等其他進階工具,不僅能對網絡進行debug,還能對IO等其他場景進行診斷,适用更複雜的debug場景。
- 直接進入容器net ns方式相對比較輕量,複用pod所在主控端工具,但魚和熊掌不可兼得,缺點是隻能進行網絡方面的debug,且需要ssh登入到pod所在節點操作。