namespace を一覧化する
lsns
で namespace の一覧を見ることができます。コンテナで bash を実行するコンテナを作った状態でlsns
を実行した結果が以下です。複数の TYPE の namespace ができていることがわかります。
# lsns -o NS,TYPE,PATH,NPROCS,PID,PPID,COMMAND,UID,USER
NS TYPE PATH NPROCS PID PPID COMMAND UID USER
4026531835 cgroup /proc/1/ns/cgroup 126 1 0 /sbin/init 0 root
4026531836 pid /proc/1/ns/pid 124 1 0 /sbin/init 0 root
4026531837 user /proc/1/ns/user 126 1 0 /sbin/init 0 root
4026531838 uts /proc/1/ns/uts 124 1 0 /sbin/init 0 root
4026531839 ipc /proc/1/ns/ipc 124 1 0 /sbin/init 0 root
4026531840 mnt /proc/1/ns/mnt 120 1 0 /sbin/init 0 root
4026531861 mnt /proc/19/ns/mnt 1 19 2 kdevtmpfs 0 root
4026531993 net /proc/1/ns/net 124 1 0 /sbin/init 0 root
4026532157 mnt /proc/446/ns/mnt 1 446 1 /lib/systemd/systemd-udevd 0 root
4026532167 mnt /proc/490/ns/mnt 1 490 1 /lib/systemd/systemd-networkd 100 systemd-network
4026532168 mnt /proc/518/ns/mnt 1 518 1 /lib/systemd/systemd-resolved 101 systemd-resolve
4026532193 mnt /proc/27142/ns/mnt 2 27142 27104 bash 0 root
4026532194 uts /proc/27142/ns/uts 2 27142 27104 bash 0 root
4026532195 ipc /proc/27142/ns/ipc 2 27142 27104 bash 0 root
4026532196 pid /proc/27142/ns/pid 2 27142 27104 bash 0 root
4026532198 net /proc/27142/ns/net 2 27142 27104 bash 0 root
コンテナ内で動いているプロセスの PID(この例では、27142) がlsns
と一致していることがわかります。
# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ef0425afad12 nicolaka/netshoot "bash" 54 minutes ago Up 54 minutes vigilant_hopper
# docker inspect --format {{.State.Pid}} ef0425afad12
27142
namespace に入る
nsenter
コマンドを使うと namespace の中に入ってコマンドを実行することができて便利です。例えば、コンテナ内には netstat コマンドが入っていないけれど、実行したい時は以下のように、--target PID
で対象プロセスを指定します。network namespace に入る場合は、--net
指定します。
# nsenter --target 27142 --net netstat -ant
Active Internet connections (servers and established)
Proto Recv-Q Send-Q Local Address Foreign Address State
tcp 0 0 172.17.0.2:53400 172.217.175.238:80 TIME_WAIT
--mount
を指定すると mount namespace になります。--all
で全てのタイプの namespace に入ります。
# nsenter --target 27142 --all cat /etc/os-release
NAME="Alpine Linux"
ID=alpine
VERSION_ID=3.13.2
PRETTY_NAME="Alpine Linux v3.13"
HOME_URL="https://alpinelinux.org/"
BUG_REPORT_URL="https://bugs.alpinelinux.org/"
ネットワークの階層モデルと namespace
namespace の影響受けるもの
netstat
コマンドは namespace によって見える範囲が変わります。例えば、コンテナ内から curl http://google.com/
を実行した直後の状態です。
# nsenter --target 27142 --all netstat -ant | grep 80
tcp 0 0 172.17.0.2:34148 216.58.197.206:80 TIME_WAIT
# netstat -ant | grep 80
# 何も表示されない
arp
コマンドも同様です。
# nsenter --target 27142 --all arp
? (172.17.0.1) at 02:42:b0:b9:9b:50 [ether] on eth0
# arp
Address HWtype HWaddress Flags Mask Iface
172.17.0.2 ether 02:42:ac:11:00:02 C docker0
10.0.2.3 ether 52:54:00:12:35:03 C eth0
_gateway ether 52:54:00:12:35:02 C eth0
namespace の影響受けないもの
一方、tcpdump
コマンドは namespace の影響受けません。コンテナ内から curl http://google.com/
を実行した時の結果です。tcpdump
はより低レイヤー(データリンク層 L2)の情報を取得するからのようです。
# コンテナ内部で tcpdump を実行した結果
13:19:41.076077 IP a8c89c57d8ef.40442 > nrt12s36-in-f14.1e100.net.80: Flags [P.], seq 0:74, ack 1, win 64240, length 74: HTTP: GET / HTTP/1.1
# コンテナ外部で tcpdump を実行した結果
13:19:41.076207 IP vagrant.40442 > nrt12s36-in-f14.1e100.net.http: Flags [P.], seq 0:74, ack 1, win 64240, length 74: HTTP: GET / HTTP/1.1
コンテナ外部で iptraf-ng
を使うと、コンテナ内から張った TCP コネクションを一覧化することが出来て便利です。
参考
https://qiita.com/minamijoyo/items/9dd59109e9fe1a35f888
https://github.com/nicolaka/netshoot