Docker1.12版本swarm模式下的网络模型

Docker 1.12版本中将swarm内置到了Docker Engine中,网络部分也发生了一些改进,本文中将深入探讨Docker1.12版本swarm模式下的网络模型。

如下图所示Swarm模式下的集群架构,这是一个典型的master-slave的架构。每个节点都是运行着Docker Engine的Docker主机。一些节点有更高的权限,被称为Manager。下面绿色的节点是worker节点,接收来自manager组的任务指示。

docker7621

下图Docker Engine的swarm模式下节点是如何工作:

docker7622

如下图,创建一个有5个节点的swarm集群测试环境。

docker7623

如果SSH到test-master1的话,可以看到默认的网络拓扑:

docker7624

每个容器都有一个IP地址,有三种overlay的网络模式:

  1. Ingress
  2. docker_gwbridge
  3. user-defined overlay
Ingress Networking

Swarm manager使用ingress负载均衡,将需要对外可用的服务暴露给swarm。Swarm manager可以自动给这个服务分配一个PublishedPort ,或者你可以为这个服务配置一个在30000-32767之内的PublishedPort 。实际上,集群内的ingress网络是基于节点端口模式的,每个服务被分配到集群内预留的30000-32000之间的端口。集群内的每个监听这个端口的节点,都可以为那个服务路由流量。这与一个特定的worker节点上运行的服务无关。

特别要注意的是,只有那些暴露端口的服务才需要ingress网络,不对外暴露端口的后端服务,其对应的容器也不会被加到ingress网络中。

外部组件,比如云负载均衡器,可以访问集群中的任意节点,不管这个节点是否运行着服务中的任务。Swarm集群中的所有节点都通过ingress连接到运行的任务实例。因此,ingress遵循节点网络模式,同一个服务在集群的每个节点上都有相同的端口。

docker_gwbridge

『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.

User-defined Overlay

这是用户指定的容器的overlay网络模式。在下面的例子中,我们会叫它mynet。一个容器可以在多个user-defined overlay网络中。

理论知识介绍得差不多了,下面我们来实践一下:

如下,这个swarm集群中有3个节点,其中1个是master节点,2个是worker节点。

docker7625

通过下面的代码创建了一个user-defined overlay:

$ sudo docker network create -d overlay mynet

可以在swarm模式下看到新的overlay网络列表,如下:

docker7626

有一个名为『frontier』的服务,服务中的3个任务分别运行在node 1,node 2和master1上 如下图:

docker7627

可以分别查看在node-1和node-2下的容器:

docker7628

同时,我添加了一个新的Node-3,并将其扩展到10个:

docker7629

现在我们可以看到这些容器在swarm集群内被扩展了。

为了看下overlay网络是如何工作的,我们以第4个节点为目标,并将其加到swarm集群中。

docker7630

现在节点列表更新如下:

docker7631

向swarm集群中添加节点时,mynet的overlay网络并不会自动更新:

docker7632

只有新任务被分配时,overlay网络才会被影响,而且是按需的。

下面我们扩展旧的服务,看下node-4网络布局是否会被mynet网络影响。之前我们有10个副本在运行,分别运行在master1,node1,node2和node4上,一旦我们扩展到20个实例,swarm集群的engine会跨所有节点进行扩展:

docker7633

现在node-4的网络拓扑如下:

docker7634
所以,一旦新的任务被指定给这个节点,Overlay网络就会被按需创建。

Self-Healing

Swarm节点是自组织(self-organizing)和自修复(self-healing)的,什么意思?只要有节点或容器宕掉,swarm engine就会尝试修复,下面我们来具体看一下。

经过上面的操作之后,我们有以下几个节点:

  • Master-1上运行着4个任务;
  • Node-1上运行着4个任务;
  • Node-2上运行着4个任务;
  • Node-3上运行着4个任务;
  • Node-4上运行着4个实例;

现在我们让node-4上的容器都宕掉。

docker7635

一旦node-4上所有容器停止,Docker就会试图在相同的节点上启动4个不同ID的容器。

docker7636
这就是Docker Swarm Engine的self-healing功能。

Self-Organizing

现在我们让node-4整个宕掉,node-4上的容器会自动在其它节点上启动。

docker7637

  • Master-1上运行着5个任务;
  • Node-1上运行着5个任务;
  • Node-2上运行着5个任务;
  • Node-3上运行着4个任务;

Docker自动将原node-4上的容器分配给了其它节点。

Global Services

这个选项让服务可以运行在所有的节点上,你可以在创建服务的时候,加上-mode-global的选项,开启这项功能:

docker7638

Constraints

有些情况下,你会想要某些工作负载分离出来,运行在特定的节点上。比如在DockerCon大会上的演讲中,展示了contraints的用法:

docker7639

Routing Mesh

docker7640

假设在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中每个节点暴露一个端口,来保证流量被引到正确的容器上。

K8S中文社区微信公众号
分享到:更多 ()

评论 抢沙发

评论前必须登录!