Docker Swarm:绕过负载均衡器并直接向特定容器发出请求
Docker Swarm: bypass load balancer and make direct request to specific containers
我有两个容器 运行 成群。每个都公开了一个我试图抓取的 /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 完成吗?
从覆盖网络内部,您可以使用 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
结合起来以设置要抓取的目标(here 是一篇关于如何抓取的文章) .这很容易获得 运行 但在功能上有些限制(尤其是在大型环境中)。
实现相同目的的更高级方法是使用 dockerswarm_sd_config
(docs, example configuration)。这样,将通过查询 Docker 守护程序以及一些有用的标签(即节点名称、服务名称、自定义标签)来收集端点列表。
您可以尝试在主机上发布特定的容器端口
,添加到您的服务:
ports:
- target: 8081
published: 8081
protocol: tcp
mode: host
虽然不太理想,但您可以引入一个微服务作为其他容器的中介,这些容器公开 /stats
。此微服务必须使用单独的端点进行配置,并在与所述端点相同的网络中运行。
这并没有绕过负载均衡器,而是让它变得无关紧要。
中间人可以汇总信息,或者您可以通过传递不透明标识符列表使其更复杂,然后调用者可以使用这些标识符来单独查询中间人。
从某种意义上说,它有点“反模式”,因为您有一个必须配置为能够访问每个端点的高度耦合的“统计”代理。
也就是说,从某种意义上说,这很好,您不必在代理外部公开单个容器。从安全角度来看,这可能更好,因为您不会从您的群中泄露额外的信息。
我有两个容器 运行 成群。每个都公开了一个我试图抓取的 /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 完成吗?
从覆盖网络内部,您可以使用 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
结合起来以设置要抓取的目标(here 是一篇关于如何抓取的文章) .这很容易获得 运行 但在功能上有些限制(尤其是在大型环境中)。
实现相同目的的更高级方法是使用 dockerswarm_sd_config
(docs, example configuration)。这样,将通过查询 Docker 守护程序以及一些有用的标签(即节点名称、服务名称、自定义标签)来收集端点列表。
您可以尝试在主机上发布特定的容器端口 ,添加到您的服务:
ports:
- target: 8081
published: 8081
protocol: tcp
mode: host
虽然不太理想,但您可以引入一个微服务作为其他容器的中介,这些容器公开 /stats
。此微服务必须使用单独的端点进行配置,并在与所述端点相同的网络中运行。
这并没有绕过负载均衡器,而是让它变得无关紧要。
中间人可以汇总信息,或者您可以通过传递不透明标识符列表使其更复杂,然后调用者可以使用这些标识符来单独查询中间人。
从某种意义上说,它有点“反模式”,因为您有一个必须配置为能够访问每个端点的高度耦合的“统计”代理。
也就是说,从某种意义上说,这很好,您不必在代理外部公开单个容器。从安全角度来看,这可能更好,因为您不会从您的群中泄露额外的信息。