Docker 1.12版本中将swarm内置到了Docker Engine中,网络部分也发生了一些改进,本文中将深入探讨Docker1.12版本swarm模式下的网络模型。
如下图所示Swarm模式下的集群架构,这是一个典型的master-slave的架构。每个节点都是运行着Docker Engine的Docker主机。一些节点有更高的权限,被称为Manager。下面绿色的节点是worker节点,接收来自manager组的任务指示。
下图Docker Engine的swarm模式下节点是如何工作:
如下图,创建一个有5个节点的swarm集群测试环境。
如果SSH到test-master1的话,可以看到默认的网络拓扑:
每个容器都有一个IP地址,有三种overlay的网络模式:
- Ingress
- docker_gwbridge
- user-defined overlay
Swarm manager使用ingress负载均衡,将需要对外可用的服务暴露给swarm。Swarm manager可以自动给这个服务分配一个PublishedPort ,或者你可以为这个服务配置一个在30000-32767之内的PublishedPort 。实际上,集群内的ingress网络是基于节点端口模式的,每个服务被分配到集群内预留的30000-32000之间的端口。集群内的每个监听这个端口的节点,都可以为那个服务路由流量。这与一个特定的worker节点上运行的服务无关。
特别要注意的是,只有那些暴露端口的服务才需要ingress网络,不对外暴露端口的后端服务,其对应的容器也不会被加到ingress网络中。
外部组件,比如云负载均衡器,可以访问集群中的任意节点,不管这个节点是否运行着服务中的任务。Swarm集群中的所有节点都通过ingress连接到运行的任务实例。因此,ingress遵循节点网络模式,同一个服务在集群的每个节点上都有相同的端口。
『default_gwbridge』网络只能用在非内部的网络环境下,内部的网络可以加上『-internal』的选项。连接到多主机网络的容器会自动连接到docker_gwbridge网络。这种网络模式让容器可以和集群外产生外部连接,并且在每个worker节点上创建。
Docker Engine提供了多种灵活的网络模式,既可以手动创建docker_gwbridge,也可以让daemon自动创建。除非你需要一个在指定子网的docker_gwbridge,可以用以下方式创建:
$docker network create –subnet={Your prefered subnet } -o com.docker.network.bridge.enable_icc=false -o com.docker.network.bridge.name=docker_gwbridge docker_gwbridge.
这是用户指定的容器的overlay网络模式。在下面的例子中,我们会叫它mynet。一个容器可以在多个user-defined overlay网络中。
理论知识介绍得差不多了,下面我们来实践一下:
如下,这个swarm集群中有3个节点,其中1个是master节点,2个是worker节点。
通过下面的代码创建了一个user-defined overlay:
$ sudo docker network create -d overlay mynet
可以在swarm模式下看到新的overlay网络列表,如下:
有一个名为『frontier』的服务,服务中的3个任务分别运行在node 1,node 2和master1上 如下图:
可以分别查看在node-1和node-2下的容器:
同时,我添加了一个新的Node-3,并将其扩展到10个:
现在我们可以看到这些容器在swarm集群内被扩展了。
为了看下overlay网络是如何工作的,我们以第4个节点为目标,并将其加到swarm集群中。
现在节点列表更新如下:
向swarm集群中添加节点时,mynet的overlay网络并不会自动更新:
只有新任务被分配时,overlay网络才会被影响,而且是按需的。
下面我们扩展旧的服务,看下node-4网络布局是否会被mynet网络影响。之前我们有10个副本在运行,分别运行在master1,node1,node2和node4上,一旦我们扩展到20个实例,swarm集群的engine会跨所有节点进行扩展:
现在node-4的网络拓扑如下:
所以,一旦新的任务被指定给这个节点,Overlay网络就会被按需创建。
Swarm节点是自组织(self-organizing)和自修复(self-healing)的,什么意思?只要有节点或容器宕掉,swarm engine就会尝试修复,下面我们来具体看一下。
经过上面的操作之后,我们有以下几个节点:
现在我们让node-4上的容器都宕掉。
一旦node-4上所有容器停止,Docker就会试图在相同的节点上启动4个不同ID的容器。
这就是Docker Swarm Engine的self-healing功能。
现在我们让node-4整个宕掉,node-4上的容器会自动在其它节点上启动。
- Master-1上运行着5个任务;
- Node-1上运行着5个任务;
- Node-2上运行着5个任务;
- Node-3上运行着4个任务;
Docker自动将原node-4上的容器分配给了其它节点。
这个选项让服务可以运行在所有的节点上,你可以在创建服务的时候,加上-mode-global的选项,开启这项功能:
有些情况下,你会想要某些工作负载分离出来,运行在特定的节点上。比如在DockerCon大会上的演讲中,展示了contraints的用法:
假设在myapp:80服务上,有1个manager节点和3个worker节点。当有人想要通过暴露的端口访问myapp:80的时候,运气好的话,会被外部的负载均衡器引流到worker-2,因为worker-2有2个前端容器的副本,随时都可以提供服务;但如果不幸访问myapp:80的请求,被重定向到了没有容器副本的worker-3,就是Routing Mesh技术发挥作用的时候了。worker-3上没有容器的副本,Docker Swarm Engine就会将流量重新路由到有足够副本的worker-2上提供服务。外部的负载均衡器不需要知道容器在哪里运行。Routing Mesh是自动完成这一系列动作的。
总之,容器感知的Routing Mesh就是将流量从node-3重新路由到运行着容器的node-2。Docker Engine在集群内部分配端口,并将端口对应到服务的容器,Routing Mesh会通过为swarm中每个节点暴露一个端口,来保证流量被引到正确的容器上。
评论前必须登录!
注册