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将请求定向到集群中的不同节点。
当使用 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 ofvip
. 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将请求定向到集群中的不同节点。