Docker Swarm:绕过负载均衡器,直接请求特定容器

3

我有两个在swarm中运行的容器。每个容器都暴露了一个/stats端点,我正在尝试进行抓取。

然而,使用swarm端口显然会导致查询被负载均衡,因此统计信息都混杂在一起:

+--------------------------------------------------+
|                       Server                     |
|    +-------------+             +-------------+   |
|    |             |             |             |   |
|    | Container A |             | Container B |   |
|    |             |             |             |   |
|    +-------------+             +-------------+   |
|                 \              /                 |
|                  \            /                  |
|                 +--------------+                 |
|                 |              |                 |
|                 | Swarm Router |                 |
|                 |              |                 |
|                 +--------------+                 |
|                         v                        |
+-------------------------|------------------------+
                          |                         
                       A Stats                      
                       B Stats                      
                       A Stats                      
                       B Stats                      
                          |                         
                          v                          

我希望保留应用请求的负载均衡器,但也需要一种直接的方式来请求每个容器以获取统计信息。

+--------------------------------------------------+
|                       Server                     |
|    +-------------+             +-------------+   |
|    |             |             |             |   |
|    | Container A |             | Container B |   |
|    |             |             |             |   |
|    +-------------+             +-------------+   |
|        |        \              /         |       |
|        |         \            /          |       |
|        |        +--------------+         |       |
|        |        |              |         |       |
|        |        | Swarm Router |         |       |
|        v        |              |         v       |
|        |        +--------------+         |       |
|        |                |                |       |
+--------|----------------|----------------|-------+
         |                |                |
      A Stats             |             B Stats
      A Stats       Normal Traffic      B Stats
      A Stats             |             B Stats
         |                |                |
         |                |                |
         v                |                v

动态解决方案会更理想,但是由于我不打算进行任何动态缩放,因此为每个容器设置硬编码端口之类的东西就可以了。
::8080  Both containers via load balancer
::8081  Direct access to container A
::8082  Direct access to container B

Swarm能否实现这个功能?

3个回答

1
在叠加网络内,您可以通过tasks.<service_name> DNS查询获取所有副本的IP地址:
; <<>> DiG 9.11.5-P4-5.1+deb10u5-Debian <<>> -tA tasks.foo_test
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 19860
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;tasks.foo_test.            IN  A

;; ANSWER SECTION:
tasks.foo_test.     600 IN  A   10.0.1.3
tasks.foo_test.     600 IN  A   10.0.1.5
tasks.foo_test.     600 IN  A   10.0.1.6

这在文档中提到。

另外,如果你使用Prometheus来抓取这些端点的指标,你可以结合dns_sd_configs将目标设置为抓取(这里有一篇文章介绍如何操作)。这种方法易于运行但功能有限(特别是在大型环境中)。

一个更高级的实现相同效果的方法是使用dockerswarm_sd_config文档配置示例)。这样,端点列表将通过查询Docker守护程序进行收集,并附带一些有用的标签(如节点名称、服务名称、自定义标签)。


@JShorthouse更新了答案,提供了关于dns_sd_configdockerswarm_sd_config之间差异的一些信息。 - anemyte

1

虽然不是最理想的解决方案,但您可以引入一个微服务作为中介来处理其它容器所暴露的/stats端点。该微服务必须配置各个端点,并在相同网络中运行。

这样做并没有绕过负载均衡器,而是使负载均衡器变得无关紧要。

该中介可以汇总信息,或者您可以通过传递不透明标识符列表来使其更加复杂,然后调用者可以使用这些标识符单独查询中介。

从某种意义上说,这稍微有些“反模式”,因为您必须配置高度耦合的“stats”代理才能访问每个端点。

话虽如此,从安全角度来看,这是很好的,因为您不必将单个容器暴露给代理外部。这样做可能更安全,因为您不会泄露更多的Swarm信息。


0

您可以尝试在主机上发布特定的容器端口,将其添加到您的服务中:

    ports:
      - target: 8081
        published: 8081
        protocol: tcp
        mode: host

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接