Docker Overlay 网络的核心工作(以跨节点容器通信为例)

Docker 的 overlay 网络是一种基于 VXLAN(Virtual Extensible LAN)的多主机网络模式,专为 Docker Swarm 集群设计,用于实现跨节点的容器通信。它通过虚拟二层网络,允许容器在不同主机上像在同一局域网内一样通信。Docker 在实现 overlay 网络时,协调用户态(Docker 守护进程、libnetwork)和内核态(Linux 网络栈、VXLAN 模块),完成从网络创建到数据包转发的复杂工作。以下是以 Markdown 格式输出的详细讲解,以两个跨节点容器(例如节点 1 的 gindemo1 和节点 2 的 gindemo2)通信为例,深入分析 Docker 的核心工作,并具体展示路由表和数据包转发流程。


我们假设以下场景:

  • 节点 1 :IP 192.168.1.9,主机名 node01,运行容器 gindemo1(IP: 10.0.1.2)。
  • 节点 2 :IP 192.168.1.10,主机名 node02,运行容器 gindemo2(IP: 10.0.1.6)。
  • 网络my-overlay-network,VNI(VXLAN Network Identifier)为 4097,子网 10.0.1.0/24,网关 10.0.1.1
  • 通信gindemo2(节点 2)访问 gindemo1(节点 1),例如 curl http://gindemo1

Docker 在实现这一通信的过程中,完成了以下核心工作,并涉及具体的路由表配置。

1. 网络创建与配置

Docker 通过 libnetwork 和 Swarm 控制平面创建和管理 overlay 网络。

  • 创建网络

    • 命令:

      bash 复制代码
      docker network create -d overlay --attachable my-overlay-network
    • 工作:

      • 使用 overlay 驱动分配网络 ID 和子网(10.0.1.0/24)。
      • 生成唯一的 VNI(4097),存储在配置中(com.docker.network.driver.overlay.vxlanid_list)。
      • 配置 MTU(默认 1450,适应 VXLAN 50 字节开销)。
      • 设置 attachable: true,允许手动附加容器(避免 not manually attachable 错误)。
  • Swarm 同步

    • 将网络配置(VNI、子网、网关)存储在 Swarm 的分布式键值存储(Raft 协议)。
    • 通过 TCP 2377(Swarm 管理)和 TCP/UDP 7946(gossip 协议)端口,分发到节点 1 和节点 2。
    • 确保节点 2 无需手动创建 my-overlay-network,直接使用集群配置。
  • IPAM(IP 地址管理)

    • 分配子网 10.0.1.0/24,网关 10.0.1.1
    • 为容器动态分配 IP:gindemo110.0.1.2)、gindemo210.0.1.6)。

2. VXLAN 接口与桥接网络初始化

Docker 在每个节点上创建 VXLAN 接口和桥接网络,支持跨节点二层通信。

  • VXLAN 接口

    • 在节点 1 和节点 2 上为 my-overlay-network 创建 VXLAN 接口(例如 vxlan0)。

    • 配置:

      • VNI:4097
      • 目标端口:UDP 4789(VXLAN 默认端口)。
      • 绑定物理网卡:enp0s3(你的节点 2 网卡)。
      • MTU:1450。
    • 示例(节点 2,若接口正常显示):

      bash 复制代码
      ip -d link show vxlan0

      输出:

      复制代码
      10: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
          link/ether 02:42:ac:11:00:06 brd ff:ff:ff:ff:ff:ff
          vxlan id 4097 srcport 0 0 dstport 4789 ...
  • 桥接网络

    • 创建桥接接口(例如 br-xxxx),连接 VXLAN 接口和容器虚拟接口。

    • 示例(节点 2,假设 brctl 已安装):

      bash 复制代码
      brctl show

      输出:

      复制代码
      bridge name     bridge id               STP enabled     interfaces
      br-xxxx         8000.0242ac110006       no              vxlan0
                                                      veth30344ea
      docker_gwbridge 8000.0242bf32025b       no              vetha7fbe75
      • vxlan0:VXLAN 接口,处理跨节点通信。
      • veth30344eagindemo2 的虚拟接口。
      • docker_gwbridge:用于外部网络连接。
  • 你的情况

    • 节点 2 未显示 VXLAN 接口(ip -d link show type vxlan 无输出),但抓包确认 VNI 4097 和通信正常,说明 VXLAN 功能通过内核或其他机制运行。

3. 容器网络命名空间配置

Docker 为每个容器创建独立的网络命名空间,配置 IP、MAC 和路由。

  • 命名空间创建

    • gindemo1gindemo2 创建网络命名空间,隔离网络栈。

    • 示例(节点 2,gindemo2):

      bash 复制代码
      docker inspect gindemo2 | grep -A 5 Network

      输出:

      复制代码
          "Networks": {
              "my-overlay-network": {
                  "IPAddress": "10.0.1.6",
                  "Gateway": "10.0.1.1",
                  "EndpointID": "xxxx",
                  "MacAddress": "02:42:ac:11:00:06"
              }
          }
  • 虚拟接口

    • 创建 veth 接口对:

      • 容器端:eth0(IP: 10.0.1.6,MAC: 02:42:ac:11:00:06)。
      • 主机端:veth30344ea,连接到桥接接口(br-xxxxdocker_gwbridge)。
    • 示例(容器内):

      bash 复制代码
      docker exec -it gindemo2 ip addr

      输出:

      复制代码
      1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
          inet 127.0.0.1/8 scope host lo
      30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450
          inet 10.0.1.6/24 brd 10.0.1.255 scope global eth0
  • 路由表配置

    • Docker 为容器配置路由表,确保数据包通过网关或直接发送到目标。

    • 示例(gindemo2 容器内):

      bash 复制代码
      docker exec -it gindemo2 ip route

      输出:

      复制代码
      default via 10.0.1.1 dev eth0
      10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.6
      • 解释
        • 默认路由:通过网关 10.0.1.1(虚拟网关,由 Docker 实现)。
        • 本地子网:10.0.1.0/24 直接通过 eth0 访问,覆盖 gindemo110.0.1.2)。
  • 主机路由表

    • 主机上为 my-overlay-network 配置路由,确保数据包进入 VXLAN 隧道。

    • 示例(节点 2 主机):

      bash 复制代码
      ip route

      输出:

      复制代码
      default via 192.168.1.1 dev enp0s3
      10.0.1.0/24 dev br-xxxx proto kernel scope link src 10.0.1.1
      192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.10
      • 解释
        • 10.0.1.0/24:通过桥接接口(br-xxxx)访问,网关 10.0.1.1
        • 外部流量通过物理网卡 enp0s3 和默认网关 192.168.1.1

4. DNS 解析与服务发现

Docker 提供内置 DNS 服务,简化容器间通信。

  • DNS 配置

    • Swarm 维护分布式 DNS 记录,将容器名称映射到 IP。
    • 示例:gindemo1 解析为 10.0.1.2gindemo2 解析为 10.0.1.6
    • 配置存储在 Swarm 键值存储中,通过 gossip 协议同步。
  • 通信过程

    • gindemo2 执行 curl http://gindemo1
      • DNS 查询 gindemo1,解析到 10.0.1.2
      • 数据包通过容器路由表发送到 eth0
  • 你的抓包

    • 抓包显示 10.0.1.6gindemo2)访问 10.0.1.2gindemo1)的 websm 端口(80 或 443),DNS 解析正常。

5. VXLAN 数据包封装与转发

Docker 协调内核 VXLAN 模块,完成数据包的封装和跨节点转发。

  • 数据包生成

    • gindemo210.0.1.6)发送 HTTP 请求到 gindemo110.0.1.2)。

    • 容器内路由表:

      复制代码
      10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.6
      • 数据包通过 eth0 发送,目标 IP 10.0.1.2,MAC 未解析(需 ARP)。
  • ARP 解析

    • Docker 通过 Swarm 的 gossip 协议或多播,解析 10.0.1.2 的 MAC(例如 02:42:ac:11:00:02)。

    • FDB 表记录 MAC 到节点映射:

      bash 复制代码
      bridge fdb show dev vxlan0

      输出(节点 2):

      复制代码
      02:42:ac:11:00:02 dst 192.168.1.9 self
      • 表示 gindemo1 的 MAC 映射到节点 1(192.168.1.9)。
  • VXLAN 封装

    • 数据包进入主机桥接接口(br-xxxx),转发到 VXLAN 接口(vxlan0)。

    • 内核 VXLAN 模块封装数据包:

      • 内部帧 :源 10.0.1.6(MAC: 02:42:ac:11:00:06),目标 10.0.1.2(MAC: 02:42:ac:11:00:02)。
      • VXLAN 头 :VNI 4097
      • 外部 UDP :源 192.168.1.10(动态端口,例如 50730),目标 192.168.1.9:4789
      • 外部 IP :源 192.168.1.10,目标 192.168.1.9
    • 你的抓包:

      复制代码
      07:22:12.656724 IP 192.168.1.10.50730 > 192.168.1.9.vxlan: VXLAN, flags [I] (0x08), vni 4097
      IP 10.0.1.6.35126 > 10.0.1.2.websm: Flags [S], seq 2498547307, win 28200, ...
  • 转发

    • 数据包通过物理网卡(enp0s3)发送到节点 1。

    • 主机路由表(节点 2):

      复制代码
      192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.10
      • 目标 192.168.1.9 通过 enp0s3 直接发送。
  • 节点 1 解封装

    • 节点 1 接收 UDP 4789 数据包,VXLAN 接口(vxlan0)解封装。

    • 内部帧转发到 gindemo110.0.1.2)的 eth0

    • 节点 1 路由表(容器内):

      复制代码
      default via 10.0.1.1 dev eth0
      10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.2

6. iptables 和外部连接

Docker 配置 iptables,支持容器与外部网络的通信。

  • NAT 配置

    • 为端口映射(例如 -p 8081:80)配置 iptablesnat 表(DOCKER 链)。

    • 示例(节点 2):

      bash 复制代码
      sudo iptables -t nat -L DOCKER

      输出:

      复制代码
      Chain DOCKER (2 references)
      target     prot opt source               destination
      DNAT       tcp  --  anywhere             0.0.0.0/0            tcp dpt:8081 to:10.0.1.6:80
  • docker_gwbridge

    • 连接容器到外部网络,处理外部访问(例如通过 192.168.1.10:8081 访问 gindemo2)。

    • 你的输出:

      复制代码
      10: docker_gwbridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
          link/ether 02:42:bf:32:02:5b ...
      24: vetha7fbe75@if23: ... master docker_gwbridge ...
      31: veth30344ea@if30: ... master docker_gwbridge ...
  • 防火墙

    • 确保 UDP 4789(VXLAN)、TCP 2377(Swarm 管理)、TCP/UDP 7946(gossip)端口开放。

    • 示例:

      bash 复制代码
      sudo ufw allow 4789/udp

7. Swarm 控制平面管理

Docker Swarm 提供分布式管理,确保 overlay 网络跨节点一致。

  • 网络同步

    • 通过 Raft 协议存储网络配置(VNI、子网、FDB)。
    • 节点 2 无需手动创建 my-overlay-network,Swarm 自动分发。
  • 服务发现

    • Swarm 维护 DNS 记录,动态更新容器 IP 和名称。
    • 示例:gindemo2 查询 gindemo1,返回 10.0.1.2
  • 故障处理

    • 检测节点状态(docker node ls),重新同步配置。
    • 你的问题(节点 2 无 VXLAN 接口)可能因同步或内核问题,Docker 仍通过其他机制维持通信。

8. 性能优化

Docker 优化 overlay 网络的性能。

  • 内核 VXLAN

    • 使用 Linux 内核的 VXLAN 模块,高效处理封装。
    • 支持网卡硬件卸载(如果支持)。
  • 多播/单播

    • 默认使用多播分发 ARP,动态切换到单播(你的环境中可能为单播)。

    • FDB 表动态更新:

      复制代码
      02:42:ac:11:00:02 dst 192.168.1.9 self
  • MTU

    • 设置 MTU 1450,适应 VXLAN 封装。
    • 你的抓包显示 mss 1410,确认 MTU 正确。

9. 调试与监控

Docker 提供工具支持 overlay 网络调试。

  • 网络检查

    • docker network inspect my-overlay-network:显示 VNI(4097)、子网、容器 IP。
    • docker inspect gindemo2:确认 IP 和 MAC。
  • 抓包

    • 你的抓包:

      复制代码
      IP 192.168.1.10.50730 > 192.168.1.9.vxlan: VXLAN, flags [I] (0x08), vni 4097
      • 验证 VNI 和通信。
  • 日志

    • journalctl -u docker:记录网络错误。

10. 异常处理

Docker 处理 overlay 网络的异常情况。

  • 你的问题(节点 2 无 VXLAN 接口)

    • 可能原因:VXLAN 模块未加载(modprobe vxlan)、iproute2 过旧、Docker 网络栈异常。
    • Docker 仍通过内核直接处理 VXLAN 流量(抓包确认),但接口未显示。
  • 解决方案

    • 加载 VXLAN 模块:

      bash 复制代码
      sudo modprobe vxlan
    • 更新 iproute2

      bash 复制代码
      sudo yum update iproute
    • 重启 Docker:

      bash 复制代码
      systemctl restart docker

具体路由表和数据包流程

以下是 gindemo2(节点 2,10.0.1.6)访问 gindemo1(节点 1,10.0.1.2)的详细流程,包含路由表。

1. gindemo2 容器(节点 2)

  • 路由表

    bash 复制代码
    docker exec -it gindemo2 ip route
    复制代码
    default via 10.0.1.1 dev eth0
    10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.6
  • 流程

    • curl http://gindemo1 解析为 10.0.1.2(Swarm DNS)。
    • 数据包:源 10.0.1.6:35126,目标 10.0.1.2:80(HTTP)。
    • 路由匹配 10.0.1.0/24,通过 eth0 发送。
    • ARP 请求 10.0.1.2 的 MAC,解析为 02:42:ac:11:00:02

2. 节点 2 主机

  • 路由表

    bash 复制代码
    ip route
    复制代码
    default via 192.168.1.1 dev enp0s3
    10.0.1.0/24 dev br-xxxx proto kernel scope link src 10.0.1.1
    192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.10
  • FDB 表

    bash 复制代码
    bridge fdb show dev vxlan0
    复制代码
    02:42:ac:11:00:02 dst 192.168.1.9 self
  • 流程

    • 数据包从 veth30344ea 进入桥接接口(br-xxxx)。
    • VXLAN 接口(vxlan0,若存在)封装数据包:
      • 内部:源 10.0.1.6(MAC: 02:42:ac:11:00:06),目标 10.0.1.2(MAC: 02:42:ac:11:00:02)。
      • 外部:源 192.168.1.10:50730,目标 192.168.1.9:4789,VNI 4097
    • 路由匹配 192.168.1.0/24,通过 enp0s3 发送。

3. 节点 1 主机

  • 路由表

    bash 复制代码
    ip route
    复制代码
    default via 192.168.1.1 dev enp0s3
    10.0.1.0/24 dev br-yyyy proto kernel scope link src 10.0.1.1
    192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.9
  • 流程

    • 接收 UDP 4789 数据包,VXLAN 接口解封装。
    • 内部帧转发到桥接接口(br-yyyy),匹配 10.0.1.2
    • 数据包通过 veth 接口送达 gindemo1eth0

4. gindemo1 容器(节点 1)

  • 路由表

    bash 复制代码
    docker exec -it gindemo1 ip route
    复制代码
    default via 10.0.1.1 dev eth0
    10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.2
  • 流程

    • 接收数据包,处理 HTTP 请求。
    • 响应通过相同路径返回(反向封装,VXLAN 到节点 2)。

总结

Docker 在 overlay 网络中完成以下核心工作:

  1. 网络创建 :分配 VNI(4097)、子网(10.0.1.0/24),通过 Swarm 同步。
  2. VXLAN 初始化 :创建 VXLAN 接口(vxlan0)、桥接接口(br-xxxx)。
  3. 容器配置 :分配 IP(10.0.1.2, 10.0.1.6)、MAC,配置路由表和 veth 接口。
  4. DNS 解析 :提供 Swarm DNS,解析 gindemo110.0.1.2
  5. 数据封装 :封装 VXLAN 数据包(外部: 192.168.1.10192.168.1.9,VNI 4097),维护 FDB。
  6. iptables :配置 NAT 和端口映射,连接 docker_gwbridge
  7. Swarm 管理:分布式同步,故障恢复。
  8. 优化与调试:内核 VXLAN、MTU 1450、抓包支持。
相关推荐
xier_ran21 分钟前
【infra之路】GPU 存储层次总结:L1 / L2 / HBM
java·网络·数据库
小网洞1 小时前
免费WPA无线握手包在线分析跑包网站
网络·网络安全·密码学·wps
FoldWinCard1 小时前
K8s集群部署的方法原理
大数据·容器·kubernetes
@insist1233 小时前
系统集成项目管理工程师-信息和文档管理
网络·数据库·软考·系统集成项目管理工程师·软考中项·软件水平考试
极客互动API3 小时前
企业微信 iPad 协议服务搭建与 AI 回调实战
网络·汇编·人工智能·微信·企业微信·ipad
QH139292318803 小时前
Keysight N5183B N5183B 微波模拟信号发生器
网络·单片机·嵌入式硬件·集成测试·信息与通信
LabVIEW开发3 小时前
基于原始套接字实现LabVIEW网络Ping检测的编程方法
网络·labview·labview知识·labview功能·labview程序
东莞和裕包装3 小时前
如何管控广州定制纸箱生产中的啤切精度与印刷色差质量问题
大数据·运维·网络·人工智能
二宝哥4 小时前
docker安装apisix
docker·容器·apisix
Zguigo5 小时前
lesson19-23计算机网络数据链路层完全指南:从帧封装到滑动窗口协议
网络·计算机网络