300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > Docker网络教程(三)overlay 网络教程

Docker网络教程(三)overlay 网络教程

时间:2019-06-24 16:53:59

相关推荐

Docker网络教程(三)overlay 网络教程

使用 overlay 网络联网

本系列的教程处理有关于 swarm 服务有关的网络。对于独立容器的网络,参考独立容器联网教程。如果想了解更多 Docker 网络的理论知识,参考概述。

本文包括四个不同的教程。你可以在Linux、Windows或Mac上运行它们中的每一个,但对于最后两个,你需要在其他地方运行第二个Docker主机。

使用默认的 overlay 网络演示了如何使用 Docker 在你初始化或加入 swarm 时为你自动设置的默认 overlay 网络。这个网络不是生产环境中的最佳选择。

使用用户定义的 overlay 网络演示了如何创建和使用你自己的自定义 overlay 网络,以连接服务。建议在生产环境中运行的服务使用这个方法。

给独立容器用上overlay 网络显示了如何使用 overlay 网络在不同Docker daemon 的独立容器之间进行通信。

容器和 swarm 服务之间的通信在独立的容器和 swarm 服务之间建立通信,使用了一个可附加的 overlay 网络。

先决条件

这些要求你至少有一个单节点的 swarm,这意味着你已经启动了 Docker 并在宿主机上运行docker swarm init。你也可以在多节点 swarm 上运行这些例子。

使用默认的 overlay 网络

在这个例子中,你启动一个alpine服务,并在各个服务容器里检查网络的特性。

本教程不涉及关于如何实现 overlay 网络的操作系统的具体细节,而是侧重于从服务的角度看 overlay 如何运作。

先决条件

本教程需要三个物理或虚拟的Docker主机,它们都可以相互通信。本教程假设这三个主机运行在同一个网络上,并且没有防火墙干扰。

这些主机将被称为manager,worker-1worker-2manager主机将同时作为管理者和 worker 发挥作用,这意味着它既可以运行服务任务,也可以管理 swarm;worker-1worker-2将只作为worker 发挥作用。

如果你手头没有三台主机,一个简单的解决方案是在云服务提供商(如亚马逊EC2)上设置三台Ubuntu主机,它们都在同一个网络上,并且允许该网络上的所有主机进行通信(使用EC2安全组等机制),然后按照Docker Engine 安装说明 - Community on Ubuntu的安装说明操作。

演练

创建 swarm

在这个过程结束时,所有三个Docker主机都将加入到 swarm 中,并将使用一个名为ingress的覆盖网络连接在一起。

manager上初始化 swarm。如果宿主机只有一个网络接口,则--advertise-addr标志是可选的。

$ docker swarm init --advertise-addr=<IP-ADDRESS-OF-MANAGER>

记下打印出来的文本,因为它包含您将用于将worker-1worker-2加入蜂群的令牌。将该令牌存储在某个密码管理器中是个好主意。

worker-1上加入swarm。如果主机只有一个网络接口,则--advertise-addr标志是可选的。

$ docker swarm join --token <TOKEN> \--advertise-addr <IP-ADDRESS-OF-WORKER-1> \<IP-ADDRESS-OF-MANAGER>:2377

worker-2上加入swarm。如果主机只有一个网络接口,则--advertise-addr标志是可选的。

$ docker swarm join --token <TOKEN> \--advertise-addr <IP-ADDRESS-OF-WORKER-2> \<IP-ADDRESS-OF-MANAGER>:2377

manager上列出所有的节点。此命令只会在管理节点上生效。

$ docker node lsID HOSTNAME STATUS AVAILABILITY MANAGER STATUSd68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 ReadyActive Leadernvp5rwavvb8lhdggo8fcf7plgip-172-31-35-151 ReadyActiveouvx2l7qfcxisoyms8mtkgahwip-172-31-36-89ReadyActive

你也可以用--filter标志来根据节点的角色进行过滤显示:

$ docker node ls --filter role=managerID HOSTNAME STATUS AVAILABILITY MANAGER STATUSd68ace5iraw6whp7llvgjpu48 * ip-172-31-34-146 ReadyActive Leader$ docker node ls --filter role=workerID HOSTNAME STATUS AVAILABILITY MANAGER STATUSnvp5rwavvb8lhdggo8fcf7plgip-172-31-35-151 ReadyActiveouvx2l7qfcxisoyms8mtkgahwip-172-31-36-89ReadyActive

列出managerworker-1worker-2上的 Docker 网络,并注意到它们现在都有一个名为ingress的 overlay 网络和一个名为docker_gwbridge的 bridge 网络。这里只显示manager的:

$ docker network lsNETWORK IDNAMEDRIVER SCOPE495c570066be bridge bridge local961c6cae9945 docker_gwbridgebridge localff35ceda3643 hosthostlocaltrtnl4tqnc3n ingress overlay swarmc8357deec9cb nonenulllocal

docker_gwbridgeingress网络连接到 Docker 宿主机的网络接口上,这样流量就可以在 swarm管理者和 worker 之间流动。如果你创建了 swarm 服务,但没有指定网络,它们就会被连接到ingress网络上。建议你为每个应用程序或将一起工作的应用程序组使用单独的 overlay 网络。在接下来的步骤中,你将创建两个覆盖网络,并将一个服务连接到每个网络。

创建服务

manager上,创建一个新的 overlay 网络,取名为nginx-net:

$ docker network create -d overlay nginx-net

你不需要在其他节点上创建 overlay 网络,因为当这些节点开始运行一个需要它的服务任务时,它将自动创建。

manager上创建有5个副本的 Niginx 服务,并连接到nginx-net。此服务会发布80端口到外界。所有任务下的容器,都可以自由通讯,而不需端口发布。

注意: 服务只能在管理节点上创建

$ docker service create \--name my-nginx \--publish target=80,published=80 \--replicas=5 \--network nginx-net \nginx

当你没有用--publish标志指定发布模式时,ingress会启用默认模式。默认模式下,你在manager,worker-1, 或者worker-2上浏览到端口 80,你将被连接到 5 个服务任务中的一个的 80 端口,即使你浏览到的节点上当前没有任务在运行。如果你想使用host模式发布端口,你可以在--publish输出中添加mode=host。然而,在这种情况下,你也应该使用--mode global而不是--replicas=5,因为在一个给定的节点上只有一个服务任务可以绑定一个给定的端口。

运行docker service ls指令,来监控服务启动起来的进程,这也许需要几分钟。

manager,worker-1, 和worker-2上 inspect 一下nginx-net网络。记得你不需要在worker-1worker-2上创建它,Docker 会自动帮你创建。输出会很长,关注ContainersPeers部分。Containers列出在这台主机上所有连接到此 overlay 网络的服务任务(或者独立的容器)。

manager上,用docker service inspect my-nginx指令 inspect 一下服务,注意服务用到的端口(ports)跟端点(endpoints)。

创建新的网络nginx-net-2,接着更新服务连接到它而不是nginx-net:

$ docker network create -d overlay nginx-net-2

$ docker service update \--network-add nginx-net-2 \--network-rm nginx-net \my-nginx

运行docker service ls来验证服务是否已经更新,所有任务是否已经重新部署。运行docker network inspect nginx-net,确认没有容器连接到它。对nginx-net-2运行同样的命令,注意所有的服务任务容器都连接到了它。

注意: 即使 overlay 网络是根据需要在 swarm 工作节点上自动创建的,它们也不会被自动删除。

清理服务跟网络。在manager上运行下面的命令。管理节点会指引 worker 自动删除掉对应的网络。

$ docker service rm my-nginx$ docker network rm nginx-net nginx-net-2

使用用户定义的 overlay 网络

先决条件

此教程会假设 swarm 已经设置好并且你在管理节点上。

演练

创建用户定义的 overlay 网络

$ docker network create -d overlay my-overlay

启动一个服务,使用 overlay 网络并且在 Docker 宿主机上发布 80 跟 8080 端口。

$ docker service create \--name my-nginx \--network my-overlay \--replicas 1 \--publish published=8080,target=80 \nginx:latest

运行docker network inspect my-overlay命令,通过观察Containers部分,验证my-nginx服务下的任务已经连接到它。

删除测试的服务以及网络。

$ docker service rm my-nginx$ docker network rm my-overlay

给独立容器用上overlay 网络

这个例子演示了 DNS 容器发现——具体来说,就是如何使用 overlay 网络在不同 Docker daemon 的独立容器之间进行通信。步骤是:

host1,初始化为 swarm 的管理节点。在host2,加入 swarm 成为 worker 节点。在host1,创建一个可附加(attachable)overlay 网络(test-net)。在host1,test-net网络上运行一个交互式un an interactivealpine容器 (alpine1) 。在host2,test-net网络上运行一个交互式、分离的(亦即后台)alpine容器(alpine2) 。在host1,alpine1的会话里 pingalpine2。

先决条件

在此项测试中,你需要两个独立的、可以通讯的 Docker 宿主机。每个主机需要对彼此开放以下的端口:

TCP port 2377TCP and UDP port 7946UDP port 4789

一个简单的把这些配置起来的方法,是拥有两台虚拟机(无论是本地虚拟的还是在云厂商比如亚马逊云那里购买),每一台都已经安装并运行好 Docker。如果你正在使用亚马逊云或者其他类似的云计算平台,最简单的配置方法是使用一个安全组,安全组里开放两个主机之间的所有端口以及对你 ssh 客户端的IP开放 ssh 端口。

这个例子中,我们把两个 swarm 节点分别称为host1host2。同事,例子使用的是Linux 主机,但同样的命令也可以在 Windows 下面起作用。

演练

设置好 swarm。

a. 在host1, 初始化一个 swarm (如果有提示,使用--advertise-addr来指定与 swarm 中其他主机通信的接口的IP地址,例如,AWS的私有IP地址):

$ docker swarm initSwarm 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:2377To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.

b. 在host2, 按照上面的指示,加入创建好的 swarm:

$ docker swarm join --token <your_token> <your_ip_address>:2377This node joined a swarm as a worker.

如果节点加入 swarm 失败,docker swarm join命令会超时。要解决这个问题,可以在host2运行docker swarm leave --force,验证一下你的网络跟防火墙的设置是否正常,然后再试一次。

host1, 船舰一个可附加的 overlay 网络,叫test-net:

$ docker network create --driver=overlay --attachable test-netuqsof8phj3ak0rq9k86zta6ht

注意返回的网络ID-- 当你从host2连接到它时,你会再次看到它。

host1, 启动一个可交互 (-it) 容器(alpine1) ,连接到test-net:

$ docker run -it --name alpine1 --network test-net alpine/ #

host2, 列出所有可用的网络,注意到test-net还没有创建:

$ docker network lsNETWORK IDNAMEDRIVER SCOPEec299350b504 bridge bridge local66e77d0d0e9a docker_gwbridgebridge local9f6ae26ccb82 hosthostlocalomvdxqrda80z ingress overlay swarmb65c952a4b2b nonenulllocal

host2, 启动一个分离式 (-d) 和交互式 (-it) 容器 (alpine2) ,连接到test-net:

$ docker run -dit --name alpine2 --network test-net alpinefb635f5ece59563e7b8b99556f816d24e6949a5f6a5b1fbd92ca244db17a4342

自动的容器 DNS 发现功能,只会在容器名唯一时有效。

host2, 验证一下test-net已经被创建出来(它的网络 ID 跟刚刚在host1上的test-net看到的一致):

$ docker network lsNETWORK IDNAMEDRIVER SCOPE...uqsof8phj3ak test-net overlay swarm

host1, 用alpine1容器的交互终端 pingalpine2

/ # ping -c 2 alpine2PING alpine2 (10.0.0.5): 56 data bytes64 bytes from 10.0.0.5: seq=0 ttl=64 time=0.600 ms64 bytes from 10.0.0.5: seq=1 ttl=64 time=0.555 ms--- alpine2 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.555/0.577/0.600 ms

这两个容器与连接两台主机的 overlay 网络进行通信。如果你在host2上运行另一个没有分离(not detached)的 alpine 容器,你可以从host2上pingalpine1(这里我们添加了移除选项,用于自动清理容器):

$ docker run -it --rm --name alpine3 --network test-net alpine/ # ping -c 2 alpine1/ # exit

host1, 关掉alpine1会话(容器会跟着停止掉):

/ # exit

清理你的容器跟网络:

你必须分别在不同的主机上停止跟移除容器,因为两个 Docker daemon 是独立运行的,并且容器也是独立的容器。你只需要在host1上移除网络,因为当你在host2上停止alpine2时,test-net也跟着消失了。

a. 在host2停止alpine2, 检查test-net已经被移除,接着移除alpine2:

$ docker container stop alpine2$ docker network ls$ docker container rm alpine2

a. 在host1移除alpine1test-net:

$ docker container rm alpine1$ docker network rm test-net

容器和 swarm 服务之间的通信

在这个例子中,你在同一台 Docker 宿主机上启动两个不同的alpine容器,并做测试,以了解它们如何相互通信。你需要安装并运行 Docker。

打开一个终端窗口。在你做其他事情之前,列出当前的网络。如果你从未在这个 Docker daemon上添加过网络或初始化过 swarm,你应该看到以下内容。你可能会看到不同的网络,但你至少应该看到这些(网络ID会不同):

$ docker network lsNETWORK IDNAMEDRIVER SCOPE17e324f45964 bridge bridge local6ed54d316334 hosthostlocal7092879f2cc8 nonenulllocal

默认的bridge网络在hostnone中被列出。后两者并不是“完整意义”上的网络,只是用来启动一个直接连接到宿主机的网络栈的容器,又或者是一个没有网络设备的容器。此教程会把两个容器连接到bridge网络上。

启动两个运行ashalpine容器,这是 Alpine 的默认shell而不是bash-dit标志意味着启动的容器是分离的(在后台)、交互式的(能够向其中输入文字)和有一个TTY(所以你可以看到输入和输出)。由于你是以分离方式启动的,所以你不会立即与容器连接。相反,容器的ID将被打印出来。因为你没有指定任何--network标志,所以容器会连接到默认的bridge网络。

$ docker run -dit --name alpine1 alpine ash$ docker run -dit --name alpine2 alpine ash

检查两个容器都已经正常启动:

$ docker container lsCONTAINER ID IMAGECOMMAND CREATED STATUS PORTSNAMES602dbf1edc81 alpine "ash"4 seconds ago Up 3 seconds alpine2da33b7aa74b0 alpine "ash"17 seconds agoUp 16 seconds alpine1

Inspect 一下bridge网络,看看哪些容器连接到了它。

$ docker network inspect bridge[{"Name": "bridge","Id": "17e324f459648a9baaea32b248d3884da102dde19396c25b30ec800068ce6b10","Created": "-06-22T20:27:43.826654485Z","Scope": "local","Driver": "bridge","EnableIPv6": false,"IPAM": {"Driver": "default","Options": null,"Config": [{"Subnet": "172.17.0.0/16","Gateway": "172.17.0.1"}]},"Internal": false,"Attachable": false,"Containers": {"602dbf1edc81813304b6cf0a647e65333dc6fe6ee6ed572dc0f686a3307c6a2c": {"Name": "alpine2","EndpointID": "03b6aafb7ca4d7e531e292901b43719c0e34cc7eef565b38a6bf84acf50f38cd","MacAddress": "02:42:ac:11:00:03","IPv4Address": "172.17.0.3/16","IPv6Address": ""},"da33b7aa74b0bf3bda3ebd502d404320ca112a268aafe05b4851d1e3312ed168": {"Name": "alpine1","EndpointID": "46c044a645d6afc42ddd7857d19e9dcfb89ad790afb5c239a35ac0af5e8a5bc5","MacAddress": "02:42:ac:11:00:02","IPv4Address": "172.17.0.2/16","IPv6Address": ""}},"Options": {"work.bridge.default_bridge": "true","work.bridge.enable_icc": "true","work.bridge.enable_ip_masquerade": "true","work.bridge.host_binding_ipv4": "0.0.0.0","work.bridge.name": "docker0","work.driver.mtu": "1500"},"Labels": {}}]

在顶部附近,列出了bridge网络的信息,包括Docker主机和bridge网络之间的网关的IP地址(172.17.0.1)。在Containers键下,列出了每个连接的容器,以及关于其IP地址的信息(172.17.0.2alpine1172.17.0.3alpine2)。

两个容器都在后台运行着,用docker attach命令连接alpine1.

$ docker attach alpine1/ #

提示符变成了#,表示你是容器内的root用户。使用ip addr show命令来显示alpine1的网络接口,就像这样:

# ip addr show1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::1/128 scope hostvalid_lft forever preferred_lft forever27: eth0@if28: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue state UPlink/ether 02:42:ac:11:00:02 brd ff:ff:ff:ff:ff:ffinet 172.17.0.2/16 scope global eth0valid_lft forever preferred_lft foreverinet6 fe80::42:acff:fe11:2/64 scope linkvalid_lft forever preferred_lft forever

第一个接口是回环设备,暂时忽略。注意第二个接口的IP地址是172.17.0.2,这与上一步中显示的alpine1的地址相同。

alpine1中,通过 ping 百度来确认你已经连接到互联网。-c 2标志限定了命令执行两次ping

# ping -c 2PING (39.156.66.10): 56 data bytes64 bytes from 39.156.66.10: seq=0 ttl=47 time=42.544 ms64 bytes from 39.156.66.10: seq=1 ttl=47 time=42.523 ms--- ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 42.523/42.533/42.544 ms

现在试试 ping 第二个容器。首先用它的IP地址172.17.0.3试试:

# ping -c 2 172.17.0.3PING 172.17.0.3 (172.17.0.3): 56 data bytes64 bytes from 172.17.0.3: seq=0 ttl=64 time=0.086 ms64 bytes from 172.17.0.3: seq=1 ttl=64 time=0.094 ms--- 172.17.0.3 ping statistics ---2 packets transmitted, 2 packets received, 0% packet lossround-trip min/avg/max = 0.086/0.090/0.094 ms

成功了。接着,试试用容器名去 pingalpine2容器。这应该会失败。

# ping -c 2 alpine2ping: bad address 'alpine2'

用 Detach 操作序列从alpine1断开,CTRL+pCTRL+q(按下CTRL然后依次键入pq)。如果你愿意,也可以连接进alpine2来重复步骤4、5、6,用alpine1代替alpine2

停止并移除所有的容器。

$ docker container stop alpine1 alpine2$ docker container rm alpine1 alpine2

记住,默认的bridge网络不建议用在生产环境中。了解更多的用户定义 bridge 网络,请继续下一个教程。

其他的网络教程

现在你已经完成了 overlay 网络联网的教程,你可能想跑一下其他的:

Host 网络教程独立容器网络教程Macvlan 网络教程

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。