swarm mode 集群内部自带负载均衡,Docker 会在节点间默认创建一个 ingress 网络,通过 ingress LB 可以将容器网络中的容器服务暴露到宿主机网络中,从而被外部请求快速发现,并支持通过服务名或别名的访问方式。
swarm mode 集群支持 healthcheck 进行健康检查,当充当访问入口的某个节点的容器服务出现问题时, ingress LB 会自动路由到其他节点的 active 容器拷贝(repica)上,做到容器服务的自动负载均衡,最终实现集群的高可用。请参考
routing mesh 了解更多。
实现原理
- swarm mode 集群会默认生成一个 ingerss 网络,在用户请求 > 节点 IP: 端口 > ingress > 容器的访问链路中,负责与节点和内部容器间的通讯。其中 ingress 是由 IPVS 实现的,具有负载均衡和名字解析功能。
- Ingress LB 分别在节点 iptables,ingress_sbox 的 iptables 和 IPVS,service 容器的 iptables 处设置相应规则,从而可以在宿主机网络上通过宿主机 IP 和 published 端口来访问容器网络的服务。
您可以使用阿里云负载均衡服务为 swarm mode 集群配置外部负载均衡服务,将外部请求路由到目标 swarm mode 集群,实现公网下的服务发现和负载均衡。原理图如下:
以上图为例,节点 published 端口 > 容器 targeted 端口的具体数据流程如下:
- 宿主机网络通过 Worker 节点 IP 和 service published port 来访问服务。本示例中定义了 --publish 8888:80 ,可以通过 workerIP:8888 访问服务。
- Worker 节点 iptables 中 NAT 表定义规则,对于匹配 published 的宿主机端口(8888)的数据,将其 dstIP 转换成 ingress_sbox 中的 IP。
- 节点上 Ingress_sbox 会设置 mangle 表,将 dst port 为 8888 的数据做标记(fwmark)。通过 IPVS,将标记为 fwmark 的数据包 LB 到各个实际IP中,默认 round-robin 算法,forware 为 VS/NAT 方式。
- Service 的各个容器会将 dst port 为 8888 的数据的 dst port 转换成 80,从而访问到真实的服务。
优势
- 摆脱传统 DNS 轮询的时效性问题,同时可以支持 UDP 等协议, 性能比 DNS 优秀。
- 支持集群内任意节点作为访问入口,服务在任何一台主机的 published 端口都可到达。
编排示例
您可以通过以下两种方式设置端口:
- 可以手动指定未使用端口(-p <PUBLISHED-PORT>:<TARGET-PORT> 或 --publish <PUBLISHED-PORT>:<TARGET-PORT>)。
- 或者不指定,由 Docker swarm 在 30000-32767 中指定一个端口。
[backcolor=transparent]注意:请确保预留 7946 TCP/UDP 用于发现容器网络和 4789 UDP 来使 ingress 网络正常工作。
编排示例如下:
- [backcolor=transparent]version[backcolor=transparent]:[backcolor=transparent] [backcolor=transparent]"3"
- [backcolor=transparent]services[backcolor=transparent]:
- [backcolor=transparent] ngx[backcolor=transparent]:
- [backcolor=transparent] image[backcolor=transparent]:[backcolor=transparent] nginx[backcolor=transparent]:[backcolor=transparent]latest
- [backcolor=transparent] ports[backcolor=transparent]:
- [backcolor=transparent] [backcolor=transparent]-[backcolor=transparent] [backcolor=transparent]8888[backcolor=transparent]:[backcolor=transparent]80
在该示例中, nginx 容器将 80 端口暴露给集群内所有节点的 8888 端口,外部请求可以由所有节点上的 8888 端口自动路由到集群内运行的 nginx 容器。