「深入浅出」理解 Linux Network-Namespace

Network-Namespace 是 Linux 内核提供的用于实现网络虚拟化的重要功能,它能创建多个隔离的网络空间,该网络空间内的防火墙、网卡、路由表、邻居表、协议栈与外部都是独立的。不管是虚拟机还是容器,当运行在独立的命名空间时,就像是一台单独的主机一样。**

下面会通过一些例子来说明网络命名空间,以加深理解,会用到 iproute2 工具包的 ip 命令,需先自行安装,并且使用 root 权限操作。

  1. 在 Centos 下执行如下命令:
yum install iproute2  
  1. 验证安装完成:
[root@worker3 ~]# ip help
Usage: ip [ OPTIONS ] OBJECT { COMMAND | help }
       ip [ -force ] -batch filename
where  OBJECT := { link | address | addrlabel | route | rule | neigh | ntable | tunnel | tuntap | maddress | mroute | mrule | monitor | xfrm | netns | l2tp | fou | macsec | tcp_metrics | token | netconf | ila | vrf }
       OPTIONS := { -V[ersion] | -s[tatistics] | -d[etails] | -r[esolve] |
                    -h[uman-readable] | -iec |
                    -f[amily] { inet | inet6 | ipx | dnet | mpls | bridge | link } |
                    -4 | -6 | -I | -D | -B | -0 |
                    -l[oops] { maximum-addr-flush-attempts } | -br[ief] |
                    -o[neline] | -t[imestamp] | -ts[hort] | -b[atch] [filename] |
                    -rc[vbuf] [size] | -n[etns] name | -a[ll] | -c[olor]}

创建网络命名空间

ip 命令中用于操作网络命名空间的命令是 ip netns,用 help 来查看一下子命令有哪些

[root@worker3 ~]# ip netns help
Usage: ip netns list
       ip netns add NAME
       ip netns set NAME NETNSID
       ip [-all] netns delete [NAME]
       ip netns identify [PID]
       ip netns pids NAME
       ip [-all] netns exec [NAME] cmd ...
       ip netns monitor
       ip netns list-id

常用的也就是增删查命令,先来创建一个网络空间空间 ns1

ip netns add ns1

查看当前所有的网络命名空间

[root@worker3 ~]# ip netns list
ns1

在这有些人可能会很困惑,我主机上明明运行中好几个 docker 容器,按理说每个容器都运行在独立的网络命名空间,怎么这里没有列出来?不要着急,下面会提到。

先来感觉一下什么叫独立的网卡,独立的路由表,要查看 ns1 命名空间的网卡,iproute2 工具提供了命令 ip netns exec ns1,跟在这个命令后面的命令都会在这个网络命名空间中执行。

先查看一下主机的网卡和路由表

[root@worker3 ~]# ip link
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:50:56:bb:ab:df brd ff:ff:ff:ff:ff:ff

[root@worker3 ~]# ip route
default via 10.57.4.1 dev eth0
10.1.2.0/24 dev br0 proto kernel scope link src 10.1.2.1

再看看 ns1 中的网卡和路由表

[root@worker3 ~]# ip netns exec ns1 ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    
[root@worker3 ~]# ip netns exec ns3 ip route

这样执行命令有点麻烦,也可以简单一点:

[root@worker3 ~]#ip netns exec ns1 bash
//这个命令后执行的命令就都是在ns1中执行了
[root@worker3 ~]#ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
[root@worker3 ~]#ip route

exit 可以回到主机的默认空间。

ip netns add的原理

当我们在主机上执行 ip netns add ns1 后 ,实际是在 /var/run/netns 下创建了一个 ns1 的文件

[root@worker3 ~]# ls /var/run/netns
ns1

下面的命令可以模拟 ip netns add ns2 && ip netns exec ns2 bash

[root@worker3 ~]# touch /var/run/netns/ns2
[root@worker3 ~]# unshare --net bash
[root@worker3 ~]# mount --bin /proc/self/ns/net /var/run/netns/ns2
//上面的过程实际就是执行了ip netns add ns2 && ip netns exec ns2 bash

[root@worker3 ~]# ip link
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00

[root@worker3 ~]# exit
//退出,回到主机默认命名空间。用ip netns list查看,已经可以看到ns2
[root@worker3 ~]# ip netns list
ns2
ns1
//如果想再次进入ns2,还有一个方法:
[root@worker3 ~]# nsenter --net=/var/run/netns/ns2

从上面的示例可以看出,创建命名的 Network Namespace 其实就是创建一个文件,然后通过绑定挂载的方式将新创建的 Network Namespace 文件和进程的 /proc/self/ns/net 文件绑定。

查看容器的网络命名空间

接下来该回答上面的遗留问题,为什么当我在主机上 ip netns list 的时候看不到 docker 的网络命名空间?因为 ip netns list 的时候只会显示在 /var/run/netns 下的文件,而 docker 的文件默认是创建在 /var/run/docker/netns 下的。所以我们可以通过 ls /var/run/docker/netns 来显示当前的所有容器的网络命名空间,并且通过 nsenter --net=/var/run/docker/xxx 来进入容器的网络命名空间。

[root@worker3 ~]# ls /var/run/docker/netns
5bbd5f99d403  a2eabf9acccb  b63ec59b3d9e  d6e4ff961713  default
[root@worker3 ~]# nsenter --net=/var/run/docker/netns/b63ec59b3d9e
[root@worker3 ~]# 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
4: eth0@if3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default
    link/ether fa:a7:8d:05:03:a6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 10.244.0.11/32 scope global eth0
       valid_lft forever preferred_lft forever

如果想查看具体某个 docker 容器对应的文件,可以用:

docker inspect $CONTAINER_ID$|grep SandboxKey

注意如果是 K8S 拉起来的 docker,要拿非 hostNetwork=true 的 pause 容器来看。如果hostNetwork=true,那么下面的值为 /var/run/docker/netns/default,这是主机的默认网络命名空间。如果不是 pause 容器,那么下面的值为空,因为只有 pause 容器会创建一个新的网络命名空间,其它 container 都只是加入这个网络命名空间。

[root@worker3 ~]# docker inspect ebd6855901ef|grep SandboxKey
            "SandboxKey": "/var/run/docker/netns/b63ec59b3d9e",

还有另一个办法:

[root@worker3 ~]# docker inspect nginx|grep Pid
            "Pid": 31817,
            "PidMode": "",
            "PidsLimit": null,
[root@worker3 ~]# mkdir -p /var/run/netns/
[root@worker3 ~]# ln -s /proc/31817/ns/net /var/run/netns/ns100
[root@worker3 ~]# ip netns ls
ns100
ns2
ns1
[root@worker3 ~]# ip netns exec ns100 bash
[root@worker3 ~]# //这时候已经在容器网络里了,比nsenter还方便

这个小技巧在我们调试 Pod 的网络时非常有用,大多数时候 Pod 里面自带的工具非常少,没有 curl 没有 telnet,这时候用这个技巧先进入空器的网络空间,再执行命令就行了,因为只是切了网络命名空间,其它还在主机上,所以用的工具也全是主机的工具。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,013评论 6 481
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,205评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 152,370评论 0 342
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,168评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,153评论 5 371
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,954评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,271评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,916评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,382评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,877评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,989评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,624评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,209评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,199评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,418评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,401评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,700评论 2 345

推荐阅读更多精彩内容