­

linux模拟pod并配置上外网

前言

 

这篇文章我们将完成以下几件事情:

 

用docker模拟一个POD

将这个POD和主机连接起来,在主机中能访问POD的网站

让这个POD能上外网

 

 

模拟一个POD

 

POD是一个K8S的逻辑概念,POD里会有一个或多个容器,他们之间共享一个网络命名空间,可以用localhost相互访问,下面我们将脱离开K8S,直接用docker来模拟这种情况:
首先创建一个network=none的容器:

 

1.jpg

 

这时候pause容器会新建一个网络命名空间,但不会加入docker0网桥中,我们用下面的命令来查看:

 

2.jpg

 

我们再运行一个nginx容器,加入上面的pause容器的网络命名空间,命令如下:

 

3.jpg

 

这时候我们试一下在pause容器中用localhost访问nginx:

 

4.jpg

 

也可以这样验证:

 

5.jpg

 

把容器的网络命名空间映射出来,让我们用ip netns可以更方便地操作到:

 

6.jpg

 

好了,到这一步为止,我们已经把一个pause容器模拟出来了,而且已经加了一个nginx在这个pause容器的网络命名空间中,把这个网络命名空间挂到了/var/run/netns/ns99下面,我们现在可以用:

 

7.jpg

 

来操作这个Pod的网络了,接下来的事情就是前面已经完成过的内容了,这里直接把命令列出,不再一一解释了。

 

POD连接节点

 

接下来,我们会在主机的网络命名空间创建一对veth网卡对,然后把一端转到POD的网络中,并且设置IP地址:

 

8.jpg

 

接下来进入pod中配置默认网关和邻居表:

 

9.jpg

 

这时候退出来主机的网络空间中,然后试着curl 10.2.2.4

 

10.jpg

 

已经成功了。

 

POD连接外网

 

现在POD已经连到了主机上,我们现在要把主机当成NAT网关来上外网,首先要开启主机的转发功能

 

11.jpg

 

然后要加两条iptables规则:

 

12.jpg

 

第一条是说放过所有转发的数据包,第二条是说为来源为10.2.2.4的数据进行SNAT,做完这两步后,再进去POD中PING 8.8.8.8已经通了。

 

为什么加了个snat,就能正常出外网了呢?实际上,不加snat,流量也能正常出的,关键是,回不来

 

仔细想一下,源地址为10.2.2.4,目标为8.8.8.8,在主机出外网的出口上肯定要做一次nat,假设主机所在网络的出口的ip是7.7.7.7,那么从7.7.7.7到8.8.8.8是没的问题的,从8.8.8.8回7.7.7.7也是没有问题的,关键是7.7.7.7的这个出口路由上再要把包再回给10.2.2.4就有问题了,因为这个ip是我们在主机上虚拟出来的,除了这台主机外其它人根本不认识,所以snat在这里就很关键了。

 

作者:刘海峰,IT行业资深码农,从事.net/Java/go语言开发十余年,长期关注springcloud/k8s/linux网络相关的技术,现为滴普科技容器产品首席架构师。

 

了解更多详情请登录://www.deepexi.com/