3月
18
背景
在docker中,为了尽可能缩减镜像大小,常常不会包含一些常用的工具,类似ping,curl,tcpdump等,虽然精简了镜像,但如果我们需要在容器内部测试网络联通性时,没有这些工具就非常的头疼。其实容器内部和主机之间的网络环境是互相隔离的,处于独立的命名空间下,那如果能在主机上切换命名空间,就可以在主机上以容器的网络环境进行操作,就可以利用主机上的工具,能够实现这种需求的工具就是我们今天要介绍的nsenter
使用
nsenter [options] [program [arguments]] options: -t, --target pid:指定被进入命名空间的目标进程的pid -m, --mount[=file]:进入mount命令空间。如果指定了file,则进入file的命令空间 -u, --uts[=file]:进入uts命令空间。如果指定了file,则进入file的命令空间 -i, --ipc[=file]:进入ipc命令空间。如果指定了file,则进入file的命令空间 -n, --net[=file]:进入net命令空间。如果指定了file,则进入file的命令空间 -p, --pid[=file]:进入pid命令空间。如果指定了file,则进入file的命令空间 -U, --user[=file]:进入user命令空间。如果指定了file,则进入file的命令空间 -G, --setgid gid:设置运行程序的gid -S, --setuid uid:设置运行程序的uid -r, --root[=directory]:设置根目录 -w, --wd[=directory]:设置工作目录 如果没有给出program,则默认执行$SHELL。
ping
以nginx镜像为例,nginx镜像默认是不包含ping命令,也不包含ip,ifconfig等常用命令
# docker run --name nginx-app -d nginx 2c0b7246f4a10d043e07527fdc4c3237c7af9d643741c954d4a84ece37976014 # docker exec -it nginx-app bash root@2c0b7246f4a1:/# ping www.baidu.com bash: ping: command not found # ip addr bash: ip: command not found # ifconfig bash: ifconfig: command not found
很多时候我们需要知道容器内部解析的域名ip信息,如果没有这些工具,本来很简单的事就变得很麻烦,通过以下步骤就可以通过nsenter
解决以上问题
- 获取容器pid
# docker inspect nginx-app -f '{{.State.Pid}}' 23069 #也可以通过ContainerID docker inspect 2c0b7246f4a1 -f '{{.State.Pid}}' 23069
- 执行
nsenter
命令
# nsenter -n -t23069 # ifconfig eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST> mtu 1500 inet 172.17.0.5 netmask 255.255.0.0 broadcast 0.0.0.0 inet6 fe80::42:acff:fe11:5 prefixlen 64 scopeid 0x20<link> ether 02:42:ac:11:00:05 txqueuelen 0 (Ethernet) RX packets 3 bytes 222 (222.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 8 bytes 648 (648.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
这个命令没有任何输出,通过ifconfig命令查看当前ip可以确定我们已经进入了容器的网络空间
这时候主机上的命令都可以使用
]# ip addr 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1 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 16: eth0@if17: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP link/ether 02:42:ac:11:00:05 brd ff:ff:ff:ff:ff:ff link-netnsid 0 inet 172.17.0.5/16 scope global eth0 valid_lft forever preferred_lft forever inet6 fe80::42:acff:fe11:5/64 scope link valid_lft forever preferred_lft forever # ping www.baidu.com PING www.a.shifen.com (180.101.49.12) 56(84) bytes of data. 64 bytes from 180.101.49.12 (180.101.49.12): icmp_seq=1 ttl=49 time=10.1 ms 64 bytes from 180.101.49.12 (180.101.49.12): icmp_seq=2 ttl=49 time=10.1 ms
- 退出
如果想退出当前网络空间,返回系统网络空间,输入exit
就行
# exit logout
kubernetes
如果是kubernetes的话事情会变得稍微复杂点,首先你得确定你的应用部署在哪个节点上,还要确定containerid
# kubectl get po {pod名称} -n {命名空间} -ojsonpath='{..nodeName}' k8s-node-dev-1 # kubectl get po {pod名称} -n {命名空间} -ojsonpath='{...containerStatuses[0].containerID}' docker://6dee4b562504cd63480e56e65f692943ce368a85b08ed1090171afc2c4f0f6a7
拿到containerid后就可以登录到pod所在的主机上按照上面的步骤进行操作
在kubernetes中最常用的应该是我们需要一个service的地址,通过nsenter
工具进入pod的网络空间后,可以通过ping {服务名称}
获取服务ip
nsenter
是Linux平台上的工具,不适用windows和Mac
Address: https://zhengjianfeng.cn/?p=527
no comment untill now