overlay网络
overlay网络驱动程序会在多个docker守护程序(即多个主机上的docker守护程序)之间创建分布式网络。该网络(overlays)位于特定于主机的网络之上,允许连接到它的容器(包括swarm群集服务容器)安全地进行通信。Docker透明地正确处理到达和来自Docker守护程序主机的每个数据包,并正确的路由到目标容器
初始化swarm或将Docker主机加入现有swarm时,会在该Docker主机上创建两个新网络:
- 名称为ingress的overlay网络,处理与swarm集群服务相关的控制和数据流量。swarm群组服务并不会将其连接到用户定义的overlay网络时,而是连接到默认的ingress网络,若要连接到用户自定义的overlay网络需要使用--network指定(但创建该用户自定义的overlay网络时必须使用--attachable选项)。
- 名为docker_gwbridge的桥接网络,它将参与到该swarm群集的各个Docker守护程序连接连接起来。
可以使用docker network create创建用户定义overlay网络,服务或容器一次可以连接到多个网络,服务或容器只能通过它们各自连接的网络进行通信。
创建overlay网络
先决条件:
- 使用overlay网络的Docker守护程序的防火墙规则
需要打开以下端口以放行来往于overlay网络上的每个Docker主机的流量:
![](/qrcode.jpg)
- 用于swarm集群管理通信的TCP端口2377(仅manager上)
- TCP和UDP端口7946,用于节点之间的通信(manager和worker上)
- UDP端口4789,用于overlay网络流量(manager和worker上)
- 在创建overlay网络之前,需要使用docker swarm init将Docker守护程序初始化为swarm manager,或者使用docker swarm join将其连接到现有的swarm。这两个操作都会创建默认ingress overlay网络,该overlay网络默认情况下由swarm群组服务使用。即使从未计划使用swarm群组服务,也需要执行此操作。之后,可以创建其他用户定义的overlay网络
创建用户自定义的用于swarm服务的overlay网络,使用如下命令:
docker network create -d overlay my-overlay
创建可由swarm群集服务或独立容器用于与在其他Docker守护程序上运行的其他独立容器通信的overlay网络,请添加--attachable标志:
docker network create -d overlay --attachable my-attachable-overlay
可以指定IP地址范围,子网,网关和其他选项
自定义默认ingress网络
大多数用户从不需要配置ingress网络,但Docker 17.05及更高版本允许自定义。如果自动选择的子网与网络上已存在的子网冲突,或需要自定义其他底层网络设置(如MTU),则此功能非常有用。
自定义ingress网络涉及删除和重新创建它,在swarm中,需要在创建任何服务之前完成。如果具有发布端口的现有服务,则在删除ingress网络之前需要删除这些服务
在删除默认的ingress网络后,无发布端口的现有服务继续运行,但不是负载平衡的,而发布端口的服务会受到影响,例如发布端口80的WordPress服务。
1、使用docker network inspect ingress检查ingress网络,并删除其容器连接到它的任何服务。这些是发布端口的服务,例如发布端口80的WordPress服务,如果未停止所有此类服务,则下一步失败。
2、删除现有ingress网络:
$ docker network rm ingress
WARNING! Before removing the routing-mesh network, make sure all the nodes in your swarm run the same docker engine version. Otherwise, removal may not be effective and functionality of newly created ingress networks will be impaired.
Are you sure you want to continue? [y/N]
3、使用--ingress选项创建新的覆盖网络,以及要设置的自定义选项
此示例将MTU设置为1200,将子网设置为10.11.0.0/16,并将网关设置为10.11.0.2。
$ docker network create \
--driver overlay \
--ingress \
--subnet=10.11.0.0/16 \
--gateway=10.11.0.2 \
--opt com.docker.network.driver.mtu=1200 \
my-ingress
注意:
可以将ingress网络命名为其他名称,但只能拥有一个(ingress属性的网络),尝试创建第二个失败(--ingress选项创建swarm专用的路由网格,只能有一个)
4、重新启动在第一步中停止的服务
自定义docker_gwbridge接口
docker_gwbridge是一个虚拟网桥,将overlay网络(包括ingress网络)连接到单个Docker守护程序的物理网络
Docker初始化swarm或将Docker主机加入swarm时会自动创建该网桥(master和node都会创建),但它不是Docker设备,它存在于Docker主机的内核中(软桥)。
如果需要自定义该网桥设置,则必须在将Docker主机加入swarm群组之前或从群集中临时删除主机之后,执行下面的操作
- 停止Docker
- 删除现有docker_gwbridge
sudo ip link set docker_gwbridge down
sudo ip link del dev docker_gwbridge
- 启动Docker,不要加入或初始化swarm
- 使用docker network create命令自定义创建docker_gwbridge桥
此示例使用子网10.11.0.0/16
$ docker network create \
--subnet 10.11.0.0/16 \
--opt com.docker.network.bridge.name=docker_gwbridge \
--opt com.docker.network.bridge.enable_icc=false \
--opt com.docker.network.bridge.enable_ip_masquerade=true \
docker_gwbridge
- 初始化或加入群。由于桥已经存在,Docker不会使用自动设置再次创建它,而是使用前面创建好的。
-o,--opt可使用的选项有:
Option |
Equivalent |
Description |
com.docker.network.bridge.name |
- |
bridge name to be used when creating the Linux bridge |
com.docker.network.bridge.enable_ip_masquerade |
--ip-masq |
Enable IP masquerading |
com.docker.network.bridge.enable_icc |
--icc |
Enable or Disable Inter Container Connectivity |
com.docker.network.bridge.host_binding_ipv4 |
--ip |
Default IP when binding container ports |
com.docker.network.driver.mtu |
--mtu |
Set the containers network MTU |
在overlay网络上发布端口
连接到同一overlay网络的群集服务有效地将所有端口相互暴露(类似自定义网桥)。对于可在服务外部访问的端口,当使用docker service create或docker service update指令时,必须使用-p或--publish标记发布该端口。
支持遗留的冒号分隔语法和较新的逗号分隔语法(首选)
标志值 |
描述 |
-p 8080:80或-p published = 8080,target = 80 |
将服务上的TCP 80端口映射到路由网格上的8080端口。 |
-p 8080:80/udp或-p published = 8080,target = 80,protocol = udp |
将服务上的UDP 80端口映射到路由网格上的8080端口。 |
-p 8080:80/tcp -p 8080:80/udp或-p published = 8080,target = 80,protocol = tcp -p published = 8080,target = 80,protocol = udp |
将服务上的TCP 80端口映射到路由网格上的TCP8080端口,并将服务上的UDP 80端口映射到路由网格上的UDP8080端口。 |
绕过swarm群集服务的路由网格
默认情况下,发布端口的swarm服务使用路由网格来实现。当连接到任何swarm节点上的已发布端口(无论该节点是否正在运行给定服务)时,请求将被透明地重定向到正在运行该服务的worker节点上。实际上,Docker充当swarm群服务的负载均衡器。使用路由网格的服务以虚拟IP(VIP)模式运行。
即使在每个节点上运行的服务(通过--global选项)也使用路由网格,使用路由网格时,无法保证哪个Docker节点为客户端请求提供服务(肯定是集群中的某一个node,但不能确定是哪个)。
要绕过路由网格,可以使用DNS循环(DNSRR)模式启动服务,方法是将--endpoint-mode标志设置为dnsrr(docker service create --help)。但必须在服务前运行自己的负载均衡器(即不使用docker作为负载均衡器,例如自己配置的Haproxy、lvs等)。Docker主机上的服务名称的DNS查询返回运行该服务的节点的IP地址列表。配置负载均衡器以使用此列表,并平衡节点之间的流量。
单独的控制和数据流量
默认情况下,与swarm群组管理相关的控制流量以及进出应用程序的流量都在同一网络上运行,尽管swarm群集控制流量已加密。可以将Docker配置为使用单独的网络接口来处理两种不同类型的流量。当初始化或加入swarm时(docker swarm init --help),分别指定--advertise-addr(集群间管理、通信流量通道)和--datapath-addr(外部访问服务数据流量通道),必须为加入群集的每个节点执行此操作
将独立容器连接到overlay网络
ingress网络被创建且无--attachable标志,这意味着只有swarm服务可以使用它,而独立的容器不能使用。可以将独立容器连接到使用--attachable选项创建的用户定义的overlay网络。
这使得在不同Docker守护程序上运行的独立容器能够进行通信,而无需在各个Docker守护程序主机上设置路由。
使用host网络
如果容器使用host网络驱动程序,则该容器的网络堆栈不会与Docker宿主机隔离
例如,如果运行绑定到80端口的容器并使用host网络,则容器的应用程序将在主机IP地址的端口80上可用。
host网络驱动程序仅适用于Linux主机,不支持Docker for Mac,Docker for Windows或Docker EE for Windows Server。
在Docker 17.06及更高版本中,还可以通过传递--network host选项给docker container create命令,将host网络用于swarm群组服务。在这种情况下,控制流量(与管理swarm群集和服务相关的流量)仍然通过overlay网络发送,但各个swarm群集服务容器使用Docker守护程序的宿主机网络和端口发送数据,这会产生一些额外的限制(如,如果服务容器绑定到端口80,则只有一个服务容器可以在给定的swarm节点上运行)
如果容器或服务未发布端口,则主机网络无效
Macvlan网络
某些应用程序,尤其是遗留应用程序或监视网络流量的应用程序,希望直接连接到物理网络。在这种情况下,可以使用macvlan网络驱动程序为每个容器的虚拟网络接口分配MAC地址,使其看起来像是直接连接到物理网络的物理网络接口。
在这种情况下,需要在Docker主机上指定一个物理接口,用于Macvlan,及Macvlan的子网和网关。甚至可以使用不同的物理网络接口隔离Macvlan网络。
记住以下事项:
- 由于IP地址耗尽或“VLAN传播”,很容易无意中损坏网络,在这种情况下,网络中有大量不同的唯一MAC地址。
- 网络设备需要能够处理“混杂模式”,其中一个物理接口可以分配多个MAC地址。
- 如果应用程序可以使用桥接(在单个Docker主机上)或overlay(跨多个Docker主机进行通信),那么从长远来看,这些解决方案可能会更好(不推荐使用macvlan网络)。
创建一个macvlan网络
创建Macvlan网络时,它可以处于桥接模式或802.1q trunk桥接模式
- 在桥接模式下,Macvlan流量通过宿主机上的物理设备。
- 在802.1q trunk桥接模式下,流量通过Docker在运行中创建的802.1q子接口。这使得可以在更细粒度的级别上控制路由和筛选。
1、桥接模式
要创建与给定物理网络接口桥接的Macvlan网络,请使用docker network create命令的--driver macvlan选项。还需要指定parent,这是流量将在Docker宿主机上实际通过的接口eth0。
$ docker network create -d macvlan \
--subnet=172.16.86.0/24 \
--gateway=172.16.86.1 \
-o parent=eth0 \
pub_net
如果需要排除在Macvlan网络中正在使用的IP地址,例如当已给定的IP地址正在使用,使用--aux-addresses选项:
$ docker network create -d macvlan \
--subnet=192.168.32.0/24 \
--ip-range=192.168.32.128/25 \
--gateway=192.168.32.254 \
--aux-address="my-router=192.168.32.129" \
-o parent=eth0 \
macnet32
2、802.1q trunk桥接模式
如果指定parent包含点的接口名称,例如eth0.50,Docker将其解释为eth0的子接口,并自动创建子接口。
$ docker network create -d macvlan \
--subnet=192.168.50.0/24 \
--gateway=192.168.50.1 \
-o parent=eth0.50 \
macvlan50
使用ipvlan而不是macvlan
在上面的示例中,使用的是L3网桥。可以使用ipvlan,以获得L2桥接。
指定-o ipvlan_mode=l2
$ docker network create -d ipvlan \
--subnet=192.168.210.0/24 \
--subnet=192.168.212.0/24 \
--gateway=192.168.210.254 \
--gateway=192.168.212.254 \
-o ipvlan_mode=l2 \
ipvlan210
使用IPv6
如果已将Docker守护程序配置为允许IPv6,则可以使用IPv4/IPv6双栈Macvlan网络。
$ docker network create -d macvlan \
--subnet=192.168.216.0/24 --subnet=192.168.218.0/24 \
--gateway=192.168.216.1 --gateway=192.168.218.1 \
--subnet=2001:db8:abc8::/64 --gateway=2001:db8:abc8::10 \
-o parent=eth0.218 \
-o macvlan_mode=bridge \
macvlan216
禁用容器的网络连接(即使用none类型网络)
如果要完全禁用容器上的网络堆栈,可以在启动容器时使用--network none选项,这样容器内仅创建一个环回设备lo。
以下示例说明了这一点。
1、创建容器:
$ docker run --rm -dit \
--network none \
--name no-net-alpine \
alpine:latest \
ash
2、通过在容器中执行一些常见的网络命令来检查容器的网络堆栈。请注意,没有eth0创建。
docker exec no-net-alpine ip link show
docker exec no-net-alpine ip route #命令返回空,因为没有路由表
网络指南
独立Docker容器的网络连接
1、默认桥接网络docker0
在此示例中,在同一个Docker主机上启动两个不同的alpine容器,并进行一些测试以了解它们如何相互通信。
1)打开终端窗口。在执行任何其他操作之前列出当前网络。如果从未在此Docker守护程序上添加网络或初始化swarm群组,应该看到以下内容(网络ID会有所不同):
$ docker network ls
NETWORK ID NAME DRIVER SCOPE
17e324f45964 bridge bridge local
6ed54d316334 host host local
7092879f2cc8 none null local
bridge列出了默认网络以及host和none
host(用于启动直接连接到Docker守护程序宿主机的网络堆栈的容器)和none(用于启动没有网络设备的容器)不是完全成熟的网络
2) 启动两个alpine容器运行ash shell,由于未指定任何--network标志,因此容器将连接到默认bridge网络。
docker run -dit --name alpine1 alpine ash
docker run -dit --name alpine2 alpine ash
注意:ash是alpine镜像中的一个shell
检查两个容器是否实际启动:
3)检查bridge网络以查看连接到它的容器
docker network inspect bridge
4)容器在后台运行。使用docker attach命令连接到alpine1(从已经attach的容器中分离出来使用快捷键ctrl+p+q,使用ctrl+d会导致容器以外退出而挂掉)
$ docker attach alpine1
/ #
提示符更改为#表示您是容器中的root用户,使用ip a命令显示alpine1容器内的网络接口:
# ip a
5)从alpine1内部,确保可以通过ping连接到互联网google.com
6)现在尝试ping第二个容器
首先,通过IP地址ping它172.17.0.3(成功)
然后,按容器名称alpine2来ping(失败)
最后,使用按主机名(若启动容器不使用-h指定,默认是容器ID)ping(失败)
8)停止并移除两个容器。
docker container stop alpine1 alpine2
docker container rm alpine1 alpine2
由上述可知,使用默认的bridge网桥,容器之间通信只能使用ip,而不能使用容器名和主机名通信
不建议将默认bridge网络用于生产环境,生产环境中独立运行的容器应使用用户自定义的网桥(自定义网桥,容器之间通信可以使用ip、容器名称及主机名)
2、使用用户自定义的网桥
再次启动两个alpine容器,但将它们附加到已创建的用户定义的alpine-net(自定义的网桥)网络中,而不是连接到默认bridge网络。
然后,启动第三个alpine连接到bridge网络,但未连接到的容器alpine-net,
以及第四个容器alpine同时连接到两个网络默认的bridge和alpine-net。
1、创建alpine-net网络,可以不指定--driver bridge选项,因为它是默认值。
docker network create --driver bridge alpine-net
2、列出Docker的网络:
检查alpine-net网络
3)创建四个容器,在docker run命令中只能指定连接到一个网络
docker run -dit --name alpine1 --network alpine-net alpine ash
docker run -dit --name alpine2 --network alpine-net alpine ash
docker run -dit --name alpine3 alpine ash
docker run -dit --name alpine4 --network alpine-net alpine ash
docker network inspect bridge
docker network inspect alpine-net
docker network connect bridge alpine4
再次检查bridge网络
可以看到:
容器alpine3和alpine4连接到bridge网络
容器alpine1,alpine2和alpine4连接到alpine-net网络
进入alpine3:
ping alpine4的IP
ping alpine4容器名
ping alpine4主机名
进入alpine4:
ping alpine1/2的IP
ping alpine1/2容器名
ping alpine1/2主机名
注意:
alpine4它连接到默认bridge网络和alpine-net。它应该能够到达所有其他容器
停止并删除所有容器和alpine-net网络。
docker container stop alpine1 alpine2 alpine3 alpine4
docker container rm alpine1 alpine2 alpine3 alpine4
docker network rm alpine-net
结论:
如果容器均使用用户自定义的bridge网络,则进入到其中任何一个容器中,可使用IP、容器名、容器主机名ping
如果容器均默认的bridge网络docker0,则进入到其中任何一个容器中,只能使用IP 去ping
3、使用宿主机网络
将独立容器的网络直接绑定到Docker宿主机网络,没有进行网络隔离
示例:
启动一个nginx直接绑定到Docker宿主机上的80端口的容器。从网络的角度来看,这是相同的隔离级别,就好像nginx进程直接在Docker宿主机上而不是在容器中运行一样。但是其他方式(如存储,进程命名空间和用户命名空间)中,nginx进程与主机隔离,仅网络空间没有隔离
先决条件
- 要求Docker宿主机上80端口没有被占用
- host网络驱动程序仅适用于Linux
1)查看网络
2)创建并启动容器
docker run --rm -itd --network host --name my_nginx nginx
通过浏览到http://localhost:80/来访问Nginx
4)使用以下命令检查宿主机网络堆栈:
ip a
netstat -tulpn | grep 80
5) 停止容器。它将在使用该--rm选项启动时自动删除。
docker container stop my_nginx
思考:在使用容器部署zabbix系统时,如果在客户机使用容器部署,默认监控的是容器的相关信息,测试客户机启动容器时如果使用宿主机的网络空间是否能够监控到宿主机的相关性
预测:不能,因为容器和宿主机之间仅网络空间没有隔离,其他仍然是隔离的
4、使用overlay网络
先决条件
这些要求至少拥有一个单节点swarm群,这意味着已启动Docker,并docker swarm init在主机上运行,也可以在多节点群上运行示例。
最后,一个示例需要Docker 17.06或更高版本。
使用默认overlay网络
在此示例中,将启动alpine服务并从各个服务容器的角度检查网络的特征。
先决条件
需要三个物理或虚拟Docker主机,都可以相互通信,都运行Docker 17.03或更高版本,三台主机在同一网络上运行,不涉及防火墙。
这些主机将被称为manager,worker-1和worker-2
manager主机将作为既是manager(管理节点)又是worker(负载节点),这意味着它可以运行服务任务和管理群。worker-1和worker-2仅作为worker。
1)创建swarm
在此过程结束时,所有三个Docker主机将连接到swarm群集,并使用名为ingress的overlay网络连接在一起
在manager节点上执行:如果该主机只有一个接口,则省略--advertise-add选项
docker swarm init --advertise-add 10.0.0.103:2377
会提示信息,根据提示信息在另外2个worker节点上执行如下指令
docker swarm join --token \
SWMTKN-1-57n61vyjgud735zh31fc4xajxj81ml85f9m2171h5f39jy0msm-6ivonfta5sqllx3475r6yq8sw 10.0.0.103:2377
2)在worker1和worker2上执行:
docker swarm join --token \
SWMTKN-1-57n61vyjgud735zh31fc4xajxj81ml85f9m2171h5f39jy0msm-6ivonfta5sqllx3475r6yq8sw 10.0.0.103:2377
注意:worker1、worker2及manager之间的防火墙必须关闭,否则上述操作将会失败
3)manager节点上执行:
docker node ls #swarm中的所有节点都会被列出
docker node ls -f role=worker #swarm中的worker节点都会被列出
docker node ls -f role=manager #swarm中的manager节点都会被列出
如果swarm集群创建很久以后若有新的node要加入swarm集群中作为work节点或manager节点,使用如下指定查询,加入swarm集群中的指令:
docker swarm join-token worker #查看node加入swarm作为worker的指令
docker swarm join-token manager #查看node加入swarm作为manager的指令
4)分别在manager、worker-1、worker-2上列出Docker网络,会发现他们都有一个名为ingress的overlay网络和一个名为docker_gwbridge的网桥
docker network ls
docker_gwbridge将ingress网络连接到docker宿主机的网络接口以致swarm manger和worker的流量能够相互进出
如果创建swarm服务但未指定网络,则它们默认将连接到ingress网络
建议协同工作的每个应用程序或应用程序组使用单独的overlay网络
创建2个overlay网络,并将服务连接到每个网络。
创建服务
1)在manager上创建一个名为nginx-net的新overlay网络:
docker network create -d overlay nginx-net
不需要在其他节点上创建overlay网络,因为当其中一个worker节点运行需要它的服务时,将会在该worker节点上自动创建overlay网络(服务时在manager节点上创建,创建时指定网络使用overlay,该任务分配到哪个worker节点,哪个节点就会自动创建overlay网络)
2)在manager上创建连接到nginx-net网络的5个副本Nginx服务,该服务将向外界发布80端口,所有服务任务容器之间都可以相互通信而无需打开任何端口。
注意:只能在namager上创建服务。
$ docker service create \
--name my-nginx \
--publish published=80,target=80 \
--replicas=5 \
--network nginx-net \
nginx
当不使用--publish选项指定mode,将会使用默认的ingress发布模式,意味着如果在manager,worker-1或worker-2上浏览到80端口,都会被连接到5项服务任务之一的80端口上,即服务不在当前节点上运行。
如果要使用host模式发布端口,可以添加--publish mode=host选项(即只能通过访问分配了服务的worker节点才能访问;如果不指定--publish的mode选项使用默认的ingress)。
另外也应该使用--mode global(如果不指定,默认的--mode选项是replicated)而不是--replicas=5,在这种情况下,因为只有一个服务任务可以在给定节点上绑定给定的端口(?????)。
3)运行docker service ls 以监视服务启动的进度,这可能需要几秒钟。
watch docker service ls
docker service ps my-nginx #查看服务在各个worker上的分布情况
4)在master,worker-1和worker-2上,检查nginx-net网络。记住,在worker-1,worker-2上不需要手动创建overlay网络,因为Docker会自动创建它。输出很长,注意Containers和Peers部分,Containers列出从该主机连接到overlay网络的所有服务任务(或独立容器)。
5)在manager上使用docker service inspect my-nginx检查服务,并注意有关服务使用的端口和端点的信息。
6)创建一个新网络nginx-net-2,然后更新服务以使用此网络而不是nginx-net(服务运行的过程中,将服务添加到新网络,删除旧网络):
docker network create -d overlay nginx-net-2 #注意不需要--attacheable标记,若带有则允许独立容器连接
docker service update --network-add nginx-net-2 --network-rm nginx-net my-nginx
7)运行docker service ls以验证服务是否已更新并且已重新部署所有任务。
运行docker network inspect nginx-net以验证没有容器连接到它
运行docker network inspect nginx-net-2以检查nginx-net-2网络,并注意所有服务任务的容器都连接到它
注意:即使在swarm的worker节点上会按需自动创建overlay网络,但不会自动删除。
8)清理服务和网络。在manager上,运行以下命令,manager节点将会指导work节点自动删除网络。
docker service rm my-nginx #删除服务
docker network rm nginx-net nginx-net-2 #网络不会自动删除,需要手动删除
使用用户自定义的overlay网络
先决条件
假设已经设置了swarm,且登录到manager上
操作:
1)创建用户定义的overlay网络。
docker network create -d overlay my-overlay
2)使用overlay网络启动服务,并将端口80发布到Docker宿主机上的端口8080。
$ docker service create \
--name my-nginx \
--network my-overlay \
--replicas 1 \
--publish published=8080,target=80 \
nginx:latest
3)通过运行docker network inspect my-overlay,验证my-nginx服务任务已连接到该网络,查看Containers部分
4)删除服务和网络
docker service rm my-nginx
docker network rm my-overlay #网络不会自动删除,需要手动删除
将overlay网络用于独立容器
此示例演示DNS容器发现——特别是在不同Docker守护程序上的独立容器之间(即不同宿主机上的容器间通信)如何使用overlay网络进行通信
步骤:
a) 在host1,将节点初始化为swarm(manager)
b) 在host2,将节点加入swarm(worker)
c) 在host1,创建一个可附加(attachable)的覆盖网络(test-net),即允许独立容器连接到该网络
d) 在host1,在test-net网络上,打开一个交互式的alpine容器(alpine1)
e) 在host2,在test-net网络上(host2上不需要创建),打开一个交互式alpine容器(alpine2)
f) 在host1,从alpine1的会话中ping alpine2(能够ping通,虽然二者不在一个网段,但二者使用同一个overlay网络)
先决条件
对于此测试,需要两个可以相互通信的不同的Docker宿主机,每个主机必须具有Docker 17.06或更高版本,并且在两个Docker主机之间打开以下端口:
- TCP端口2377(仅manager节点)
- TCP和UDP端口7946(manger和worker)
- UDP端口4789(manger和worker)
操作
1)设置集群swarm
在host1上,初始化一个群
docker swarm init
Swarm initialized: current node (vz1mm9am11qcmo979tlrlox42) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5g90q48weqrtqryq4kj6ow0e8xm9wmv9o6vgqc5j320ymybd5c-8ex8j0bc40s6hgvy5ui5gl4gy 172.31.47.252:2377
To add a manager to this swarm, run:
'docker swarm join-token manager' and follow the Instructions.
在host2上,按照上面的说明加入swarm:
docker swarm join --token SWMTKN-1-5g90q48weqrtqryq4kj6ow0e8xm9wmv9o6vgqc5j320ymybd5c-8ex8j0bc40s6hgvy5ui5gl4gy 172.31.47.252:2377
如果docker swarm join命令超时,节点加入swarm失败,可以在host2上运行docker swarm leave --force,验证网络和防火墙设置后,再次将host2加入swarm。
2)在host1,创建一个可附加的overlay网络,名称为test-net:
docker network create --driver=overlay --attachable test-net
uqsof8phj3ak0rq9k86zta6ht #成功执行上述命令后,返回的网络ID
注意返回的NETWORK ID,从host2连接到它时,将再次看到它
3)在host1上,启动一个交互式(-it)容器(alpine1)并连接到test-net网络
docker run -it --name alpine1 --network test-net alpine
4)在host2,列出可用的网络,注意test-net尚不存在
docker network ls
5)在host2,启动分离的(-d),且交互式的(-it)容器(alpine2),并连接到test-net网络
docker run -dit --name alpine2 --network test-net alpine
自动DNS容器发现仅适用于的容器名称唯一的容器
6)host2上,验证test-net网络是否被创建(和host1上具有相同的网络ID为test-net):
docker network ls
7)在host1上上的alpine1容器内,ping alpine2
/ # ping -c 2 alpine2
可见两个使用overlay网络连接的容器,虽然位于不同的宿主机但能够进行通信
在host2上运行的另一个未分离的alpine容器,可以从host2上的这个容器中ping alpine1
$ docker run -it --rm --name alpine3 --network test-net alpine
/ # ping -c 2 alpine1
/ # exit
8)host1上,关闭alpine1会话(也会停止容器):
/ # exit
8)清理容器和网络:
必须单独停止和删除每个主机上的容器,因为Docker守护程序独立运行(不像swarm集群),并且这些是独立容器。只需要删除host1上的网络,因为停止host2上的alpine2时,test-net会自动消失。
host2上,停止alpine2,检查test-net是否已删除,然后删除alpine2
docker container stop alpine2
docker network ls
docker container rm alpine2
host1上,删除alpine1和test-net:
docker container rm alpine1
docker network rm test-net
小结:
连接到同一个overlay网络(该网络在swarm的manager节点上创建,带有--attachable标记)的多个独立容器,能够相互通信
在其中一个独立容器中ping另一台主机的独立容器,可通过容器名称、容器ID、IP 相互ping通
独立容器所在主机的容器删除后会自动删除overlay网络,swarm manager上的overlay网络并不会自动删除,即使manager主机上的对应容器删除
container和swarm service之间的通信
先决条件
需要Docker 17.06或更高版本。
操作
在此示例中,在同一个Docker主机上启动两个不同的alpine容器,并进行一些测试以了解它们如何相互通信。
1)打开终端窗口。在执行任何其他操作之前列出当前网络。如果从未在此Docker守护程序上添加网络或初始化swarm,那么应该看到以下内容(网络ID会有所不同):
docker network ls
启动两个容器连接到默认的bridge网络
2)启动两个alpine容器并运行ash
docker run -dit --name alpine1 alpine ash
docker run -dit --name alpine2 alpine ash
检查两个容器是否实际启动:
docker container ls
3)检查bridge网络以查看连接到它的容器。
docker network inspect bridge
4)容器在后台运行,使用docker attach命令连接到alpine1。
docker attach alpine1
/ #
提示符更改为#表示是容器中的root用户,使用该ip a命令显示alpine1容器内的网络接口
# ip a
第一个接口是环回设备,暂时忽略它。
第二个接口具有IP地址172.17.0.2,该地址3)中显示的地址相同
5)从alpine1内部,确保您可以通过ping连接到互联网
ping -c2 baidu.com(通)
ping 第二个容器的IP(通)
ping 第二个容器的容器名(不通)
ping 第二个容器的主机名(不通)
6)停止并移除两个容器。
docker container stop alpine1 alpine2
docker container rm alpine1 alpine2