範例講解看nsenter帶你「上帝視角」看網路

2023-07-06 15:00:12
摘要:本文重點關注進入目標程序的「網路ns」視角,即站在「容器中的程序視角」看待容器裡面的網路世界,並在那個視角中執行命令。

本文分享自華為雲社群《《跟唐老師學習雲網路》 - nsenter魔法棒》,作者:tsjsdbd 。

有時候Docker容器中缺少需要的軟體。比如 curl,wget,ifconfig,ip,tcpdump 等基礎軟體包,什麼都幹不了,很是讓人抓狂。

[root@tsjsdbd home]# docker exec -it 8402 /bin/bash
root@8402d89fe04a:/# ifconfig
bash: ifconfig: command not found
root@8402d89fe04a:/# ip
bash: ip: command not found
root@8402d89fe04a:/# tcpdump
bash: tcpdump: command not found
root@8402d89fe04a:/# curl
bash: curl: command not found
root@8402d89fe04a:/# nslookup
bash: nslookup: command not found
root@8402d89fe04a:/# wget
wget: missing URL
Usage: wget [OPTION]... [URL]...

面對這種容器映象,定位問題就會很困難,因為你進入容器後,想執行命令還得重新安裝各種基礎軟體,非常麻煩。

這個時候,我們要拿起「nsenter」這個根魔法棒,在主機上上面揮舞起來。

ns-enter,顧名思義,就是「進入各種namespace」,即nsenter命令可以進入到指定目標程序的ns視角。

所以nsenter可以站在指定程序的「視角」看世界,本文重點關注進入目標程序的「網路ns」視角,即站在「容器中的程序視角」看待容器裡面的網路世界,並在那個視角中執行命令。

首先,我們要找到,要進入的「目標ns」的目標程序ID。即:容器裡面的根程序

[root@tsjsdbd ubuntu]# docker inspect 8402d89fe04a
[
    {
        "Id": "8402d89fe04a7e161faf8a01a86c47f8402d4c8d7207b6897d8e6d661d670df4",
        "State": {
            "Status": "running",
            "Pid": 18751,
            "ExitCode": 0,
            "Error": "",
            "StartedAt": "2023-05-10T03:12:19.221460059Z",
            "FinishedAt": "0001-01-01T00:00:00Z"
        },

容器裡的「老大」是程序18751號。

所以我們直接在Host主機上,跟蹤這個程序,並進入它的「視角」,我們就可以看到容器裡面的世界了。而且由於我們這個時候,作為控制者,還是處在Host主機上的,因此可以執行Host主機上的各種命令列。

如下:

[root@tsjsdbd ubuntu]# nsenter -t 18751 -n ifconfig
eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
 inet 172.17.0.2  netmask 255.255.0.0  broadcast 172.17.255.255
        ether 02:42:ac:11:00:02 txqueuelen 0  (Ethernet)
        RX packets 1688355  bytes 194318903 (185.3 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 138826  bytes 146246172 (139.4 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
lo: flags=73<UP,LOOPBACK,RUNNING>  mtu 65536
 inet 127.0.0.1  netmask 255.0.0.0
 loop  txqueuelen 0  (Local Loopback)
        RX packets 13939  bytes 13140220 (12.5 MiB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 13939  bytes 13140220 (12.5 MiB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

其他命令,照搬都可以執行。

比如,容器裡面沒有nslookup命令,但是隻有Host主機上有,咱就可在容器中執行它:

[root@tsjsdbd ubuntu]# nsenter -t 18751 -n nslookup www.baidu.com
Server:       10.129.2.34
Address:   10.129.2.34#53
Non-authoritative answer:
www.baidu.com canonical name = www.a.shifen.com.
Name:  www.a.shifen.com
Address: 14.119.104.254
Name:  www.a.shifen.com
Address: 14.119.104.189

所以原本在容器裡面,無法執行的偵錯行為,就這麼可以完成偵錯。

更直接的,如果不帶最後的執行命令引數,可以直接進到「目標視角」裡面去,進行互動式執行cli:

[root@tsjsdbd ubuntu]# nsenter -t 18751 -n
#這裡就進入互動模式,相當於沒有填寫cli時,預設執行[當前bash]
[root@tsjsdbd ubuntu]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN
4261: eth0@if4262: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP
[root@tsjsdbd ubuntu]# curl
curl: try 'curl --help' or 'curl --manual' for more information
[root@tsjsdbd ubuntu]# tcpdump
listening on eth0, link-type EN10MB (Ethernet), capture size 262144 bytes
^C
0 packets captured
0 packets received by filter
0 packets dropped by kernel
[root@tsjsdbd ubuntu]# exit
#執行exit,可退出「目標視角」

可以看到,所有的網路相關的cli命令列都可以執行。

並且,這些命令,都是站在容器內的「視角」執行的,所以效果與在容器中是一樣的(雖然它們本身在Host中發起的)。

類似電影《原始碼》《駭客帝國》中那樣,用外面世界中的「人」,去控制「裡面世界」中的行為。希望可以理解這種上帝視角的邏輯:-)

總結用法:

(1) 找到目標程序PID

docker inspect xxx

(2)直接執行特定的cli命令

nsenter -n -t 822647 ifconfig

(3)進入容器視角,進行互動式cli

nsenter -n -t 822647
exit

 

點選關注,第一時間瞭解華為雲新鮮技術~