Linux入门教程:管理swarm(19) – 将服务附加到覆盖网络,swarm模式的覆盖


Docker Engine的swarm模式原生支持覆盖网络(overlay networks),所以你可以启用容器到容器的网络。swarm模式的覆盖网络包括以下功能:

你可以附加多个服务到同一个网络 默认情况下,service discovery为每个swarm服务分配一个虚拟IP地址(vip)和DNS名称,使得在同一个网络中容器之间可以使用服务名称为互相连接。 你可以配置使用DNS轮循而不使用VIP

为了可以使用swarm的覆盖网络,在启用swarm模式之间你需要在swarm节点之间开放以下端口:

TCP/UDP端口7946 – 用于容器网络发现 UDP端口4789 – 用于容器覆盖网络

在swarm中创建一个覆盖网络

当你运行Docker Engine的swarm模式时,你可以在管理节点执行docker network create命令来创建一个覆盖网络。例如,创建一个名为my-network的网络:

$ docker network create \   --driver overlay \   --subnet 10.0.9.0/24 \   --opt encrypted \   my-network   273d53261bcdfda5f198587974dae3827e947ccd7e74a41bf1f482ad17fa0d33

默认情况下swarm中的节点通信是加密的。在不同节点的容器之间,可选的–opt encrypted参数能在它们的vxlan流量启用附加的加密层。
–subnet参数指定覆盖网络的子网。当你不指定一个子网时,swarm管理器自动选择一个子网并分配给网络。在一些旧的内核,包括kernel 3.10,自动分配的地址可能会与其它子网重叠。这样的重叠可能引起连接问题。
执行docker network ls来查看网络:

$ docker network ls   NETWORK ID          NAME        DRIVER   SCOPE f9145f09b38b        bridge      bridge   local ..snip.. 273d53261bcd        my-network  overlay  swarm

swarm scope表示部署到swarm的服务可以使用这个网络。当你创建一个服务并附加到一个网络后,swarm仅仅扩展该网络到服务运行的节点上。在一个没有运行有附加到网络的服务worker节点上,network ls命令不会显示有任何网络。

附加服务到覆盖网络

要附加一个服务到一个覆盖网络,在创建服务的时候传递–network参数。例如创建一个nginx服务并附加到一个名为my-network的网络:

$ docker service create \   --replicas 3 \   --name my-web \   --network my-network \   nginx

注意:在附加服务到网络前,必须先创建这个网络。

在同一个覆盖网络的容器之间能互相连接。在管理节点执行docker service ps 来查看哪些节点运行着这个服务:

$ docker service ps my-web   ID                         NAME      IMAGE  NODE   DESIRED STATE  CURRENT STATE               ERROR 63s86gf6a0ms34mvboniev7bs  my-web.1  nginx  node1  Running        Running 58 seconds ago 6b3q2qbjveo4zauc6xig7au10  my-web.2  nginx  node2  Running        Running 58 seconds ago 66u2hcrz0miqpc8h0y0f3v7aw  my-web.3  nginx  node3  Running        Running about a minute ago

pic1
你可以在运行着附加有网络的服务的节点上查看这个网络的详情:

$ docker network inspect <NETWORK>

这个网络信息包括了该节点上附加到该网络的容器的列表。例如:

$ docker network inspect my-network [     {         "Name": "my-network",         "Id": "273d53261bcdfda5f198587974dae3827e947ccd7e74a41bf1f482ad17fa0d33",         "Scope": "swarm",         "Driver": "overlay",         "EnableIPv6": false,         "IPAM": {             "Driver": "default",             "Options": null,             "Config": [                 {                     "Subnet": "10.0.9.0/24",                     "Gateway": "10.0.9.1"                 }             ]         },         "Internal": false,         "Containers": {             "404d1dec939a021678132a35259c3604b9657649437e59060621a17edae7a819": {                 "Name": "my-web.1.63s86gf6a0ms34mvboniev7bs",                 "EndpointID": "3c9588d04db9bc2bf8749cb079689a3072c44c68e544944cbea8e4bc20eb7de7",                 "MacAddress": "02:42:0a:00:09:03",                 "IPv4Address": "10.0.9.3/24",                 "IPv6Address": ""             }         },         "Options": {             "com.docker.network.driver.overlay.vxlanid_list": "257"         },         "Labels": {}     } ]

在上面的示例中,my-web服务的容器my-web.1.63s86gf6a0ms34mvboniev7bs附加到该节点的my-network网络。

使用swarm模式的service discovery

默认情况下,当你创建一个服务并附加到一个网络时,swarm就给服务分配一个VIP。VIP根据服务名称映射到DNS别名。在该网络的容器之间通过gossip来共享DNS映射信息,所以在该网络的容器能通过服务名称来访问彼此。
你不需要公开特定于服务的端口,以使服务可用于同一覆盖网络上的其他服务。 swarm的内部负载均衡会自动将请求分发到服务VIP。
你可以使用如下命令来查看服务的VIP:

$ docker service inspect \   --format='{{json .Endpoint.VirtualIPs}}' \   my-web   [{"NetworkID":"7m2rjx0a97n88wzr4nu8772r3" "Addr":"10.0.0.2/24"}]

下面的示例展示如何添加一个busybox服务到与nginx服务相同的网络,以及busybox服务使用DNS名称my-web访问nginx服务:
1.在管理节点,部署busybox服务到与my-web同一个网络:

$ docker service create \   --name my-busybox \   --network my-network \   busybox \   sleep 3000

2.查看哪个节点运行着my-busybox服务:

$ docker service ps my-busybox   ID                         NAME          IMAGE    NODE   DESIRED STATE  CURRENT STATE          ERROR 1dok2cmx2mln5hbqve8ilnair  my-busybox.1  busybox  node1  Running        Running 5 seconds ago

3.登录上一步查询到的node1节点,在busybox容器中打开一个可交互的shell:

$ docker exec -it my-busybox.1.1dok2cmx2mln5hbqve8ilnair /bin/sh

你可以将容器名称推断为 + 。 或者,你可以在运行任务的节点上运行docker ps。
4.在busybox容器内部,查询my-web服务的VIP:

$ nslookup my-web   Server:    127.0.0.11 Address 1: 127.0.0.11   Name:      my-web Address 1: 10.0.9.2 ip-10-0-9-2.us-west-2.compute.internal

5.在busybox容器内部,查询的DNS记录来找出my-web服务的所有容器IP地址:

$ nslookup tasks.my-web   Server:    127.0.0.11 Address 1: 127.0.0.11   Name:      tasks.my-web Address 1: 10.0.9.4 my-web.2.6b3q2qbjveo4zauc6xig7au10.my-network Address 2: 10.0.9.3 my-web.1.63s86gf6a0ms34mvboniev7bs.my-network Address 3: 10.0.9.5 my-web.3.66u2hcrz0miqpc8h0y0f3v7aw.my-network

6.在busybox容器内,执行wget来访问my-web服务的nginx web server:

$ wget -O- my-web   Connecting to my-web (10.0.9.2:80) <!DOCTYPE html> <html> <head> <title>Welcome to nginx!</title> ...snip...

通过访问服务的VIP,swarm负载均衡自动将HTTP请求路由可用的容器中。 它使用轮循的方式来平均地分发请求。

使用DNS轮循请求

你可以配置服务直接使用DNS轮循而不用VIP,在创建服务的时候设置–endpoint-mode dnsrr。在你要使用你自己的负载均衡器时可能会用此方法。
下面的示例展示一个服务使用dnsrr endpoint模式:

$ docker service create \   --replicas 3 \   --name my-dnsrr-service \   --network my-network \   --endpoint-mode dnsrr \   nginx

当你查询服务名称的DNS记录时,DNS服务会返回所有该服务容器的IP地址:

$ nslookup my-dnsrr-service Server:    127.0.0.11 Address 1: 127.0.0.11   Name:      my-dnsrr Address 1: 10.0.9.8 my-dnsrr-service.1.bd3a67p61by5dfdkyk7kog7pr.my-network Address 2: 10.0.9.10 my-dnsrr-service.3.0sb1jxr99bywbvzac8xyw73b1.my-network Address 3: 10.0.9.9 my-dnsrr-service.2.am6fx47p3bropyy2dy4f8hofb.my-network

相关内容