从容器内部抓取 docker 指标 配置从容器内部启动 Socat 容器curl Container 发布的端口连接挂了防火墙

问题描述

我正在尝试从容器内刮取 docker metrics。我见过普罗米修斯的创造者这样做see video here。我无法重现它。

配置

我已经通过 json 配置公开了 docker 指标页面

{
  "metrics-addr" : "172.17.0.1:4999","experimental" : true
}

我也尝试过 0.0.0.0。在任何情况下,我都可以毫无问题地从主机本身卷曲。

$ curl 172.17.0.1:4999/metrics | more

  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0# HELP builder_builds_Failed_total Number of Failed image builds
# TYPE builder_builds_Failed_total counter
builder_builds_Failed_total{reason="build_canceled"} 0
builder_builds_Failed_total{reason="build_target_not_reachable_error"} 0
...

从容器内部

但是,我无法从容器内部获取相同的指标页面。我曾尝试 basi/socat 图像,与视频中的图像相同。我还尝试了一些其他方法,例如从容器内部使用 curl 等等。

图像基本上只做一件事

ENV IN="172.17.0.1:4999" \
    OUT="4999"

ENTRYPOINT socat -d -d TCP-L:$OUT,fork TCP:$IN

启动 Socat 容器

docker run --rm -p 4998:4999 basi/socat
2021/04/02 16:27:47 socat[8] N listening on AF=2 0.0.0.0:4999

curl Container 发布的端口

curl localhost:4998/metrics

连接挂了

socat 图像识别出连接,但它挂起 1-2 分钟并超时。

2021/04/02 16:29:53 socat[8] N accepting connection from AF=2 172.17.0.1:57678 on AF=2 172.17.0.2:4999
2021/04/02 16:29:53 socat[8] N forked off child process 9
2021/04/02 16:29:53 socat[8] N listening on AF=2 0.0.0.0:4999
2021/04/02 16:29:53 socat[9] N opening connection to AF=2 172.17.0.1:4999
2021/04/02 16:32:04 socat[9] E connect(5,AF=2 172.17.0.1:4999,16): Operation timed out
2021/04/02 16:32:04 socat[9] N exit(1)
2021/04/02 16:32:04 socat[8] N childdied(): handling signal 17
2021/04/02 16:32:04 socat[8] W waitpid(): child 9 exited with status 1
curl: (52) Empty reply from server

防火墙

我慢慢地想知道它是否会出现在我的 iptables 规则中。我已在 INPUTDOCKER-USER 链下方张贴。只有这些是我自己改变的。

sudo iptables -L -n -v
Chain INPUT (policy DROP 32060 packets,1810K bytes)
 pkts bytes target     prot opt in     out     source               destination         
 716K 1484M ACCEPT     all  --  lo     *       0.0.0.0/0            0.0.0.0/0           
 599K 1069M ACCEPT     all  --  *      *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED

Chain DOCKER-USER (1 references)
 pkts bytes target     prot opt in     out     source               destination         
   16  3138 ACCEPT     all  --  eth0   *       0.0.0.0/0            0.0.0.0/0            ctstate RELATED,ESTABLISHED
   12   624 DROP       all  --  eth0   *       0.0.0.0/0            0.0.0.0/0           
74921  139M RETURN     all  --  *      *       0.0.0.0/0            0.0.0.0/0           

解决方法

事实证明问题确实出在 iptables 上。在这种情况下,INPUT 链的默认策略是 DROP。由于容器现在正在尝试到达主机系统本身,因此其流量将通过输入链。

所以我现在添加了 2 个简单的规则,这将允许来自 INPUTdocker0docker_gwbridge 链中的所有流量。

sudo iptables -A INPUT -i docker0 -j ACCEPT
sudo iptables -A INPUT -i docker_gwbridge -j ACCEPT

之后,我终于可以从容器内部查询 docker 指标了。

docker run --rm curlimages/curl -I -m 10 172.17.0.1:4999/metrics
HTTP/1.1 200 OK
Content-Type: text/plain; version=0.0.4; charset=utf-8
Date: Sat,03 Apr 2021 10:53:12 GMT