背景
k8s中的容器里面沒有bash/sh可執行文件,使用kubectl exec指令無法進入容器;或者容器里面有bash/sh可執行文件,但是缺少其他用于排查問題的工具,如ping、tcpdump等。
解決方法
問題的原因是容器內的文件系統里沒有對應的可執行文件,如果需要的可執行文件在主機上是存在的,可以在pod所在宿主機上執行nsenter進入容器對應進程的network namespace內執行相關命令即可。
nsenter 是一個用于進入命名空間(namespace)的實用工具。它允許你在已經運行的進程的命名空間中執行命令,以便查看或修改這些命名空間的狀態。以下是 nsenter 的基本用法和一些常見參數:
基本用法:
nsenter [OPTIONS] [COMMAND] [ARG]...
常見參數:
-
-t或--target:指定目標進程的PID。這是進入其命名空間的目標進程。 -
-n:用于進入網絡命名空間,網絡命名空間允許不同命名空間中的進程擁有獨立的網絡棧,包括獨立的網絡接口、IP地址、路由表等。這意味著不同網絡命名空間中的進程可以隔離和互不干擾地運行網絡應用程序。pod內的容器共享一個網絡命名空間。 -
-u:用于進入UTS命名空間,該空間用于隔離進程的hostname。 -
-i:用于進入IPC命名空間,IPC命名空間允許不同命名空間中的進程擁有獨立的進程間通信(IPC)資源,如消息隊列、共享內存、信號等。這使得不同命名空間中的進程無法直接通信。 -
-m:用于進入掛載命名空間,掛載命名空間允許不同命名空間中的進程擁有獨立的文件系統掛載點和文件系統視圖。這意味著每個掛載命名空間都可以有自己的根文件系統,獨立于其他命名空間。 -
-p:PID命名空間,PID命名空間允許不同命名空間中的進程有獨立的進程ID(PID)空間,即不同命名空間中的進程可以擁有相同的PID而不會互相干擾。
實施例子
[root@localhost ~]# kubectl -n test exec -it nginx-test-xxx bash
[root@nginx-test-xxx nginx]# ip a
bash: ip: command not found
可以看到直接使用kubectl exec進入容器后發現沒有ip指令,接下來我們可以通過nsenter來獲取IP。
具體步驟:
-
查詢pod所在節點
[root@localhost ~]# kubectl -n test get po nginx-test-xxx -owide
[root@localhost ~]# kubectl -n test get po nginx-test-xxx -owide|awk 'NR>1 {print $7}'
192.168.212.15
-
在pod所在節點上查詢容器對應的進程id
#namespace和name支持正則表達式
[root@localhost ~]# crictl pods --namespace="test" --name="nginx-test-xxx.*"
POD ID CREATED STATE NAME NAMESPACE ATTEMPT
567f966d8d708 3 weeks ago Ready nginx-test-xxx test 0
#567f是前面指令獲得的podId
[root@localhost ~]# crictl inspectp --output=go-template --template="{{.info.pid}}" 567f966d8d708
28186
-
進入進程的網絡命名空間查詢IP
[root@localhost ~]# nsenter -t 28186 -n -- ip a
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2199: eth0@if2200: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1400 qdisc noqueue state UP group default
link/ether 00:00:00:5c:48:fe brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 100.126.0.46/16 brd 100.126.255.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::200:ff:fe5c:48fe/64 scope link
valid_lft forever preferred_lft forever
至此我們就獲取到了容器的IP,可以使用kubectl get po -owide 來比較下二者的IP是否一致。除了ip指令,主機上的其他網絡指令也能在容器內的網絡命名空間執行,對于排查網絡問題很有幫助。