很蛋疼,我在上一篇博文里写到docker的overlay网络解决了以前的一些问题,但是实际上看起来它并没有解决任何问题。最值得吐槽的一点就是,端口的publish仍然是由dockerd这个用户空间daemon监听然后转发到容器内。
还是跟几年前一样在用户空间做端口转发,性能是真的差,跟这个的overhead相比什么用udp封装以太帧这种奇葩做法简直是小儿科(vxlan,带来约50%吞吐性能下降),而最严重的缺陷就是容器里不可能得到原始连接的套接字。#25526
dockerd再通过一个叫ingress网络接口把连接代理进容器的overlay网络,这个ingress网络是个特殊的用做路由的overlay网络,swarm节点和service在里面都占据ip。最大的槽点其实就在ingress里用了IPVS做loadbalancer(可以用docker service inspect看到一个service在ingress层和overlay层的virtual-ip分别是什么),那么为什么不直接在宿主机里用IPVS在内核空间做端口转发,非要在用户空间里倒腾几遍?
所以我当初一直吐槽说docker只适合拿来跑http服务器。
完全可以使用传统网桥和虚拟交换机连接容器与宿主机物理网络(或者也可以保留overlay,毕竟overlay保证了物理网络与容器网络的严格隔离),容器里面绑定每一个swarm节点对应的网桥或者overlay虚拟网卡ip作为virtaul-ip,用iproute-rule分别设置路由表做multi-gateway,然后宿主机上用IPVS直接做DNAT转发,这样实现出来行为与现在的overlay+ingress完全一样,可以做到连接任意一个swarm节点等于连接到同一个service。
——没有傻逼的用户空间端口转发,没有傻逼的获取不到原始连接套接字。
docker一直被称为devops里程碑的工具,但是从这点看出来docker的核心developer可能一点网络相关的op经验都没有。
(client_conn -> host-public-eth-> dockerd(userspace-proxy) -> ingress_network -> overlay-network(eth frame over udp) -> container)