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

打印 上一主题 下一主题

主题 1950|帖子 1950|积分 5860

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

x
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 网络。


  • 创建网络

    • 下令:
      1. 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:gindemo1(10.0.1.2)、gindemo2(10.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,若接口正常表现):
      1. ip -d link show vxlan0
      复制代码
      输出:
      1. 10: vxlan0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450 qdisc noqueue state UNKNOWN mode DEFAULT group default
      2.     link/ether 02:42:ac:11:00:06 brd ff:ff:ff:ff:ff:ff
      3.     vxlan id 4097 srcport 0 0 dstport 4789 ...
      复制代码

  • 桥接网络

    • 创建桥接接口(例如 br-xxxx),连接 VXLAN 接口和容器虚拟接口。
    • 示例(节点 2,假设 brctl 已安装):
      1. brctl show
      复制代码
      输出:
      1. bridge name     bridge id               STP enabled     interfaces
      2. br-xxxx         8000.0242ac110006       no              vxlan0
      3.                                                 veth30344ea
      4. docker_gwbridge 8000.0242bf32025b       no              vetha7fbe75
      复制代码

      • vxlan0:VXLAN 接口,处理跨节点通讯。
      • veth30344ea:gindemo2 的虚拟接口。
      • docker_gwbridge:用于外部网络连接。


  • 你的情况

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

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

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


  • 定名空间创建

    • 为 gindemo1 和 gindemo2 创建网络定名空间,隔离网络栈。
    • 示例(节点 2,gindemo2):
      1. docker inspect gindemo2 | grep -A 5 Network
      复制代码
      输出:
      1.     "Networks": {
      2.         "my-overlay-network": {
      3.             "IPAddress": "10.0.1.6",
      4.             "Gateway": "10.0.1.1",
      5.             "EndpointID": "xxxx",
      6.             "MacAddress": "02:42:ac:11:00:06"
      7.         }
      8.     }
      复制代码

  • 虚拟接口

    • 创建 veth 接口对:

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

    • 示例(容器内):
      1. docker exec -it gindemo2 ip addr
      复制代码
      输出:
      1. 1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536
      2.     inet 127.0.0.1/8 scope host lo
      3. 30: eth0@if31: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1450
      4.     inet 10.0.1.6/24 brd 10.0.1.255 scope global eth0
      复制代码

  • 路由表配置

    • Docker 为容器配置路由表,确保数据包通过网关或直接发送到目标。
    • 示例(gindemo2 容器内):
      1. docker exec -it gindemo2 ip route
      复制代码
      输出:
      1. default via 10.0.1.1 dev eth0
      2. 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 访问,覆盖 gindemo1(10.0.1.2)。



  • 主机路由表

    • 主机上为 my-overlay-network 配置路由,确保数据包进入 VXLAN 隧道。
    • 示例(节点 2 主机):
      1. ip route
      复制代码
      输出:
      1. default via 192.168.1.1 dev enp0s3
      2. 10.0.1.0/24 dev br-xxxx proto kernel scope link src 10.0.1.1
      3. 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.2,gindemo2 解析为 10.0.1.6。
    • 配置存储在 Swarm 键值存储中,通过 gossip 协议同步。

  • 通讯过程

    • gindemo2 实行 curl http://gindemo1:

      • DNS 查询 gindemo1,解析到 10.0.1.2。
      • 数据包通过容器路由表发送到 eth0。


  • 你的抓包

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

5. VXLAN 数据包封装与转发

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


  • 数据包生成

    • gindemo2(10.0.1.6)发送 HTTP 哀求到 gindemo1(10.0.1.2)。
    • 容器内路由表:
      1. 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 到节点映射:
      1. bridge fdb show dev vxlan0
      复制代码
      输出(节点 2):
      1. 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。

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

  • 转发

    • 数据包通过物理网卡(enp0s3)发送到节点 1。
    • 主机路由表(节点 2):
      1. 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)解封装。
    • 内部帧转发到 gindemo1(10.0.1.2)的 eth0。
    • 节点 1 路由表(容器内):
      1. default via 10.0.1.1 dev eth0
      2. 10.0.1.0/24 dev eth0 proto kernel scope link src 10.0.1.2
      复制代码

6. iptables 和外部连接

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


  • NAT 配置

    • 为端口映射(例如 -p 8081:80)配置 iptables 的 nat 表(DOCKER 链)。
    • 示例(节点 2):
      1. sudo iptables -t nat -L DOCKER
      复制代码
      输出:
      1. Chain DOCKER (2 references)
      2. target     prot opt source               destination
      3. 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)。
    • 你的输出:
      1. 10: docker_gwbridge: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 ...
      2.     link/ether 02:42:bf:32:02:5b ...
      3. 24: vetha7fbe75@if23: ... master docker_gwbridge ...
      4. 31: veth30344ea@if30: ... master docker_gwbridge ...
      复制代码

  • 防火墙

    • 确保 UDP 4789(VXLAN)、TCP 2377(Swarm 管理)、TCP/UDP 7946(gossip)端口开放。
    • 示例:
      1. 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 表动态更新:
      1. 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。

  • 抓包

    • 你的抓包:
      1. 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 模块:
      1. sudo modprobe vxlan
      复制代码
    • 更新 iproute2:
      1. sudo yum update iproute
      复制代码
    • 重启 Docker:
      1. systemctl restart docker
      复制代码


详细路由表和数据包流程

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



  • 路由表
    1. docker exec -it gindemo2 ip route
    复制代码
    1. default via 10.0.1.1 dev eth0
    2. 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 主机



  • 路由表
    1. ip route
    复制代码
    1. default via 192.168.1.1 dev enp0s3
    2. 10.0.1.0/24 dev br-xxxx proto kernel scope link src 10.0.1.1
    3. 192.168.1.0/24 dev enp0s3 proto kernel scope link src 192.168.1.10
    复制代码
  • FDB 表
    1. bridge fdb show dev vxlan0
    复制代码
    1. 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 主机



  • 路由表
    1. ip route
    复制代码
    1. default via 192.168.1.1 dev enp0s3
    2. 10.0.1.0/24 dev br-yyyy proto kernel scope link src 10.0.1.1
    3. 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 接口送达 gindemo1 的 eth0。

4. gindemo1 容器(节点 1)



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

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


总结

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

  • 网络创建:分配 VNI(4097)、子网(10.0.1.0/24),通过 Swarm 同步。
  • VXLAN 初始化:创建 VXLAN 接口(vxlan0)、桥接接口(br-xxxx)。
  • 容器配置:分配 IP(10.0.1.2, 10.0.1.6)、MAC,配置路由表和 veth 接口。
  • DNS 解析:提供 Swarm DNS,解析 gindemo1 到 10.0.1.2。
  • 数据封装:封装 VXLAN 数据包(外部: 192.168.1.10 到 192.168.1.9,VNI 4097),维护 FDB。
  • iptables:配置 NAT 和端口映射,连接 docker_gwbridge。
  • Swarm 管理:分布式同步,故障规复。
  • 优化与调试:内核 VXLAN、MTU 1450、抓包支持。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

宁睿

论坛元老
这个人很懒什么都没写!
快速回复 返回顶部 返回列表