docker swarm 容器链接:"tasks.service1" vs 直接 "service1"

dockerswarm container linking : "tasks.service1" vs directly "service1"

当使用 docker 群时,curling/pinging 时使用“tasks.service1”或直接使用“service1”有什么区别?

实际例子: 我在同一个覆盖网络上启动了一个 docker 群服务:

$> docker network create --driver=overlay public
$> docker service create --name service1 --replicas=2 --network public ubuntu sleep 10000

现在我列出容器 :

$> docker ps -a
bd645378cb2d   ubuntu:latest   "sleep 10000"   43 seconds ago   Up 41 seconds             service1.1.rjy91s66col81libdilrd698j
686c0ab006fc   ubuntu:latest   "sleep 10000"   43 seconds ago   Up 41 seconds             service1.2.wjrwsj6h6rcadsknzxym4h9w0

如果我附加到第一个容器,我可以 ping 通其他容器:

$> docker exec -ti bd645378cb2d bash
$> apt update
$> apt install iputils-ping dnsutils
$> ping service1 # returns ok 10.0.1.65

当我挖掘特殊主机名 tasks.service1 时,我得到了所有副本的 ips。 但是这些与我通过 ping 得到的不匹配。

$> dig tasks.service1 # returns 10.0.1.66 & 10.0.1.67

为什么ips不匹配? 如果我需要从服务 1 连接到服务 2,我应该使用 tasks.service2 还是 service2?

这是一个负载平衡器 IP。如果使用默认 vip(虚拟 IP)--endpoint-mode 创建,Docker 服务有它。您可以使用 docker inspect <service_name>:

查看它
"Endpoint": {
    "Spec": {
        "Mode": "vip"
    },
    "VirtualIPs": [
        {
            "NetworkID": "i7k7pv9s4v7dgvc57zjmh6pk6",
            "Addr": "10.0.1.2/24"
        }
    ]
}

这个在documentation中有提到,虽然很容易漏掉重点:

To use an external load balancer without the routing mesh, set --endpoint-mode to dnsrr instead of the default value of vip. In this case, there is not a single virtual IP.

tasks.service1 名称将解析为服务中每个单独容器的 IP 地址。如果您需要引用单个副本,这会很有用。

但是,也有一个缺点。大多数操作系统和应用程序中的 DNS 缓存。这意味着在更新您的服务期间,过时的 DNS 解析可能指向不再可访问的 IP,或者可能指向最近使用回收 IP 启动的完全不同的容器。

为了在 Swarm 模式下处理此问题,解析 service1 时默认使用虚拟 IP (VIP)。这是动态更新的,因为副本是 created/deleted,没有 DNS 缓存问题。它对每个新连接执行循环负载平衡。

旁注,这也被已发布端口上的入口使用。这意味着如果你有一个外部 LB 指向集群,一个在入口上发布的端口,到一个全局调度的服务,你最终可能会有一个额外的网络跃点。在那些情况下,我通常会绕过VIP,以主机模式发布端口,让外部LB将请求定向到集群中的不同节点。