Docker Net为什么可以获取DMZ区和内网区的主机监控呢?

0 阅读7分钟

在运维工作中,我们经常会遇到这样的场景:Zabbix Server部署在Docker容器中(即Docker Net环境),而需要监控的主机分布在两个不同的网段——DMZ区(比如192.168.0.0/24)和内网区(比如172.16.0.0/24),且内网区主机需要通过运维机的双网卡实现上网。很多同学会有疑问:Docker容器本身处于独立的虚拟网段,为什么能跨网段获取DMZ区和内网区的主机监控数据?这背后其实是Docker网络机制、IP转发和iptables规则三者协同作用的结果,结合我自身的实操环境,今天就把这个问题讲透。

一、先明确我的实际环境

在开始分析前,先交代下我的基础环境,避免抽象理解,所有分析都基于这个真实配置:

image.png

  • 运维机:双网卡配置,分别对应两个网段

    • 网卡1:192.168.0.2/24(对应DMZ区,可直接访问外网)
    • 网卡2:172.16.0.2/24(对应内网区,内网主机的网关)
  • Zabbix Server:部署在Docker容器中,容器IP为172.20.240.2(Docker自定义虚拟网段172.20.0.0/16)

  • 监控目标:

    • DMZ区:192.168.0.0/24网段主机(安装Zabbix Agent)
    • 内网区:172.16.0.0/24网段主机(安装Zabbix Agent,需通过运维机172.16.0.2网关上网)
  • 核心前提:运维机已开启IP转发(net.ipv4.ip_forward = 1),且Docker自动生成了相关iptables规则(无需手动配置)

二、核心疑问拆解:Docker Net为什么能跨网段监控?

很多人困惑的点在于:Docker容器有自己的独立网段(比如我的172.20.0.0/16),和DMZ区、内网区属于不同网段,理论上无法直接通信,为什么能获取到这两个网段的Agent数据?答案很简单:运维机的IP转发+Docker自动生成的iptables规则,打通了Docker Net与DMZ区、内网区的通信链路,相当于给Docker容器搭建了一条“跨网段通道”。

三、关键机制:3个核心组件协同工作

Docker Net能跨网段监控,离不开以下3个核心组件的配合,缺一不可,结合我的实际iptables规则逐一分析:

1. 运维机IP转发(跨网段通信的基础)

IP转发是实现不同网段通信的前提,简单说就是:运维机作为“中转站”,接收一个网段的数据包,转发到另一个网段。在我的环境中,通过以下命令确认IP转发已开启:

sysctl net.ipv4.ip_forward
# 输出:net.ipv4.ip_forward = 1(1表示开启,0表示关闭)

开启IP转发后,运维机才能将DMZ区、内网区的Agent数据,转发到Docker容器所在的虚拟网段;同时也能将Docker容器的监控请求,转发到DMZ区、内网区的Agent主机。

如果IP转发未开启,即使有后续的iptables规则,不同网段之间也无法通信,Docker容器自然无法获取监控数据。

2. Docker自动生成的iptables规则(核心转发逻辑)

这是最关键的一步!很多同学会发现,自己没有手动配置过iptables转发规则,但Docker容器依然能和外部通信,这是因为Docker在启动容器时,会自动在宿主机(运维机)的iptables中添加DNAT(端口转发)和SNAT(地址伪装)规则,无需人工干预。

结合我导出的iptables规则,重点看两个核心规则:

(1)DNAT规则:外部请求转发到Docker容器

# 我的iptables nat表中自动生成的DNAT规则
-A DOCKER ! -i br-47879c6c373a -p tcp -m tcp --dport 10051 -j DNAT --to-destination 172.20.240.2:10051

这条规则的作用的是:所有访问运维机任意网卡IP:10051的数据包,都会被自动转发到Zabbix Server容器的172.20.240.2:10051端口

也就是说,DMZ区的Agent(192.168.0.x)访问192.168.0.2:10051、内网区的Agent(172.16.0.x)访问172.16.0.2:10051,最终都会被转发到Docker容器的172.20.240.2:10051,实现Agent与Zabbix Server的通信。

(2)SNAT/MASQUERADE规则:Docker容器访问外部网段

# 容器网段的地址伪装规则(Docker自动生成)
-A POSTROUTING -s 172.20.0.0/16 ! -o br-47879c6c373a -j MASQUERADE
# 内网区上网的SNAT规则(手动配置,适配内网上网需求)
-A POSTROUTING -s 172.16.0.0/24 -o ens33 -j SNAT --to-source 192.168.0.2

第一条MASQUERADE规则:将Docker容器网段(172.20.0.0/16)的数据包,伪装成运维机的IP地址,这样容器就能访问外部网段(DMZ区、内网区)的Agent主机(10050端口)。

第二条SNAT规则:内网区主机(172.16.0.0/24)的数据包,通过运维机的192.168.0.2网卡出网,同时也能让容器的监控请求,通过这个规则转发到内网区的Agent。

3. Zabbix Agent的正确配置(通信的“最后一公里”)

有了IP转发和iptables规则,还需要Agent配置正确,才能实现双向通信。结合我的双网段环境,Agent的配置核心是“分网段指向运维机对应网卡IP”,而不是直接指向Docker容器IP(172.20.240.2),原因后续会讲。

具体配置如下(最简版,可直接复用):

(1)DMZ区(192.168.0.0/24)Agent配置

Server=192.168.0.2          # 指向运维机DMZ区网卡IP
ServerActive=192.168.0.2    # 主动模式也指向该IP
Hostname=192.168.0.XXX      # 替换为Agent本机IP(与Zabbix前端一致)
ListenPort=10050
ListenIP=0.0.0.0            # 监听所有网卡,允许容器访问
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=0
Timeout=5
UnsafeUserParameters=0

(2)内网区(172.16.0.0/24)Agent配置

Server=172.16.0.2           # 指向运维机内网区网卡IP(网关IP)
ServerActive=172.16.0.2     # 主动模式也指向该IP
Hostname=172.16.0.XXX       # 替换为Agent本机IP(与Zabbix前端一致)
ListenPort=10050
ListenIP=0.0.0.0            # 必须监听所有网卡
LogFile=/var/log/zabbix/zabbix_agentd.log
LogFileSize=0
Timeout=5
UnsafeUserParameters=0

四、关键误区:为什么不直接让Agent指向Docker容器IP?

很多同学会问:既然Zabbix Server在172.20.240.2,为什么不直接让Agent配置Server=172.20.240.2?结合我的环境,答案很明确:不推荐,甚至会导致通信失败,原因有两个:

    1. 网段识别问题:DMZ区、内网区的主机,默认路由指向运维机,本身不认识Docker容器所在的172.20.0.0/16网段,直接访问172.20.240.2会提示“无路由可达”(可通过nc命令测试验证)。
    1. 维护成本高:Docker容器重启后,容器IP可能会变化(比如从172.20.240.2变成172.20.240.4),此时需要批量修改所有Agent的配置,非常繁琐;而指向运维机的固定网卡IP(192.168.0.2/172.16.0.2),即使容器IP变化,Docker会自动更新iptables规则,Agent配置无需改动。

而指向运维机的对应网卡IP,既能利用iptables的DNAT规则自动转发到容器,又能避免网段识别问题,还能降低维护成本,是最优选择。

五、通信链路完整梳理(直观理解)

结合我的环境,用两条链路清晰展示Docker Net如何获取两个网段的监控数据,一看就懂:

链路1:DMZ区Agent → Zabbix Server(Docker容器)

192.168.0.100(Agent) → 访问192.168.0.2:10051 → 运维机iptables DNAT规则转发 → 172.20.240.2:10051(Zabbix Server容器)

链路2:内网区Agent → Zabbix Server(Docker容器)

172.16.0.100(Agent) → 访问172.16.0.2:10051 → 运维机iptables DNAT规则转发 → 172.20.240.2:10051(Zabbix Server容器)

链路3:Zabbix Server → 两个网段Agent(拉取数据)

172.20.240.2(Zabbix Server) → 运维机iptables MASQUERADE规则伪装IP → 转发到192.168.0.100:10050/172.16.0.100:10050 → 获取Agent数据并返回

六、实操验证:如何确认通信正常?

配置完成后,可通过以下命令验证通信是否正常,避免踩坑:

    1. Agent侧验证(测试能否访问Zabbix Server) # DMZ区Agent测试 `` nc -zv 192.168.0.2 10051 `` # 内网区Agent测试 `` nc -zv 172.16.0.2 10051 ``# 输出succeeded!表示通信正常
    1. 容器侧验证(测试能否拉取Agent数据) # 进入Zabbix Server容器 `` docker exec -it zabbix-server bash `` # 测试DMZ区Agent `` zabbix_get -s 192.168.0.100 -p 10050 -k system.uname `` # 测试内网区Agent `` zabbix_get -s 172.16.0.100 -p 10050 -k system.uname ``# 返回系统信息表示正常

这里做一个用于实践一下,证明可行性。 image.png

七、总结:核心逻辑一句话概括

Docker Net之所以能获取DMZ区和内网区的主机监控,本质是:运维机开启IP转发提供跨网段通信基础,Docker自动生成的iptables DNAT/SNAT规则实现“外部请求→容器”和“容器→外部”的转发,再配合Agent分网段指向运维机固定网卡IP,三者协同打通了整个监控通信链路

这种方案的优势在于:无需手动配置复杂的转发规则(Docker自动完成),不影响内网区的上网功能,且维护成本低,非常适合双网段、多网段的运维监控场景。如果你的环境和我类似,直接复用文中的Agent配置和验证方法,就能快速实现跨网段监控。