K8s 节点 Docker 网段与外部数据库 IP 冲突

问题现象

K8s 部署环境无法连接外部 Oracle 数据库:

数据库:172.17.179.4:1521
现象:应用提示“无法连接数据源”

根本原因

每个 K8s 节点都存在 Docker 默认路由:

172.17.0.0/16 dev docker0

目标数据库 172.17.179.4 属于 172.17.0.0/16

因此,Linux 根据最长前缀匹配,将数据库流量发给了本机 docker0,而不是通过默认网关 192.168.103.1 发往外部网络:

# 修复前
172.17.179.4 dev docker0 src 172.17.0.1

这属于网络路由冲突,与数据库账号、Oracle JDBC、前端代码和域名无关。即使改用域名,只要域名仍解析到该 IP,问题依然存在。

临时解决方案

在每个可能运行相关服务的 K8s 节点上,为数据库 IP 增加一条 /32 主机路由:

ip route replace 172.17.179.4/32 via 192.168.103.1 dev eth0

验证:

ip route get 172.17.179.4

正确结果类似:

172.17.179.4 via 192.168.103.1 dev eth0 src 192.168.103.101

/32 路由比 Docker 的 /16 路由更精确,因此只有访问 172.17.179.4 的流量改走外部网关,不影响其他 Docker、K8s 和默认路由。

永久生效

先查询 eth0 对应的 NetworkManager 连接名:

nmcli -t -f NAME,DEVICE connection show --active | grep ':eth0$'

不同节点的连接名可能不同,例如:

Wired connection 1:eth0

或者:

eth0:eth0

使用实际查询到的连接名保存路由:

nmcli connection modify "Wired connection 1" +ipv4.routes "172.17.179.4/32 192.168.103.1"

如果连接名是 eth0

nmcli connection modify "eth0" +ipv4.routes "172.17.179.4/32 192.168.103.1"

验证持久化配置:

nmcli -f ipv4.routes connection show "实际连接名"

预期结果:

{ ip = 172.17.179.4/32, nh = 192.168.103.1 }

连通性验证

nc -vz -w 5 172.17.179.4 1521

如果没有安装 nc

timeout 5 bash -c '</dev/tcp/172.17.179.4/1521' \
  && echo "1521端口连通" \
  || echo "1521端口不通"

回滚方式

删除当前运行时路由:

ip route del 172.17.179.4/32

删除 NetworkManager 中的持久化配置:

nmcli connection modify "实际连接名" -ipv4.routes "172.17.179.4/32 192.168.103.1"

关键知识点

  • Linux 路由遵循“最长前缀优先”,/32 优先于 /16
  • K8s Pod 网段和 Docker 默认网桥不是一回事。本环境 Pod 使用 10.244.0.0/16,冲突的是节点上的 docker0
  • 不要因为该问题直接修改或重启 Docker 网络,否则可能影响整个 K8s 节点。
  • 多节点集群应在所有可能调度相关服务的节点上配置路由,避免 Pod 漂移后问题复发。
  • /32 主机路由适合解决单个目标 IP 的冲突,影响范围小、风险低、容易回滚。
  • 长期方案是统一规划容器网段、内部网络和云端网络,避免地址段重叠。
posted @ 2026-09-08 14:26  zjb480  阅读(5)  评论(0)    收藏  举报