进入到k8s的服务器,发现通过ip netns list
命名查看服务器的网络namespace,发现网络的namespace列表为空。难道k8s不是用namespace来隔离Pod之间的网络吗?
但是用ip netns list-id
却能看到网络的namespace id,且与对应个POD的数量差不多。因此可以猜测k8s只在Linux中存储了网络namespace的Id。
怎么用ip netns exec在k8s网络的namespace中执行
由于ip netns exec
命令必须要在/var/run/netns路径下有符号链接才能运行
方式一: 手动挂载一个容器的namespace到/var/run/netns
先查一下容器的PID,在k8s中可以查POD的pause容器对应的容器,然后再创建符号链接就可以在网络的namespace中执行命令了:
# (as root)
pid=$(docker inspect -f '{{.State.Pid}}' ${container_id})
mkdir -p /var/run/netns/
ln -sfT /proc/$pid/ns/net /var/run/netns/$container_id
然后就可以在container_id的网络namespace中执行exec了。比如,执行 ip link show 命令
ip netns exec "${container_id}" ip link show
其中:/proc/$pid/ns/net
文件中,记录了进程的网络namespace信息。
另外,如果安装了util-linux包,可以用nsenter命令进入容器的网络执行命令,比如:
nsenter -t <contanier_pid> -n <command>
实际操作示例
:
# 这里找一个k8s_POD_prometheus-k8s的pod
# docker ps |grep k8s_POD_prometheus-k8s
dab177ca748b k8s.gcr.io/pause:3.1 "/pause" 25 minutes ago Up 25 minutes k8s_POD_prometheus-k8s-0_monitoring_2d1a671f-0a5b-4899-a97b-c2ed2482cd8d_13
# 对dab177ca748b容器,挂载它的网络namespace到/var/run/netns/
container_id=dab177ca748b
pid=$(docker inspect -f '{{.State.Pid}}' ${container_id})
mkdir -p /var/run/netns/
ln -sfT /proc/$pid/ns/net /var/run/netns/$container_id
ip netns exec "${container_id}" ip a
# 下面是查看到的网络信息,和pod中看到的网络信息一致
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
3: eth0@if4: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default
link/ether 42:dc:93:4d:69:2f brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.244.218.113/32 scope global eth0
valid_lft forever preferred_lft forever
4: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
方式二: /var/run/docker/netns挂载到nicolaka/netshoot容器
另外在/var/run/docker/netns
记录有容器的所有netns,通过nicolaka/netshoot也可以在容器的netns执行命令,比如:
docker run -it --rm -v /var/run/docker/netns:/var/run/netns --privileged=true nicolaka/netshoot ip netns list
方式三: /var/run/docker/netns挂载宿主机
在k8s的服务器上执行:
ln -s /var/run/docker/netns /var/run/netns
然后查看netns里面就有数据了:
# 查看netns列表
ip netns list
# 查看netns中的网络信息,比如(和在容器中用看到的网络信息一样):
ip netns exec 7c9cafcf98a2 ip addr
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
2: tunl0@NONE: <NOARP> mtu 1480 qdisc noop state DOWN group default qlen 1000
link/ipip 0.0.0.0 brd 0.0.0.0
4: eth0@if12: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1440 qdisc noqueue state UP group default
link/ether 8a:42:02:40:0e:ad brd ff:ff:ff:ff:ff:ff link-netnsid 0
inet 10.100.13.132/32 scope global eth0
valid_lft forever preferred_lft forever