容器通用 linux删除docker0网卡,给网络命名空间增加或删除网卡

上次学习了网络命名空间,那么如何进入容器的命名空间呢?
运行的容器都对应一个PID,每个PID都有自己的命名空间 。在/proc/[pid]/ns目录下包含该进程所属的 信息 。
首先文件都是链接文件 。链接文件的内容格式为xxx:[inode ] 。其中的xxx为的类型,inode 则用来标识一个 。如果两个进程的某个文件指向同一个链接文件,说明相关资源在同一个中,比如同一个pod中容器的net命名空间是同一个,即使1个pod一个容器,在pod运行主机上 ps可以看到2个容器,这两个容器是同一net命名空间,这是k8s pod的特色 。
其次/proc/[pid]/ns 里放置这些链接文件的另外一个作用是,一旦这些链接文件被打开,只要打开的文件描述符(fd)存在,那么该下的所有进程都已结束,这个也会一直存在,后续的进程可以复用 。问题来了,怎么向容器中添加一个网卡或者删除一个网卡呢?
网络命名空间一文中看很简单,ip netns show查到一台主机上的网络命名空间,ip link set {网卡名字} netns {网络命名空间}执行下即可 。网卡名字可以是主机上的网卡名字,也可以是虚拟出来的网卡名字(如veth设备) 。
但事实上linux下的网络命名空间除了/proc/[pid]/ns下的,用命令根本查不到 。这是为什么呢?
原来是Linux下默认(包括,容器也是一个pid)把创建的网络命名空间链接文件隐藏起来了,导致ip netns命令无法读取 。
恢复任意pid的netns
【容器通用linux删除docker0网卡,给网络命名空间增加或删除网卡】获取容器的进程号:容器名称 | grep Pid 或者-f '{{.State.Pid}} 容器id或容器名称
将进程网络命名空间恢复到主机目录:ln -s /proc/{Pid}/ns/net /var/run/netns/某容器的命名空间,这里的容器命名空间的名字自己任意定义,只是做个软链接 。如果/var/run/netns目录不存在,以root用户手动创建目录 。
然后执行ip netns命令查看看该容器的网络命名空间 。
ip link set {网卡名字} netns {网络命名空间}
网络命名空间为容器的则为容器添加网卡(记得手工和配置ip) 。
从网络命名空间中删除一个网卡eth0到另一个网络命令空间:
ip netns execip link set eth0 netns
从网络命名空间中删除一个网卡eth0到Linux上默认的网络命令空间:
ip netns execip link set eth0 netns $$

容器通用  linux删除docker0网卡,给网络命名空间增加或删除网卡

文章插图
ip netns execip link set eth0 netns {Linux主机上某pid,以父进程id 1为例}
ps:不实践不知道,原来Linux主机上默认的网络命名空间不是和,预测是要做软连接的 。还好ip link set {网卡名字} netns {网络命名空间},这其中的网络命名空间可以指定pid即可 。
删除软连接:rm -rf /var/run/netns/某容器的命名空间
实际操作中一点感悟:原本通过eth0的ip ssh登录着,将Linux主机上的eth0网卡设置加入自己创建的一个网络命名空间后,ssh登录断开了 。回想起来,ssh进程和Linux主机网卡eth0在同一个网络命名空间下,当将网卡命名空间换了后,Linux主机上就看不到这个网卡了,网络就不通了 。
再抛出个问题:为何Linux下网络命名空间被隐藏了?
命名空间都有有一个inode节点,相对来说隐藏起来不会误删除 。
查询命名空间的使用场景比较少,一般谁去查命名空间呢 。
也有可能先有命名空间,后有的ip netns 。
ip netns show查命名空间从/var/run/netns/这个目录下读取的,pid下的网络命名空间可以是相同的,65536个pid的网络命名空间个数不定,如果ip netns show一个一个递归去查,有可能比较慢 。参考