滴普技术荟 - 云原生基座 OpenKube 开放容器实践(四):linux 模拟 pod 并配置上外网

前言
这篇文章我们将完成以下几件事情:
用 docker 模拟一个 POD
将这个 POD 和主机连接起来,在主机中能访问 POD 的网站
让这个 POD 能上外网
模拟一个 POD
POD 是一个 K8S 的逻辑概念,POD 里会有一个或多个容器,他们之间共享一个网络命名空间,可以用 localhost 相互访问,下面我们将脱离开 K8S,直接用 docker 来模拟这种情况:
首先创建一个 network=none 的容器:

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

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

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

也可以这样验证:

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

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

来操作这个 Pod 的网络了,接下来的事情就是前面已经完成过的内容了,这里直接把命令列出,不再一一解释了。
POD 连接节点
接下来,我们会在主机的网络命名空间创建一对 veth 网卡对,然后把一端转到 POD 的网络中,并且设置 IP 地址:

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

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

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

然后要加两条 iptables 规则:

第一条是说放过所有转发的数据包,第二条是说为来源为 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 在这里就很关键了。
欢迎关注滴普科技官网http://datasink-sensors.deepexi.top/t/Fa
作者:刘海峰,IT 行业资深码农,从事.net/java/go 语言开发十余年,长期关注 springcloud/k8s/linux 网络相关的技术,现为滴普科技容器产品首席架构师。
了解更多详情请登录:https://www.deepexi.com/
评论