swarm 文档中的 Load Balancing 部分没有说明内部负载均衡器是否也进行健康检查,以及它是否删除了不再运行服务的节点(因为它被杀死或节点被重新启动)。
在以下情况下,我有一个服务,副本为 3,在 3 个节点中的每个节点上运行 1 个实例。
经理:
[root@centosvm ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a593d485050a ddewaele/springboot.crud.sample:latest "sh -c 'java $JAVA_OP" 7 minutes ago Up 7 minutes springbootcrudsample.1.5syc6j4c8i3bnerdqq4e1yelm
节点 1:
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d3b3fbc0f2c5 ddewaele/springboot.crud.sample:latest "sh -c 'java $JAVA_OP" 4 minutes ago Up 4 minutes springbootcrudsample.3.7y1oyjyrifgkmxlr20oai5ppl
节点 2:
[root@node2 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ebca8f24ec3a ddewaele/springboot.crud.sample:latest "sh -c 'java $JAVA_OP" 7 minutes ago Up 7 minutes springbootcrudsample.2.4tqjad7od8ep047s55485na1t
现在,在 node1 上,我们终止了 docker 容器。该节点将没有服务(swarm 将在几秒钟后在此处重新创建它以保持服务上的 replication=3)
[root@node1 ~]# docker kill d3b3fbc0f2c5
d3b3fbc0f2c5
容器不见了
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
新建容器
[root@node1 ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
b8c9a7a5cf97 ddewaele/springboot.crud.sample:latest "sh -c 'java $JAVA_OP" 11 seconds ago Up 9 seconds springbootcrudsample.3.9v4cnhi8dvq7n8afb2kvp28sk
然而,在下面的输出中,当容器
d3b3fbc0f2c5
被杀死时,入口负载均衡器没有检测到这一点,它仍在向节点发送流量(导致连接被拒绝)?我们应该如何处理这样的场景?对于这种情况,我们是否仍然需要外部负载均衡器,我们应该如何配置它?
[root@centosvm ~]# while :; do curl http://localhost:8080/env/hostname ; echo "" ; sleep 1; done
{"hostname":"d3b3fbc0f2c5"}
{"hostname":"a593d485050a"}
{"hostname":"ebca8f24ec3a"}
{"hostname":"d3b3fbc0f2c5"}
{"hostname":"a593d485050a"}
{"hostname":"ebca8f24ec3a"}
{"hostname":"d3b3fbc0f2c5"}
{"hostname":"a593d485050a"}
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
curl: (7) Failed connect to localhost:8080; Connection refused
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
curl: (7) Failed connect to localhost:8080; Connection refused
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
curl: (7) Failed connect to localhost:8080; Connection refused
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
curl: (7) Failed connect to localhost:8080; Connection refused
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
curl: (7) Failed connect to localhost:8080; Connection refused
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
curl: (7) Failed connect to localhost:8080; Connection refused
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
{"hostname":"b8c9a7a5cf97"}
{"hostname":"ebca8f24ec3a"}
{"hostname":"a593d485050a"}
{"hostname":"b8c9a7a5cf97"}
最佳答案
如 François Maturel 所示,在适当的健康检查到位后,Docker Swarm 将考虑容器的健康状态来决定是否将请求路由到它。
对于启用了默认执行器的 Spring Boot 应用程序,将它添加到 Dockerfile 足以进行基本的健康检查。当 Spring Boot 应用程序初始化并启用其 health actuator 时,以下 http 请求将返回有效的 http 200 响应,健康检查将通过。
HEALTHCHECK CMD wget -q http://localhost:8080/health -O /dev/null
这将导致您的 docker 容器能够达到健康状态。当您的 docker 容器启动时,其中运行的服务可能仍在初始化。为了进行适当的负载平衡和检测服务健康状况,Swarm 需要知道何时能够将请求路由到特定的服务实例(节点上的容器)。
所以当 Swarm 启动一个服务副本时,它会启动一个容器,它会一直等到服务的健康状态为“健康”。当您的容器启动时,它将从“开始”过渡:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5001e1c46953 ddewaele/springboot.crud.sample@sha256:4ce69c3f50c69640c8240f9df68c8816605c6214b74e6581be44ce153c0f3b7a "/docker-entrypoin..." 5 seconds ago Up Less than a second (health: starting) springbootcrudsample.2.yt6d38zhhq2wxt1d6qfjz5974
到'健康'。只有这样,Swarm 负载均衡器才会将请求路由到此端点。
[root@centos-a ~]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5001e1c46953 ddewaele/springboot.crud.sample@sha256:4ce69c3f50c69640c8240f9df68c8816605c6214b74e6581be44ce153c0f3b7a "/docker-entrypoin..." About a minute ago Up About a minute (healthy) springbootcrudsample.2.yt6d38zhhq2wxt1d6qfjz5974
关于docker - 群负载均衡是否应该对其节点执行健康检查?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43340147/