ITPub博客

首页 > 数据库 > MySQL > Docker网桥模式跨机访问MySQL的IP幻觉:一次主从切换踩坑实录

Docker网桥模式跨机访问MySQL的IP幻觉:一次主从切换踩坑实录

原创 MySQL 作者:贺子_DBA时代 时间:2026-08-24 23:43:06 0 删除 编辑
【实战排错】Docker网桥诡异网络问题:MySQL VIP漂移后容器突然无法连接数据库 本文适用场景:Docker默认bridge网桥、数据库VIP主从漂移、MySQL白名单鉴权失败、容器跨主机网络异常 故障特征:业务零配置变更,仅MySQL VIP发生主机漂移,Docker容器访问数据库从正常变为权限拒绝,物理机访问完全正常。

一、故障环境与问题现象

1.1 现场基础环境

MySQL服务节点(宿主机A,MySQL 旧主库):10.2.17.1

Docker业务节点(宿主机B,MySQL新主库):10.2.17.2   (部署了docker网桥方式的服务,估计是考虑到节约资源)

容器网络模式:Docker默认docker0网桥(容器内网段 172.17.0.0/16)

MySQL权限策略:账号白名单仅放行 10.2.17.% 物理网段,未配置容器私有网段权限

1.2 故障复现过程

VIP切换前(正常):MySQL业务VIP绑定在Docker宿主机A,容器访问数据库正常,业务无报错;

VIP切换后(异常):MySQL VIP漂移至宿主机B, 同一容器、同一数据库连接地址、无任何业务配置修改,数据库连接提示IP无访问权限。报错信息: Access denied for user 'app_user'@'172.17.0.12' (using password: YES)

1.3 初步排查结论

排除代码、账号密码、端口、防火墙、数据库配置问题,唯一变量为 MySQL VIP归属主机发生迁移,故障根因为Docker默认网桥差异化SNAT转发机制。

二、故障根因:Docker0网桥的双重网络特性

这是运维、开发极易踩坑的Docker经典隐性问题: 多数人默认容器出站IP固定为172.17.0.x内网IP,实际Docker网桥流量IP动态变化。Docker0网桥核心核心机制: 访问本机服务不SNAT,访问跨机服务必SNAT。容器对外访问的源IP,不由容器自身决定,而是由 访问目标是否为宿主机本地服务决定,两种场景流量转发逻辑完全不同。

三、两种流量场景全网路拆解

3.1 正常场景:VIP在宿主机A,宿主机B容器访问跨机MySQL

VIP在宿主机A(10.2.17.1)后,容器访问为 跨主机物理网络流量。 流量路径:容器(172.17.0.x) → docker0网桥 → 宿主机B上eth0物理网卡 → 物理交换机 → 远端宿主机A的MySQL(10.2.17.1) 流量特征:
  • 流量必须经过物理网卡与物理网络设备,属于跨主机外网流量;
  • 强制触发Docker SNAT地址伪装,容器172内网IP被完全屏蔽;
  • MySQL溯源IP变为 Docker宿主机物理IP 10.2.17.2。
  • MySQL白名单为10.2.17.%,覆盖宿主机B的ip,可以正常登录

3.1 异常场景:VIP本地绑定,容器访问本机MySQL

VIP漂移后,MySQL VIP属于宿主机B本地IP,宿主机B上的容器访问属于 本机内网流量。 流量路径:容器(172.17.0.x) → docker0网桥 → 内核本地转发 → 宿主机B的MySQL 流量特征:
  • 流量全程在内核网络栈闭环, 不经过物理网卡eth0、不经过物理交换机;
  • 不触发Docker SNAT伪装规则, 保留容器真实172.17.0.x私有IP;
  • MySQL日志溯源客户端IP为容器内网IP(172.17.0.%)。
  • MySQL白名单为10.2.17.%,未覆盖宿主机B的容器内网ip,拒绝登录。
故障直接原因:Linux内核识别访问目标为本地接口IP(本机物理IP、回环IP、网桥网关IP),判定为本地流量,自动跳过NAT转发,直接本地路由闭环。MySQL白名单为10.2.17.%,未覆盖宿主机B的容器内网ip,拒绝登录,报错

四、Docker SNAT核心规则详解

上述差异化转发,由Docker默认自动生成的iptables NAT规则控制,属于标准设计而非BUG:iptables -t nat -A POSTROUTING -s 172.17.0.0/16 ! -o docker0 -j MASQUERADE 规则解析:
  • 源网段:172.17.0.0/16(Docker默认容器网段);
  • 匹配条件:出站网卡非docker0(即跨本机、走物理网卡出站);
  • 执行动作:MASQUERADE地址伪装,替换为宿主机物理IP。
设计初衷:172私有网段无法在企业物理局域网路由互通,通过SNAT伪装,解决容器跨主机网络访问问题,同时跨主机访问MySQL识别到的客户端ip为宿主机的IP。但是如果是本宿主机访问容器访问本宿主机上的MySQL,流量全程在内核网络栈闭环, 不经过物理网卡eth0、不经过物理交换机,数据库探测到客户端的IP就变成了容器ip。    

五、生产落地修复方案(优先级排序)

方案一:MySQL白名单补充授权(应急首选)

快速授权宿主机B的容器Docker网段白名单,秒级恢复业务,适合紧急故障处理:GRANT ALL ON 数据库名.* TO '业务账号'@'172.17.0.%'; 优缺点:操作简单、见效快;多节点Docker集群需逐台授权,运维繁琐。

方案二:容器使用Host网络模式(根治单节点)

容器启动增加 --net=host 参数,复用宿主机网络栈,容器所有对外流量统一使用宿主机物理IP, 彻底消除SNAT动态IP问题。 优缺点:网络稳定、规避所有网桥SNAT坑;牺牲网络隔离性,容器端口与宿主机端口不可冲突。

六、生产避坑总结

1、 破除固定认知:Docker默认网桥下,容器出站IP不固定,本机访问用容器内网IP,跨机访问自动SNAT为宿主机IP;2、 重点关注服务漂移场景:数据库VIP漂移、服务迁移、主从切换,是该类无配置变更网络故障的高频触发点;3、 权限策略适配Docker特性:Docker集群环境中,数据库白名单优先授权宿主机物理网段,不建议授权容器私有网段,规避SNAT导致的鉴权失效问题。4、 坚守dba规范:强烈建议数据库和部署服务的服务器分开,保证docker服务访问数据库是异机访问,这样只需授权宿主机IP即可。


来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29654823/viewspace-3180512/ ,如需转载,请注明出处,否则将追究法律责任。

下一篇: 没有了~
请登录后发表评论 登录
全部评论
10年数据库管理员从业经历,熟悉Oracle、mysql、tidb、oceanbase、redis、 mongodb 、python等技术栈,持有11g ocm 、mysql 5.7 ocp 、tidb 5.0 ptcp、tidb 6.0 ptca、oceanbase obcp等

注册时间:2014-05-12

  • 博文量
    327
  • 访问量
    2148906