如果你熟悉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 存在。