负载平衡是现代分布式应用程序的主要要求。 1.12中引入的Docker Swarm模式具有本机内部和外部负载平衡功能,这些功能同时利用了iptables和ipvs,这是Linux内核内部的传输层负载平衡。
服务发现
Docker使用嵌入式DNS为在单个Docker Engine上运行的容器和在Docker Swarm中运行的任务提供服务发现。 Docker Engine有一个内部DNS服务器,可为用户定义的网桥,覆盖和MACVLAN网络中主机上的所有容器提供名称解析。每个Docker容器(或Swarm模式下的任务)都有一个DNS解析器,可将DNS查询转发到充当DNS服务器的Docker引擎。然后,Docker Engine检查DNS查询是否属于请求容器所属的网络上的容器或服务。如果是,则Docker Engine在其键值存储中查找与容器,任务或服务的名称匹配的IP地址,并将该IP或服务虚拟IP(VIP)返回给请求者。
服务发现是网络范围的,这意味着只有同一网络上的容器或任务才能使用嵌入式DNS功能。不在同一网络上的容器无法解析彼此的地址。此外,仅在特定网络上具有容器或任务的节点会存储该网络的DNS条目。这样可以提高安全性和性能。
如果目标容器或服务与源容器不在同一个网络上,则Docker Engine将DNS查询转发到配置的默认DNS服务器。
在此示例中,有两个容器的服务称为myservice。 在同一网络上存在第二个服务(client)。 client对docker.com和myservice执行两个curl操作:
DNS查询由客户端针对docker.com和myservice发起。
- 容器的内置解析器拦截127.0.0.11:53上的DNS查询,并将其发送到Docker Engine的DNS服务器。
- myservice解析为该服务的虚拟IP(VIP),该IP在内部对各个任务IP地址进行负载均衡。 容器名称也将被解析,直接解析为其IP地址。
- docker.com作为mynet网络中的服务名称不存在,因此该请求将转发到配置的默认DNS服务器。
内部负载平衡
在Docker Swarm集群中创建服务时,会自动为它们分配一个虚拟IP(VIP),该IP是服务网络的一部分。 解析服务名称时,将返回VIP。 到该VIP的流量将自动通过覆盖网络发送到该服务的所有正常任务,避免了任何客户端负载平衡,因为只有单个IP返回给客户端。 Docker负责路由,并在正常运行的服务任务之间平均分配流量。
下面演示一个如何查看虚拟ip
# Create an overlay network called mynet
$ docker network create -d overlay mynet
a59umzkdj2r0ua7x8jxd84dhr
# Create myservice with 2 replicas as part of that network
$ docker service create --network mynet --name myservice --replicas 2 busybox ping localhost
8t5r8cr0f0h6k2c3k7ih4l6f5
# See the VIP that was created for that service
$ docker service inspect myservice
...
"VirtualIPs": [
{
"NetworkID": "a59umzkdj2r0ua7x8jxd84dhr",
"Addr": "10.0.0.3/24"
},
DNS循环(DNS RR)负载平衡是服务的一种负载平衡选项(使用--endpoint-mode配置)。 Docker DNS服务器以循环方式将服务名称解析为单个容器IP。
外部负载平衡(Docker路由网格)
在创建或更新服务时,可以使用--publish标志在外部公开服务。以Docker Swarm模式发布端口意味着集群中的每个节点都将监听该端口。但是,如果服务的任务不在该端口上正在侦听的节点上怎么办?
这是路由网格发挥作用的地方。路由网格是Docker 1.12中引入的一项功能,该功能结合了ipvs和iptables来创建功能强大的集群范围传输层(L4)负载均衡器。允许所有Swarm节点接受连接。当任何Swarm节点接收到发往正在运行的服务的已发布TCP / UDP端口的流量时,它将使用称为入口(ingress)网络将其转发到服务的VIP。入口(ingress)网络的行为与其他覆盖网络相似,但其唯一目的是将流量从外部客户端传输到群集服务,基于VIP的内部负载平衡。
启动服务后,将其映射到任何或所有Docker Swarm节点,无需担心容器在何处运行,因为集群中的所有节点看起来都具有路由网格路由功能。
#Create a service with two replicas and export port 8000 on the cluster
$ docker service create --name app --replicas 2 --network appnet -p 8000:80 nginx
- 创建具有两个副本的服务,并将其从外部映射到端口8000。
- 路由网格在群集中的每个主机上公开端口8000。
- 前往该应用的流量可以访问任何主机。 在这种情况下,外部LB将流量发送到没有服务副本的主机。
- 内核的IPVS负载平衡器将入口(ingress)覆盖网络上的流量重定向到正常的服务副本。
ipvs
ipvs称之为IP 虚拟服务器 (IP Virtual Server,简写为IPVS)。是运行在 LVS 下的提供负载平衡功能的一种技术。 LVS (Linux Virtual Server),虚拟服务器是一个高度可扩展性和高可用性的服务器,建立在一个集群的服务器中。服务器集群的架构对用户是完全透明的,并且用户使用起来感觉它只有一个高性能 虚拟服务器 。
IPVS基本上是一种高效的Layer-4交换机,它提供 负载平衡 的功能。当一个TCP连接的初始SYN报文到达时,IPVS就选择一台服务器,将报文转发给它。此后通过查发报文的IP和TCP报文头地址,保证此连接的后继报文被转发到相同的服务器。这样,IPVS不用检查到请求的内容再选择服务器,这就要求后端的服务器组是提供相同的服务,不管请求被送到哪一台服务器,返回结果都应该是一样的
IPVS是LVS的关键,因为LVS的IP负载平衡技术就是通过IPVS模块来实现的,IPVS是LVS集群系统的核心软件,它的主要作用是:安装在Director Server上,同时>在Director Server上虚拟出一个IP地址,用户必须通过这个虚拟的IP地址访问服务。这个虚拟IP一般称为LVS的VIP,即Virtual IP。访问的请求首先经过VIP到达负载调度器,然>后由负载调度器从Real Server列表中选取一个服务节点响应用户的请求。
ingress网络
Docker Swarm 支持两种服务发布模式,两种模式均保证服务从集群外可访问。
- Ingress模式(默认)。
- Host模式。
通过 Ingress 模式发布的服务,可以保证从 Swarm 集群内任一节点(即使没有运行服务的副本)都能访问该服务;以 Host 模式发布的服务只能通过运行服务副本的节点来访问。
来源:oschina
链接:https://my.oschina.net/woniuyi/blog/4950812