Linux network namespace(网络命名空间)认知

写在前面


  • 整理K8s网络相关笔记
  • 博文内容涉及 Linux network namespace 认知以及彼此通信Demo,实际中的应用
  • 理解不足小伙伴帮忙指正

不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候,眼前的风景已经和从前不一样了。——村上春树


network namespace 是什么?

可以通过 ip-netns 帮助文档简单了解

┌──[liruilong@liruilongs.github.io]-[~]
└─$man ip-netns | cat

网络命名空间在逻辑上是网络堆栈的另一个副本,具有自己的路由、防火墙规则和网络设备

默认情况下,进程从其父进程继承其网络名称空间。 最初,所有进程共享来自 init 进程的相同默认网络命名空间。即 Linux 进程处在和主机相同的 namespace,即初始的根 namespace 里,默认享有全局系统资源。

按照约定,命名网络命名空间是位于 /var/run/netns/NAME 的可以打开的对象。 打开 /var/run/netns/NAME 产生的文件描述符引用指定的网络名称空间。 保持文件描述符打开可以使网络命名空间保持活动状态。 文件描述符可以与 setns(2) 系统调用一起使用来更改与任务关联的网络命名空间。

对于了解网络命名空间的应用程序,惯例是首先在 /etc/netns/NAME/ 中查找全局网络配置文件,然后在 /etc/ 中查找。 例如,如果您想要不同的用于隔离 VPN 的网络命名空间的 /etc/resolv.conf 版本,您可以将其命名为 /etc/netns/myvpn/resolv.conf

ip netns exec 通过创建安装命名空间并绑定安装所有每个网络命名空间,自动处理此配置、网络命名空间不感知应用程序的文件约定将文件配置到 /etc 中的传统位置。

network namespace 可以说是整个 Linux 网络虚拟化技术的基石,其作用就是隔离内核资源

Linux 内核自2.4.19 版本接纳第一个 namespace:Mount namespace(用于隔离文件系统挂载点)起,到 3.8 版本的user namespace(用于隔离用户权限),总共实现了 6 种不同类型的 namespace (Mount namespace、UTS namespace(主机名)、IPC namespace(进程通信mq)、PID namespace、network namespace和user namespace)

默认情况下 network namespace 在 Linux 内核 2.6 版本引入,作用是隔离 Linux 系统的设备,以及 IP 地址、端口、路由表、防火墙规则等网络资源。因此,每个网络 namespace 里都有自己的网络设备(如 IP 地址、路由表、端口范围、/proc/net 目录等)。

初识 network namespace

network namespace 可以通过系统调用来创建,当前 network namespace 的增删改查功能已经集成到 Linux 的 ip 工具的 netns 子命令中。

帮助文档中的 Demo

   ip netns add vpn
          创建名为vpn的网络名称空间

   ip netns exec vpn ip link set lo up
          在vpn网络名称空间中激活回环接口。

创建一个名为 ns_lrlnetwork namespace

┌──[root@liruilongs.github.io]-[~]
└─$ip netns list
┌──[root@liruilongs.github.io]-[~]
└─$ip netns add ns_lrl
┌──[root@liruilongs.github.io]-[~]
└─$ip netns list
ns_lrl

创建了一个 network namespace 时,系统会在 /var/run/netns 路径下面生成一个挂载点

┌──[root@vms105.liruilongs.github.io]-[~]
└─$ls /var/run/netns/ns_lrl
/var/run/netns/ns_lrl
┌──[root@vms105.liruilongs.github.io]-[~]
└─$

挂载点的作用一方面是方便对 namespace 的管理,另一方面是使 namespace 即使没有进程运行也能继续存在。

命令空间通过下面的方式激活回环接口后

┌──[root@liruilongs.github.io]-[~]
└─$ip netns  exec ns_lrl ip link set lo up

可以看到像默认 Linux namespace 一样的本地回环地址

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec ns_lrl ip a
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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever

做简单的 ping 测试

┌──[root@vms105.liruilongs.github.io]-[~]
└─$ip netns exec ns_lrl  ping 127.0.0.1 -c 3
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.044 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.033 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.031 ms

--- 127.0.0.1 ping statistics ---
3 packets transmitted,3 received,0% packet loss,time 2024ms
rtt min/avg/max/mdev = 0.031/0.036/0.044/0.005 ms
┌──[root@vms105.liruilongs.github.io]-[~]
└─$

配置 network namespace 之间通信

虚拟以太网对(veth pair)

我们来看一个 Demo,两个网络命名空间如何通信,在这之前,先看一点理论,

veth pair是Virtual Ethernet(虚拟以太网)接口在Linux中的一种实现方式。veth接口具有以下特点:

veth是一对接口,分别位于两个不同的network namespace中。这一对接口通过内核实现软链接,可将不同namespace中的数据连接起来。数据可以直接在这一对接口间进行传输,实现了namespace间的数据通信。

创建一个网络命名空间

┌──[liruilong@liruilongs.github.io]-[~]
└─$ip netns add net1
mkdir /var/run/netns failed: Permission denied

需要 root 才行,切一下 root,这里需要说明

  • 非 root 进程被分配到 network namespace 后只能访问和配置已经存在于该 network namespace 的设备
  • root 进程可以在 network namespace 里创建新的网络设备
  • network namespace 里的 root 进程还能把本 network namespace 的虚拟网络设备分配到其他 network namespac
┌──[liruilong@liruilongs.github.io]-[~]
└─$sudo -i
[sudo] password for liruilong:

创建两个 网络命名空间

┌──[root@liruilongs.github.io]-[~]
└─$ip netns add net1
┌──[root@liruilongs.github.io]-[~]
└─$ip netns add net2
┌──[root@liruilongs.github.io]-[~]
└─$ip netns list
net2
net1

仅有一个本地回环设备是没法与外界通信的。如果我们想与外界(比如主机上的网卡)进行通信,就需要在 namespace 里再 创建一对虚拟的以太网卡,即所谓的 veth pair。顾名思义,veth pair 总是成对出现且相互连接,它就像 Linux 的双向管道(pipe),报文从 veth pair 一端进去就会由另一端收到.

┌──[root@liruilongs.github.io]-[~]
└─$ip link add veth1 netns net1 type veth peer name veth2 netns net2
┌──[root@liruilongs.github.io]-[~]
└─$ip link
1: lo: <LOOPBACK,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: ens160: <BROADCAST,MULTICAST,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
  • ip link add: 创建一对接口
  • veth1: 设置本地端接口名
  • netns net1: 将 veth1 移动到名为 net1 的命名空间
  • type veth: 指定接口类型为veth虚拟接口,veth是virtual ethernet的缩写,即虚拟以太网接口。
  • peer name veth2: 设置远端接口名
  • netns net2: 将veth2移动到名为 net2 的命名空间

上面的操作创建了 veth1veth2 这么一对虚拟以太网卡。在默认情况下,它们都在主机的根 network namespce 中,将其中一块虚拟网卡 veth1 通过 netns net1 命令移动到 net1 network namespace,另一块网卡通过 netns net2 命令移动到 命令移动到 net2 network namespace`

执行这个命令后,会在两个不同的命名空间net1和net2内各自创建一根接口:

  • 在 net1 命名空间内创建接口veth1
  • 在 net2 命名空间内创建接口veth2

这两根接口通过 peer 自动连接成一对,形成跨命名空间的虚拟链路

在每个命名空间执行 ip link 命令,可以看到详细的信息

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec net1 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
2: veth1@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether b2:ae:39:9e:50:4b brd ff:ff:ff:ff:ff:ff link-netns net2

net1 命名空间虚拟网卡 veth1,与名称为 net2 的命名空间相关联

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec net2 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
2: veth2@if2: <BROADCAST,MULTICAST> mtu 1500 qdisc noop state DOWN mode DEFAULT group default qlen 1000
    link/ether 7a:1b:8e:91:41:79 brd ff:ff:ff:ff:ff:ff link-netns net1

net2 命名空间虚拟网卡 veth2,与名称为 net1 的命名空间相关联

通过 ip netns exec net1 bash 这个命令进入指定命名空间的 shell 环境,在当前 shell 中执行的命名对当前命名空间生效

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec net1 bash

分配 IP 地址以及配置掩码,指定对应的虚拟网卡,这里分配IP 192.168.20.1/24

┌──[root@liruilongs.github.io]-[~]
└─$ip address add 192.168.20.1/24 dev veth1

激活本地回环网卡

┌──[root@liruilongs.github.io]-[~]
└─$ip link set dev lo up

激活虚拟网卡

┌──[root@liruilongs.github.io]-[~]
└─$ip link set dev veth1 up

因为另一端 veth1 还没有打开,所以链接状态仍然显示为关闭 state DOWN

┌──[root@liruilongs.github.io]-[~]
└─$ip link
1: lo: <LOOPBACK,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: veth1@if2: <NO-CARRIER,BROADCAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether b2:ae:39:9e:50:4b brd ff:ff:ff:ff:ff:ff link-netns net2

查看路由信息,可以发现,命令空间路由相互独立,但是由于接口当前 down,这条路由实际不可用

┌──[root@liruilongs.github.io]-[~]
└─$ip route
192.168.20.0/24 dev veth1 proto kernel scope link src 192.168.20.1 linkdown

查看命名空间IP信息

┌──[root@liruilongs.github.io]-[~]
└─$ip a
1: lo: <LOOPBACK,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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: veth1@if2: <NO-CARRIER,UP> mtu 1500 qdisc noqueue state DOWN group default qlen 1000
    link/ether b2:ae:39:9e:50:4b brd ff:ff:ff:ff:ff:ff link-netns net2
    inet 192.168.20.1/24 scope global veth1
       valid_lft forever preferred_lft forever
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit

退出第一个命名空间的 shell 环境,我们进入第二个命名空间的 shell 环境,做相同的配置 这里分配IP 192.168.20.2/24

┌──[root@liruilongs.github.io]-[~]
└─$ ip netns exec net2 bash
┌──[root@liruilongs.github.io]-[~]
└─$ip address add 192.168.20.2/24 dev veth2
┌──[root@liruilongs.github.io]-[~]
└─$ip link set dev veth2 up
┌──[root@liruilongs.github.io]-[~]
└─$ip link set dev lo up

这个时候,我们在看链接,状态,会发现,veth2 虚拟网卡状态为 UP 状态 state UP

┌──[root@liruilongs.github.io]-[~]
└─$ ip link
1: lo: <LOOPBACK,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: veth2@if2: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 7a:1b:8e:91:41:79 brd ff:ff:ff:ff:ff:ff link-netns net1

查看分配IP的虚拟网卡也为 UP 状态

┌──[root@liruilongs.github.io]-[~]
└─$ip a
1: lo: <LOOPBACK,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
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: veth2@if2: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 7a:1b:8e:91:41:79 brd ff:ff:ff:ff:ff:ff link-netns net1
    inet 192.168.20.2/24 scope global veth2
       valid_lft forever preferred_lft forever
    inet6 fe80::781b:8eff:fe91:4179/64 scope link
       valid_lft forever preferred_lft forever

独立的路由信息

┌──[root@liruilongs.github.io]-[~]
└─$ip route
192.168.20.0/24 dev veth2 proto kernel scope link src 192.168.20.2

回到 net1,net1名称空间中veth1的链接状态也显示UP (state UP)

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec net1 ip link
1: lo: <LOOPBACK,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: veth1@if2: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether b2:ae:39:9e:50:4b brd ff:ff:ff:ff:ff:ff link-netns net2
┌──[root@liruilongs.github.io]-[~]
└─$exit
exit

命名空间不知道net1net2命名空间的IP配置,三者彼此隔离。

┌──[root@liruilongs.github.io]-[~]
└─$ip link
1: lo: <LOOPBACK,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ff
    altname enp3s0

路由信息也为独立的路由信息

┌──[root@liruilongs.github.io]-[~]
└─$ip route
default via 192.168.26.2 dev ens160 proto dhcp src 192.168.26.149 metric 100
192.168.26.0/24 dev ens160 proto kernel scope link src 192.168.26.149 metric 100

从根网络命名空间 ping 测试到veth1 IP失败。这是因为IP 192.168.20.1 属于独立的网络命名空间 net1。

┌──[root@liruilongs.github.io]-[~]
└─$ping 192.168.20.1 -c 1
PING 192.168.20.1 (192.168.20.1) 56(84) bytes of data.

--- 192.168.20.1 ping statistics ---
1 packets transmitted,0 received,100% packet loss,time 0ms

net1net2 测试网络通信,命名空间使用 ping 命令。

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec net1 ping -c 1 192.168.20.2
PING 192.168.20.2 (192.168.20.2) 56(84) bytes of data.
64 bytes from 192.168.20.2: icmp_seq=1 ttl=64 time=0.060 ms

--- 192.168.20.2 ping statistics ---
1 packets transmitted,1 received,time 0ms
rtt min/avg/max/mdev = 0.060/0.060/0.060/0.000 ms

输出确认 net1 名称空间中的 veth1 接口能够成功地与 net2 名称空间中的 veth2 接口通信。

┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec net2 ping -c 1 192.168.20.1
PING 192.168.20.1 (192.168.20.1) 56(84) bytes of data.
64 bytes from 192.168.20.1: icmp_seq=1 ttl=64 time=0.027 ms

--- 192.168.20.1 ping statistics ---
1 packets transmitted,time 0ms
rtt min/avg/max/mdev = 0.027/0.027/0.027/0.000 ms
┌──[root@liruilongs.github.io]-[~]
└─$

在实际使用中,更多的是 当前的根网络命名空间和 某个网络命名空间组成 veth pair 进行通信。

# 创建一个网络命名空间
┌──[root@liruilongs.github.io]-[~]
└─$ip netns add pod_ns
# 在根网络命名空间和"pod_ns"命名空间之间创建一个veth pair,并将其中一个端口放入"pod_ns"命名空间:
┌──[root@liruilongs.github.io]-[~]
└─$ip link add veth0 type veth peer name veth1
┌──[root@liruilongs.github.io]-[~]
└─$ip link set veth1 netns pod_ns
# 在根网络命名空间中配置veth0的IP地址和其他网络参数
┌──[root@liruilongs.github.io]-[~]
└─$ip addr add 192.168.1.1/24 dev veth0
#激活虚拟网卡    
┌──[root@liruilongs.github.io]-[~]
└─$ip link set veth0 up
#  查看连接信息 link-netns pod_ns
┌──[root@liruilongs.github.io]-[~]
└─$ip link
1: lo: <LOOPBACK,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
4: veth0@if3: <NO-CARRIER,UP> mtu 1500 qdisc noqueue state LOWERLAYERDOWN mode DEFAULT group default qlen 1000
    link/ether 6e:62:83:49:71:90 brd ff:ff:ff:ff:ff:ff link-netns pod_ns
# 在"pod_ns"命名空间中配置veth1的IP地址和其他网络参数,激活网卡    
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec pod_ns ip addr add 192.168.1.2/24 dev veth1
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec pod_ns ip link set veth1 up

查看链接状态

┌──[root@liruilongs.github.io]-[~]
└─$ip link
1: lo: <LOOPBACK,LOWER_UP> mtu 1500 qdisc mq state UP mode DEFAULT group default qlen 1000
    link/ether 00:0c:29:93:51:67 brd ff:ff:ff:ff:ff:ff
    altname enp3s0
4: veth0@if3: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 6e:62:83:49:71:90 brd ff:ff:ff:ff:ff:ff link-netns pod_ns
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec pod_ns 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
3: veth1@if4: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default qlen 1000
    link/ether 7e:60:b2:6e:d8:55 brd ff:ff:ff:ff:ff:ff link-netnsid 0
┌──[root@liruilongs.github.io]-[~]
└─$ip netns exec pod_ns ip a
1: lo: <LOOPBACK> mtu 65536 qdisc noop state DOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
3: veth1@if4: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 7e:60:b2:6e:d8:55 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet 192.168.1.2/24 scope global veth1
       valid_lft forever preferred_lft forever
    inet6 fe80::7c60:b2ff:fe6e:d855/64 scope link
       valid_lft forever preferred_lft forever

在根网络命名空间对 pod_ns 网络命名空间分配IP进行ping 测试

┌──[root@liruilongs.github.io]-[~]
└─$ping -c 3 192.168.1.2
PING 192.168.1.2 (192.168.1.2) 56(84) bytes of data.
64 bytes from 192.168.1.2: icmp_seq=1 ttl=64 time=0.380 ms
64 bytes from 192.168.1.2: icmp_seq=2 ttl=64 time=0.043 ms
64 bytes from 192.168.1.2: icmp_seq=3 ttl=64 time=0.117 ms

--- 192.168.1.2 ping statistics ---
3 packets transmitted,time 2047ms
rtt min/avg/max/mdev = 0.043/0.180/0.380/0.144 ms
┌──[root@liruilongs.github.io]-[~]
└─$

network namespace 实际中的应用

接触过 k8s 的小伙伴通过ip a 命令打印网络接口信息的时候(CNI使用Calico),经常会看到下面的一些接口信息

┌──[root@vms100.liruilongs.github.io]-[~/ansible]
└─$ansible etcd -m shell -a "ip a | grep -A 4 cali"
192.168.26.102 | CHANGED | rc=0 >>
5: cali6f956c2ada9@if4: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 6a:65:54:1a:19:e6 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::6865:54ff:fe1a:19e6/64 scope link
       valid_lft forever preferred_lft forever
192.168.26.100 | CHANGED | rc=0 >>
5: cali0b7f49da20a@if4: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 9e:da:0e:cc:b3:7e brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::9cda:eff:fecc:b37e/64 scope link
       valid_lft forever preferred_lft forever
192.168.26.101 | CHANGED | rc=0 >>
5: calib6f7ddae7e3@if4: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue state UP
    link/ether 1e:e6:16:ae:f0:91 brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::1ce6:16ff:feae:f091/64 scope link
       valid_lft forever preferred_lft forever
┌──[root@vms81.liruilongs.github.io]-[~/ansible]
└─$

实际上,上面的接口信息即为生成的 虚拟以太网对veth pair,也就是刚刚做的Demo,一端在根网络命名空间,一端在 Pod对应的网络命名空间中。从而实现 k8s Pod 之间的通信,当然其中还要涉及工作节点的路由信息。

容器与 host veth pair 的关系

经典容器组网模型就是 veth pair+bridge 的模式。容器中的 eth0 实际上和外面根网络命名空间上的某个 veth 是成对的(pair)关系.(这里的 bridge 主要用于 和因特网通信)

可以通过下面两种方式来获取对应关系

方法一

容器里面看 /sys/class/net/eth0/iflink

┌──[root@liruilongs.github.io]-[/]
└─$ docker exec -it  6471704fd03a sh
/ # cat /sys/class/net/eth0/if
ifalias  ifindex  iflink
/ # cat /sys/class/net/eth0/iflink
95
/ # exit

然后,在主机上遍历 /sys/claas/net 下面的全部目录,查看子目录 ifindex 的值和容器里查出来的 iflink 值相当的 veth 名字,这样就找到了容器和主机的 veth pair 关系。

┌──[root@liruilongs.github.io]-[/]
└─$ grep -c 95 /sys/class/net/*/ifindex | grep 1
/sys/class/net/veth2e08884/ifindex:1
方法二

在目标容器里执行以下命令,获取网卡索引为 94,其中 94 是 eth0 接口的index,95 是和它成对的veth的index。

┌──[root@liruilongs.github.io]-[/]
└─$ docker exec -it  6471704fd03a sh
/ # ip link show eth0
94: eth0@if95: <BROADCAST,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue
    link/ether 02:42:ac:11:00:03 brd ff:ff:ff:ff:ff:ff
/ # exit

通过 95 index 来定位主机上对应的虚拟网卡

┌──[root@liruilongs.github.io]-[/]
└─$ ip link show | grep 95
95: veth2e08884@if94: <BROADCAST,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP mode DEFAULT
┌──[root@liruilongs.github.io]-[/]
└─$

network namespace API 的使用

  1. 创建 namespace 的黑科技:clone 系统调用

用户可以使用 clone()系统调用创建一个 namespace。

  1. 维持 namespace 存在:/proc/PID/ns 目录的奥秘

每个 Linux 进程都拥有一个属于自己的/proc/PID/ns,这个目录下的每个文件都代表一个类型的 namespace。

┌──[root@liruilongs.github.io]-[~]
└─$ls -l /proc/$$/ns
total 0
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 cgroup -> 'cgroup:[4026531835]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 ipc -> 'ipc:[4026531839]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 mnt -> 'mnt:[4026531841]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 net -> 'net:[4026531840]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 pid -> 'pid:[4026531836]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 pid_for_children -> 'pid:[4026531836]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 time -> 'time:[4026531834]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 time_for_children -> 'time:[4026531834]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 user -> 'user:[4026531837]'
lrwxrwxrwx. 1 root root 0 Feb 11 02:27 uts -> 'uts:[4026531838]'
┌──[root@liruilongs.github.io]-[~]
└─$

Linux 内核 3.8 版本以前,/proc/PID/ns 目录下的文件都是硬链接(hard link),而且只有 ipc、net 和 uts 这三个文件,从 Linux 内核 3.8 版本开始,每个文件都是一个特殊的符号链接文件

符号链接的其中一个用途是确定某两个进程是否属于同一个 namespace。如果两个进程在同一个 namespace 中,那么这两个进程/proc/PID/ns 目录下对应符号链接文件的 inode 数字(即上文例子中[]内的数字,例如 4026531839 会是一样的。

/proc/PID/ns 目录下的文件还有一个作用当我们打开这些文件时,只要文件描述符保持 open 状态,对应的 namespace 就会一直存在,哪怕这个 namespace 里的所有进程都终止运行了

  1. 往 namespace setns() 系统调用

Linux 系统调用 setns() 把一个进程加入一个已经存在的 namespace 中。

  1. 帮助进程逃离 namespace:unshare 系统调用

通过 Linux 的 network namespace 技术可以自定义一个独立的网络栈,简单到只有 loopback 设备,复杂到具备系统完整的网络能力,这就使得 network namespace 成为 Linux 网络虚拟化技术的基石——不论是虚拟机还是容器时代。

network namespace 的另一个隔离功能在于,系统管理员一旦禁用 namespace 中的网络设备,即使里面的进程拿到了一些系统特权,也无法和外界通信。

# NETNSNAME 是命名空间的名称,DEVNAME 是要禁用的网络设备的名称。
ip netns exec NETNSNAME ip link set DEVNAME down

最后,网络对安全较为敏感,即使 network namespace 能够提供网络资源隔离的机制,用户还是会结合其他类型的 namespace 一起使用,以提供更好的安全隔离能力。

博文部分内容参考

© 文中涉及参考链接内容版权归原作者所有,如有侵权请告知

原文地址:https://blog.csdn.net/sanhewuyang/article/details/136093974

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


文章浏览阅读8.4k次,点赞8次,收藏7次。SourceCodester Online Tours & Travels Management System pay.php sql injectionLine 16 of pay.php invokes a SQL query built using unvalidated input. This call could allow an attacker to modify the statement’s meaning or to execute arbitrary SQL commands.SQL
文章浏览阅读3.4k次,点赞46次,收藏51次。本文为大家介绍在windwos系统搭建typecho博客+cpolar内网穿透工具将博客发布到公共网络环境,实现远程也可以访问和操作。_windows搭建typecho
文章浏览阅读1.1k次。- php是最优秀, 最原生的模板语言, 替代语法,让php更加的优雅的与html生活在一起 -->请放心, 最终生成的,或者说用户最终看到的,仍然是一个html文档, php代码中的内容不会被泄漏的。-- 将php与html代码混编的时候,大括号很容易造成配对错误,最好杜绝它 -->php标签内部代码由php.exe解释, php标签之外的代码原样输出,仍由web服务器解析。-- 所以php的流程控制语句, 都提供了替代语法,用冒号代替大括号 -->php echo '百变鹏仔'?_利用php将静态页面修改为动态页面
文章浏览阅读1.1k次,点赞18次,收藏15次。整理K8s网络相关笔记博文内容涉及 Linux network namespace 认知以及彼此通信Demo,实际中的应用理解不足小伙伴帮忙指正不必太纠结于当下,也不必太忧虑未来,当你经历过一些事情的时候,眼前的风景已经和从前不一样了。——村上春树。_linux network namespace 多端通信 模式认知
文章浏览阅读1.2k次,点赞22次,收藏19次。此网络模型提供了一个逻辑二层(L2)网络,该网络封装在跨 Kubernetes 集群节点的现有三层(L3)网络拓扑上。使用此模型,可以为容器提供一个隔离的 L2 网络,而无需分发路由。封装网络带来了少量的处理开销以及由于覆盖封装生成 IP header 造成的 IP 包大小增加。封装信息由 Kubernetes worker 之间的 UDP 端口分发,交换如何访问 MAC 地址的网络控制平面信息。此类网络模型中常用的封装是 VXLAN、Internet 协议安全性 (IPSec) 和 IP-in-IP。_k8s网络组件对比
文章浏览阅读1.1k次,点赞14次,收藏19次。当我们谈论网络安全时,我们正在讨论的是保护我们的在线空间,这是我们所有人的共享责任。网络安全涉及保护我们的信息,防止被未经授权的人访问、披露、破坏或修改。
文章浏览阅读1.3w次,点赞3次,收藏7次。尽管您可以通过 ping 命令解析出网站的 IP 地址,但是可能在浏览器中访问时仍然遇到问题,这可能是因为浏览器使用的 DNS 解析结果不同于 ping 命令使用的解析结果。可能是因为您的网络或设备上设置了防火墙,阻止了对特定网站的访问。有些国家或组织可能会对特定的域名进行屏蔽,从而阻止访问相关网站。如果您的网络使用代理服务器进行访问控制,可能会由于代理服务器的配置问题导致无法访问某些网站。即使您的网络和设备一切正常,目标网站本身可能也存在问题,例如服务器故障、维护或过载,导致无法访问。_能ping通打不开网页
文章浏览阅读839次,点赞22次,收藏19次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。
文章浏览阅读2.1k次,点赞31次,收藏22次。基于微信小程序奶茶点餐外卖系统设计与实现(PHP后台+Mysql)可行性分析毕设源代码毕业设计,数据安全和系统稳定性以及团队能力和资源配备方面都具备较好的条件。因此,该项目的可行性较高。:黄菊华老师《Vue.js入门与商城开发实战》《微信小程序商城开发》图书作者,CSDN博客专家,在线教育专家,CSDN钻石讲师;微信小程序作为一种快捷、方便的移动应用形式,成为很多用户点餐外卖的首选。项目的界面和功能都可以定制,包安装运行!项目配有对应开发文档、开题报告、任务书、PPT、论文模版等。
文章浏览阅读1.8k次,点赞52次,收藏38次。本文主要通过对系统的前台系统和后台管理系统进行了功能性需求分析,对系统的安全性和可扩展性进行了非功能性需求分析。在详细的需求分析的基础上,根据系统的功能设计确定了数据库结构,实现完整的代码编写。Lucky+Baby母婴用品网站使用 Dreamweaver、HBuilder代码编辑器、Apache服务器等开发工具,完成了系统的主要模块的页面设计和功能实现。本文展示了首页页面的实现效果图,并通过代码和页面介绍了用户注册功能、商品搜索功能、生成订单和查看我的订单功能、在线付款功能功能的实现过程。
文章浏览阅读1.5k次,点赞45次,收藏40次。本设计主要实现集人性化、高效率、便捷等优点于一身的人事信息管理系统,完成首页、系统用户、通知公告、部门信息、员工薪资、考勤签到、员工请假、招聘信息、应聘信息等功能模块。
文章浏览阅读1k次。该错误通常出现在数据库读取结果集数据时,比如当我们写好SQL语句从数据库读取数据时,本身应该返回结果集,再给结果集中读取数据。解决思路:这种错误一般是因为echo后面输出了一个数组导致的,或者是数组作为字符串进行拼接运算时导致的。该错误直译为:警告:mysqli_fetch_assoc函数期望参数1是mysqli的结果集,但是给了一个布尔值。这种错误是PHP解析器在解析时遇到了语法错误,直译为:解析错误:语法错误,意料之外的...该错误直译为:提示:未定义的索引:username。_array to string conversion in
文章浏览阅读2.7w次。解决http请求报错context deadline exceeded (Client.Timeout exceeded while awaiting headers)_context deadline exceeded (client.timeout exceeded while awaiting headers)
文章浏览阅读1.3k次,点赞26次,收藏24次。复杂网络是一种由大量相互连接的元素(节点或顶点)组成的网络结构,这些连接通常是非常复杂和动态的。这些网络可以在各种领域中发现,包括社交网络、生物学系统、信息技术和交通系统等。_代理建模
文章浏览阅读2.6k次,点赞76次,收藏71次。epoll详解,事件模型,ET/LT模式,并通过三个示例进行代码实现。
文章浏览阅读3.3k次。罗拉ROLA-IP是一家来自纽约的代理IP提供商,由李嘉诚先生投资建设,韩国人工智能、自动驾驶、虚拟现实方面的领军企业World IT Show投资入股,由美国纽约大学IT管理教授团队研究开发,进入中国市场6年多,全世界设有多个分子公司。接下来,我们要检查代理和防火墙的设置,因为在绝大多数情况下,它们是导致这个错误的原因,尤其是当用户使用免费代理时。对网站的访问受阻实际上是一个非常常见的错误,它既可能是由于物理原因(硬件问题)造成的,也可能是由于软件错误引起的。检查代理设置,并确保其正确配置。_无法访问此网站,检查代理服务器和防火墙
文章浏览阅读1.1k次,点赞14次,收藏20次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。_php洗车服务预约管理系统php源码
文章浏览阅读1.1k次。桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。同时,对于桶中元素的排序,选择何种比较排序算法对于性能的影响至关重要。
文章浏览阅读936次,点赞22次,收藏17次。本系统带文档lw万字以上文末可领取本课题的JAVA源码参考。
文章浏览阅读822次,点赞15次,收藏14次。在整个设计过程中,要确定可能的具体解决方案,以实现每一个小的最终目标,对于每一个小目标,我们首先必须了解一些相关的需求分析信息。除了以上作品下面是2023-2024年最新100套计算机专业原创的毕业设计源码+数据库,是近期作品,如果你的题目刚好在下面可以文末领取java源码参考。springboot基于springboot的在线考试系统。springboot基于springboot的商城购物系统。springboot基于微信小程序的智慧校园设计与实现。springboot基于用户的协同过滤算法的话题推荐。