K8S网络中的Namespace

olivee 4年前 ⋅ 1276 阅读

进入到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