Linux network namespace

如果你熟悉docker的namespace隔离机制,你应该知道docker的network也是通过 namespace隔离的

要了解kubernetes的网络原理,不得不提到 linux 的network namespace

Linux的 namespace 的作用是 隔离内核资源,命名空间会给其中的进程造成两个错觉

1. 它是系统内唯一的进程

2. 它独享系统的所有资源

network namespace是从 2.6 开始引入的,作用是隔离 Linux 系统的设备,ip 地址、端口、路由表 和 防火墙规则等网络资源

创建一个名为 netns1 的 新命名空间

sudo ip netns add netns1

当 ip 命令 创建了一个 新命名空间 之后,系统会在 /var/run/netns 目录下生成一个新的挂载点

挂载点的作用在于一方面是为了方便 命名空间管理,另一个方面是使 命名空间  可以在没有进程运行时也能继续存在

删除命令并不会直接删除这个命名空间,它只是移除了挂载点,这样只要命名空间中仍然有进程运行,它就会一直存在

当 namespace 中的进程 涉及到网络通信时,它就需要一个虚拟网络设备 ,一个全新的 namespace 会附带创建一个 本地回环地址,上面的截屏中我们已经看到了。

不过需要注意的是,默认创建的网卡并没有默认启动

sudo ip netns exec netns1 ip link set dev lo up

仅有一个回环网卡是无法与外部通信的,之前在旧版本的 docker 上我使用过 veth pair,这里是一样的套路

veth pair 总是成对出现的,报文从一端进去,从另一端出来

这里我在宿主机上 创建两个端点, veth_left 和 veth_right

然后把 veth_left 绑定到 netns1 , 把 veth_right 绑定到(留给,默认就是在宿主机上创建的)当前宿主机

lizhe@ubuntu:~$ sudo ip link add veth_left type veth peer name veth_right
lizhe@ubuntu:~$ sudo ip link set veth_left netns netns1
lizhe@ubuntu:~$ 
lizhe@ubuntu:~$ sudo ip netns exec netns1 ifconfig veth_left 10.1.1.1/24 up
lizhe@ubuntu:~$ sudo ifconfig veth_right 10.1.1.2/24 up

ping 10.1.1.1

sudo ip netns exec netns1 ping 10.1.1.2

命名空间内 和 命名空间外 都可以互相ping通

之前我们说 命名空间 的作用是 隔离

那么路由表 和 防火墙 呢

sudo ip netns exec netns1 route

sudo ip netns exec netns1 iptables -L

我们试着使用 NAT 让 netns1 可以访问外网

开启 linux kernel ip forwarding

sudo sysctl net.ipv4.ip_forward=1 

将 netns1 的默认路由设为 veth_right ( 宿主机的veth ) 的 IP 地址

sudo ip netns exec netns1 route add default gw 10.1.1.2

确认一下网卡名称,这里是 ens33

配置 SNAT,将从 myspace 发出的网络包的 soruce IP address 替换为 ens33 的 IP 地址

sudo iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o ens33 -j MASQUERADE

在默认 FORWARD 规则为 DROP 时显式地允许 veth1 和 eth0 之间的 forwarding

lizhe@ubuntu:~$ sudo iptables -t filter -A FORWARD -i eth0 -o veth_right -j ACCEPT
lizhe@ubuntu:~$ sudo iptables -t filter -A FORWARD -o eth0 -i veth_right -j ACCEPT
sudo iptables -t nat -A POSTROUTING -s 10.1.1.0/24 -o ens33 -j MASQUERADE

最后我们来检查一下 route 并确认结果

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

在内核版本3.8之前,只包含 ipc、net 和 uts 的硬链接

在内核版本3.8之后,每个文件都是一个特殊的符号链接文件。

这些符号链接的其中一个用途是 确定两个进程是否同属于 同一个 namespace,
如果两个进程在同一个namespace中,那么这两个进程的 /proc/PID/ns 目录下对应的符号链接文件的 inode, 就是 【】 中的数字,将会是一样的。

另外一个作用是,通过文件描述符,在不需要进程存在的情况下也能保持 namespace 存在。

Send a Message